first commit
This commit is contained in:
18
LICENSE
Normal file
18
LICENSE
Normal 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
56
README.md
Normal 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
16
build.sh
Executable 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"
|
5
profiles/boot-to-firefox/airootfs/etc/group
Normal file
5
profiles/boot-to-firefox/airootfs/etc/group
Normal 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
|
3
profiles/boot-to-firefox/airootfs/etc/gshadow
Normal file
3
profiles/boot-to-firefox/airootfs/etc/gshadow
Normal file
@@ -0,0 +1,3 @@
|
||||
root:!*::root
|
||||
liveuser:!*::
|
||||
|
1
profiles/boot-to-firefox/airootfs/etc/hostname
Normal file
1
profiles/boot-to-firefox/airootfs/etc/hostname
Normal file
@@ -0,0 +1 @@
|
||||
boot-to-firefox
|
1
profiles/boot-to-firefox/airootfs/etc/locale.conf
Normal file
1
profiles/boot-to-firefox/airootfs/etc/locale.conf
Normal file
@@ -0,0 +1 @@
|
||||
LANG=de_DE.utf8
|
1
profiles/boot-to-firefox/airootfs/etc/localtime
Symbolic link
1
profiles/boot-to-firefox/airootfs/etc/localtime
Symbolic link
@@ -0,0 +1 @@
|
||||
/usr/share/zoneinfo/Europe/Berlin
|
@@ -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)
|
@@ -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"
|
97
profiles/boot-to-firefox/airootfs/etc/pacman.conf
Normal file
97
profiles/boot-to-firefox/airootfs/etc/pacman.conf
Normal 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
|
2
profiles/boot-to-firefox/airootfs/etc/passwd
Normal file
2
profiles/boot-to-firefox/airootfs/etc/passwd
Normal file
@@ -0,0 +1,2 @@
|
||||
root:x:0:0:root:/root:/usr/bin/bash
|
||||
liveuser:x:1000:1000::/home/liveuser:/usr/bin/bash
|
@@ -0,0 +1,2 @@
|
||||
[Daemon]
|
||||
Theme=bgrt
|
2
profiles/boot-to-firefox/airootfs/etc/shadow
Normal file
2
profiles/boot-to-firefox/airootfs/etc/shadow
Normal file
@@ -0,0 +1,2 @@
|
||||
root::14871::::::
|
||||
liveuser::14871::::::
|
@@ -0,0 +1,4 @@
|
||||
[Login]
|
||||
HandleSuspendKey=ignore
|
||||
HandleHibernateKey=ignore
|
||||
HandleLidSwitch=ignore
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -0,0 +1,2 @@
|
||||
[Network]
|
||||
IPv6PrivacyExtensions=yes
|
@@ -0,0 +1,4 @@
|
||||
# Default systemd-resolved configuration for archiso
|
||||
|
||||
[Resolve]
|
||||
MulticastDNS=yes
|
@@ -0,0 +1 @@
|
||||
/dev/null
|
@@ -0,0 +1,3 @@
|
||||
[Service]
|
||||
ExecStart=
|
||||
ExecStart=-/sbin/agetty -o '-p -f -- \\u' --noclear --autologin liveuser - $TERM
|
@@ -0,0 +1 @@
|
||||
/usr/lib/systemd/system/dbus.service
|
@@ -0,0 +1 @@
|
||||
../random-hostname.service
|
@@ -0,0 +1 @@
|
||||
../random-root-password.service
|
@@ -0,0 +1 @@
|
||||
/usr/lib/systemd/system/seatd.service
|
@@ -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
|
@@ -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
|
2
profiles/boot-to-firefox/airootfs/etc/vconsole.conf
Normal file
2
profiles/boot-to-firefox/airootfs/etc/vconsole.conf
Normal file
@@ -0,0 +1,2 @@
|
||||
KEYMAP=de-latin1
|
||||
XKBLAYOUT=de
|
1
profiles/boot-to-firefox/airootfs/home/liveuser/.bashrc
Normal file
1
profiles/boot-to-firefox/airootfs/home/liveuser/.bashrc
Normal file
@@ -0,0 +1 @@
|
||||
[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && exec hyprland
|
@@ -0,0 +1,7 @@
|
||||
monitor=,preferred,auto,1
|
||||
|
||||
input {
|
||||
kb_layout = de
|
||||
}
|
||||
|
||||
exec-once = firefox
|
@@ -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%
|
3
profiles/boot-to-firefox/efiboot/loader/loader.conf
Normal file
3
profiles/boot-to-firefox/efiboot/loader/loader.conf
Normal file
@@ -0,0 +1,3 @@
|
||||
timeout 15
|
||||
default 01-archiso-x86_64-linux.conf
|
||||
beep on
|
43
profiles/boot-to-firefox/packages.x86_64
Normal file
43
profiles/boot-to-firefox/packages.x86_64
Normal 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
|
19
profiles/boot-to-firefox/profiledef.sh
Normal file
19
profiles/boot-to-firefox/profiledef.sh
Normal 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"
|
||||
)
|
10
profiles/boot-to-firefox/syslinux/syslinux.cfg
Normal file
10
profiles/boot-to-firefox/syslinux/syslinux.cfg
Normal 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
|
||||
|
Reference in New Issue
Block a user