first commit

This commit is contained in:
2025-09-22 23:12:44 +02:00
commit 1bc83085c6
36 changed files with 409 additions and 0 deletions

18
LICENSE Normal file
View File

@@ -0,0 +1,18 @@
MIT License
Copyright (c) 2025 Andreas Schulte
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.

56
README.md Normal file
View File

@@ -0,0 +1,56 @@
# Boot-to-Firefox (Minimal Arch Linux Live System)
This repository is a **proof-of-work** project — more of a "I always wanted to try this" kind of thing.
The goal is to demonstrate how one can reproducibly build a **minimal live system** based on **Arch Linux** and its **LTS kernel**.
Once booted, the system skips the usual bells and whistles and goes straight into a graphical environment where the only real application of interest is: **Firefox**.
## Why?
In the age of increasingly complex software stacks, this project explores the opposite philosophy:
a lean, hardened live system that is **ephemeral by design**.
- **No persistence**: Each boot is a clean slate.
- **Up-to-date**: Rebuild, PXE-boot, and users always start with the latest packages.
- **Reduced attack surface**: Minimal packages, minimal services, minimal surprises.
- **Reproducible**: The build pipeline ensures you know exactly what goes into the image.
This makes it a neat candidate for:
- **PXE deployments** in organizations where users only need a browser.
- **Security-conscious environments** where diskless, hardened endpoints reduce risks.
- **Training & demonstrations** where reproducible minimalism is key.
## Features
- Boots directly into **Firefox** under a Wayland compositor (Hyprland).
- Uses **Arch Linux LTS kernel** for stability.
- Automatically sets a **random root password** on each boot.
- Automatically sets a **random hostname** on each boot.
- Boots fast and quietly — no cluttered boot messages, no menu prompts.
- Network connectivity via DHCP out-of-the-box.
## Future Directions
- Integrating **pre-configured Firefox policies** (bookmarks, addons, homepage).
- Providing optional **Waybar** or minimal panels for usability.
- Exploring additional **hardening mechanisms** (AppArmor, sandboxing, etc.).
## Disclaimer
This project is for **educational and demonstration purposes only**.
Do not rely on it as-is for production use — but do feel free to tinker, adapt, and extend.
## Build it
Building requires an Arch Linux system with the `archiso` package installed.
```bash
./build.sh
```
# Resources
- https://wiki.archlinux.org/title/Archiso
- https://gitlab.archlinux.org/archlinux/archiso/-/blob/master/docs/README.profile.rst
- https://github.com/archlinux/archiso/blob/master/configs/releng/profiledef.sh

16
build.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
PROFILEPATH="$(realpath "$(dirname "$0")/profiles/boot-to-firefox")"
IMAGEPATH="/tmp/boot-to-firefox"
WORKPATH="$IMAGEPATH/work"
OUTPATH="$IMAGEPATH/out"
if [ -d "$IMAGEPATH" ]; then
sudo rm -R "$IMAGEPATH"
fi
mkdir -p "$WORKPATH"
mkdir -p "$OUTPATH"
sudo mkarchiso -v -w "$WORKPATH" -o "$OUTPATH" "$PROFILEPATH"

View File

@@ -0,0 +1,5 @@
root:x:0:root
adm:x:4:liveuser
wheel:x:10:liveuser
uucp:x:14:liveuser
liveuser:x:1000:liveuser

View File

@@ -0,0 +1,3 @@
root:!*::root
liveuser:!*::

View File

@@ -0,0 +1 @@
boot-to-firefox

View File

@@ -0,0 +1 @@
LANG=de_DE.utf8

View File

@@ -0,0 +1 @@
/usr/share/zoneinfo/Europe/Berlin

View File

@@ -0,0 +1,3 @@
HOOKS=(base udev microcode modconf kms memdisk archiso archiso_loop_mnt archiso_pxe_common archiso_pxe_nbd archiso_pxe_http archiso_pxe_nfs block filesystems keymap keyboard plymouth)
COMPRESSION="xz"
COMPRESSION_OPTIONS=(-9e)

View File

@@ -0,0 +1,8 @@
# mkinitcpio preset file for the 'linux' package on archiso
PRESETS=('archiso')
ALL_kver='/boot/vmlinuz-linux-lts'
archiso_config='/etc/mkinitcpio.conf.d/archiso.conf'
archiso_image="/boot/initramfs-linux-lts.img"

View File

@@ -0,0 +1,97 @@
#
# /etc/pacman.conf
#
# See the pacman.conf(5) manpage for option and repository directives
#
# GENERAL OPTIONS
#
[options]
# The following paths are commented out with their default values listed.
# If you wish to use different paths, uncomment and update the paths.
#RootDir = /
#DBPath = /var/lib/pacman/
#CacheDir = /var/cache/pacman/pkg/
#LogFile = /var/log/pacman.log
#GPGDir = /etc/pacman.d/gnupg/
#HookDir = /etc/pacman.d/hooks/
HoldPkg = pacman glibc
#XferCommand = /usr/bin/curl -L -C - -f -o %o %u
#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u
#CleanMethod = KeepInstalled
Architecture = auto
# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
#IgnorePkg =
#IgnoreGroup =
#NoUpgrade =
#NoExtract =
# Misc options
#UseSyslog
#Color
#NoProgressBar
CheckSpace
#VerbosePkgLists
#ParallelDownloads = 5
# By default, pacman accepts packages signed by keys that its local keyring
# trusts (see pacman-key and its man page), as well as unsigned packages.
SigLevel = Required DatabaseOptional
LocalFileSigLevel = Optional
#RemoteFileSigLevel = Required
# NOTE: You must run `pacman-key --init` before first using pacman; the local
# keyring can then be populated with the keys of all official Arch Linux
# packagers with `pacman-key --populate archlinux`.
#
# REPOSITORIES
# - can be defined here or included from another file
# - pacman will search repositories in the order defined here
# - local/custom mirrors can be added here or in separate files
# - repositories listed first will take precedence when packages
# have identical names, regardless of version number
# - URLs will have $repo replaced by the name of the current repo
# - URLs will have $arch replaced by the name of the architecture
#
# Repository entries are of the format:
# [repo-name]
# Server = ServerName
# Include = IncludePath
#
# The header [repo-name] is crucial - it must be present and
# uncommented to enable the repo.
#
# The testing repositories are disabled by default. To enable, uncomment the
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
#[core-testing]
#Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
#[extra-testing]
#Include = /etc/pacman.d/mirrorlist
[extra]
Include = /etc/pacman.d/mirrorlist
# If you want to run 32 bit applications on your x86_64 system,
# enable the multilib repositories as required here.
#[multilib-testing]
#Include = /etc/pacman.d/mirrorlist
[multilib]
Include = /etc/pacman.d/mirrorlist
# An example of a custom package repository. See the pacman manpage for
# tips on creating your own repositories.
#[custom]
#SigLevel = Optional TrustAll
#Server = file:///home/custompkgs

View File

@@ -0,0 +1,2 @@
root:x:0:0:root:/root:/usr/bin/bash
liveuser:x:1000:1000::/home/liveuser:/usr/bin/bash

View File

@@ -0,0 +1,2 @@
[Daemon]
Theme=bgrt

View File

@@ -0,0 +1,2 @@
root::14871::::::
liveuser::14871::::::

View File

@@ -0,0 +1,4 @@
[Login]
HandleSuspendKey=ignore
HandleHibernateKey=ignore
HandleLidSwitch=ignore

View File

@@ -0,0 +1,24 @@
[Match]
# Matching with "Type=ether" causes issues with containers because it also matches virtual Ethernet interfaces (veth*).
# See https://bugs.archlinux.org/task/70892
# Instead match by globbing the network interface name.
Name=en*
Name=eth*
[Link]
RequiredForOnline=routable
[Network]
DHCP=yes
MulticastDNS=yes
# systemd-networkd does not set per-interface-type default route metrics
# https://github.com/systemd/systemd/issues/17698
# Explicitly set route metric, so that Ethernet is preferred over Wi-Fi and Wi-Fi is preferred over mobile broadband.
# Use values from NetworkManager. From nm_device_get_route_metric_default in
# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/src/core/devices/nm-device.c
[DHCPv4]
RouteMetric=100
[IPv6AcceptRA]
RouteMetric=100

View File

@@ -0,0 +1,20 @@
[Match]
Name=wl*
[Link]
RequiredForOnline=routable
[Network]
DHCP=yes
MulticastDNS=yes
# systemd-networkd does not set per-interface-type default route metrics
# https://github.com/systemd/systemd/issues/17698
# Explicitly set route metric, so that Ethernet is preferred over Wi-Fi and Wi-Fi is preferred over mobile broadband.
# Use values from NetworkManager. From nm_device_get_route_metric_default in
# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/src/core/devices/nm-device.c
[DHCPv4]
RouteMetric=600
[IPv6AcceptRA]
RouteMetric=600

View File

@@ -0,0 +1,19 @@
[Match]
Name=ww*
[Link]
RequiredForOnline=routable
[Network]
DHCP=yes
# systemd-networkd does not set per-interface-type default route metrics
# https://github.com/systemd/systemd/issues/17698
# Explicitly set route metric, so that Ethernet is preferred over Wi-Fi and Wi-Fi is preferred over mobile broadband.
# Use values from NetworkManager. From nm_device_get_route_metric_default in
# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/src/core/devices/nm-device.c
[DHCPv4]
RouteMetric=700
[IPv6AcceptRA]
RouteMetric=700

View File

@@ -0,0 +1,2 @@
[Network]
IPv6PrivacyExtensions=yes

View File

@@ -0,0 +1,4 @@
# Default systemd-resolved configuration for archiso
[Resolve]
MulticastDNS=yes

View File

@@ -0,0 +1,3 @@
[Service]
ExecStart=
ExecStart=-/sbin/agetty -o '-p -f -- \\u' --noclear --autologin liveuser - $TERM

View File

@@ -0,0 +1 @@
/usr/lib/systemd/system/dbus.service

View File

@@ -0,0 +1 @@
../random-hostname.service

View File

@@ -0,0 +1 @@
../random-root-password.service

View File

@@ -0,0 +1 @@
/usr/lib/systemd/system/seatd.service

View File

@@ -0,0 +1,10 @@
[Unit]
Description=Set random hostname
Before=systemd-logind.service
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'hostnamectl set-hostname "client-$(tr -dc a-z0-9 </dev/urandom | head -c6)"'
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,13 @@
[Unit]
Description=Set random password for user root
DefaultDependencies=no
After=local-fs.target
Before=getty@tty1.service
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo "root:$(openssl rand -base64 48)" | chpasswd'
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,2 @@
KEYMAP=de-latin1
XKBLAYOUT=de

View File

@@ -0,0 +1 @@
[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && exec hyprland

View File

@@ -0,0 +1,7 @@
monitor=,preferred,auto,1
input {
kb_layout = de
}
exec-once = firefox

View File

@@ -0,0 +1,5 @@
title Boot To Firefox
sort-key 01
linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-lts
initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux-lts.img
options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID%

View File

@@ -0,0 +1,3 @@
timeout 15
default 01-archiso-x86_64-linux.conf
beep on

View File

@@ -0,0 +1,43 @@
# core
base
linux-lts
linux-atm
linux-firmware
linux-firmware-marvell
# boot
edk2-shell
mkinitcpio
mkinitcpio-archiso
mkinitcpio-nfs-utils
nbd
nfs-utils
plymouth
pv
syslinux
# network
dhcpcd
networkmanager
# wayland
wayland
seatd
xdg-desktop-portal-wlr
xorg-xwayland
# compositor
hyprland
hypridle
hyprpaper
hyprlock
# utils
kitty
xdg-utils
# input
libinput
# browser
firefox

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
iso_name="BOOTTOFIREFOX"
iso_label="BOOTTOFIREFOX"
iso_publisher="0x0001f346 0x0001f346@pm.me>"
iso_application="Boot to Firefox"
install_dir="arch"
buildmodes=('iso')
arch="x86_64"
pacman_conf="airootfs/etc/pacman.conf"
bootmodes=(
'bios.syslinux.mbr'
'bios.syslinux.eltorito'
'uefi-x64.systemd-boot.esp'
'uefi-x64.systemd-boot.eltorito'
)
file_permissions=(
["/etc/gshadow"]="0:0:0400"
["/etc/shadow"]="0:0:400"
)

View File

@@ -0,0 +1,10 @@
PROMPT 0
TIMEOUT 0
DEFAULT arch
LABEL arch
MENU LABEL Boot to Firefox
LINUX /arch/boot/x86_64/vmlinuz-linux-lts
INITRD /arch/boot/x86_64/initramfs-linux-lts.img
APPEND archisobasedir=arch archisolabel=BOOTTOFIREFOX quiet splash loglevel=3 rd.systemd.show_status=auto rd.udev.log_priority=3 vt.global_cursor_default=0