Initial commit

pull/1/head
Dustin 2022-03-07 08:53:58 -06:00
commit 2437e6e467
25 changed files with 498 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/_build

17
Makefile Normal file
View File

@ -0,0 +1,17 @@
SHELL ?= /bin/sh
.PHONY: rootfs
rootfs:
$(SHELL) mkrootfs.sh _build/rootfs
.PHONY: initramfs
initramfs: _build/rootfs/boot/initramfs.img
_build/rootfs/boot/initramfs.img: \
_build/rootfs/bin/dracut \
mkinitramfs.sh
$(SHELL) mkinitramfs.sh _build/rootfs
.PHONY: publish
publish:
$(SHELL) publish.sh _build/rootfs

32
README.md Normal file
View File

@ -0,0 +1,32 @@
# Basement Hud Network-Booted OS
Customized Fedora-based operating system distributed as an immutable
root filesystem image.
## Building
Must run on a Fedora host or privileged container.
Build the root filesystem image:
```sh
make rootfs
```
This will create an `_build/rootfs` directory containing the root filesystem
hierarchy. The `_build/rootfs/boot` directory contains the necessary files to
boot the system:
* `efi`: This directory contains the Raspberry Pi firmware files
* `initramfs.img`: Early userspace image
* `vmlinuz`: Kernel image
* `basementhud.squashfs`: Root filesystem image
The Raspberry Pi firmware, initramfs image, and kernel image files must be
served by a TFTP, while the rootfs image is served by NBD.
Build the initramfs image:
```sh
make initramfs
```

18
ci/Dockerfile Normal file
View File

@ -0,0 +1,18 @@
FROM registry.fedoraproject.org/fedora:35
ARG UID
ARG GID
RUN groupadd -g ${GID} jenkins \
&& useradd -u ${UID} -g ${GID} -m -d /var/lib/jenkins -l jenkins
RUN dnf install -y \
findutils \
make \
openssh-clients \
rsync \
squashfs-tools \
tar \
unzip \
util-linux \
&& dnf clean all

67
ci/Jenkinsfile vendored Normal file
View File

@ -0,0 +1,67 @@
DOCKER_BUILD_ARGS = '''\
--build-arg UID=$(id -u) \
--build-arg GID=$(id -g) \
'''
pipeline {
agent {
label 'docker && aarch64'
}
options {
buildDiscarder logRotator(numToKeepStr: '5')
disableConcurrentBuilds()
}
triggers {
pollSCM ''
}
parameters {
booleanParam \
name: 'Clean',
description: 'Clean the workspace and perform a full rebuild'
}
stages {
stage('Build') {
agent {
dockerfile {
reuseNode true
dir 'ci'
args '--privileged -u 0:0'
additionalBuildArgs DOCKER_BUILD_ARGS
}
}
steps {
script {
if (params.Clean) {
sh 'rm -rf _build'
}
}
sh 'make rootfs initramfs'
}
}
stage('Publish') {
when {
not {
changeRequest()
}
}
agent {
dockerfile {
reuseNode true
dir 'ci'
args '-v /etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts'
additionalBuildArgs DOCKER_BUILD_ARGS
}
}
steps {
sshagent(['jenkins-pxe']) {
sh 'make publish'
}
}
}
}
}

1
cmdline.txt Normal file
View File

@ -0,0 +1 @@
rd.retry=3 rd.timeout=5 panic=5 audit=0 root=nbd:pxe0.pyrocufflink.blue:basementhud

55
config.txt Normal file
View File

@ -0,0 +1,55 @@
# Raspberry Pi 4
[pi4]
kernel=vmlinuz
dtoverlay=upstream-pi4
# Default Fedora configs for all Raspberry Pi Revisions
[all]
# Put the RPi into 64 bit mode
arm_64bit=1
# To use an external initramfs file
initramfs initramfs.img
# Enable UART
# Only enable UART if you're going to use it as it has speed implications
# Serial console is ttyS0 on RPi3 and ttyAMA0 on all other variants
# u-boot will auto detect serial and pass corrent options to kernel if enabled
# Speed details: https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=141195
# Terrible hack to work around U-Boot issues on most devices
#enable_uart=1
# Early boot delay in the hope monitors are initialised enough to provide EDID
bootcode_delay=1
# We need this to be 32Mb to support VCHI services and drivers which use them
# but this isn't used by mainline VC4 driver so reduce to lowest supported value
# You need to set this to at least 80 for using the camera
gpu_mem=32
# Use eXtended firmware by default
start_x=1
# Stop the RPi turning on HDMI monitors on reboot
hdmi_ignore_cec_init=1
# New option to allow the firmware to load upstream dtb
# Will allow things like camera, touchscreen etc to work OOTB
upstream_kernel=1
# HAT and DT overlays. Documentation at Raspberry Pi here:
# https://www.raspberrypi.org/documentation/configuration/device-tree.md
# Each dtoverlay line is an individual HAT/overlay, multiple lines allowed
# dtoverlay=rpi-sense
# Other options you can adjust for all Raspberry Pi Revisions
# https://www.raspberrypi.org/documentation/configuration/config-txt/README.md
# All options documented at http://elinux.org/RPiconfig
# for more options see http://elinux.org/RPi_config.txt
# To use this on Fedora you need to use firmware provided device tree, not kernel
# For this functionality follow the following guide:
# https://fedoraproject.org/w/index.php?title=Architectures/ARM/Raspberry_Pi/HATs
dtoverlay=disable-bt

36
mkinitramfs.sh Normal file
View File

@ -0,0 +1,36 @@
#!/bin/sh
set -eu
destdir="$(readlink -e "$1")"
kver=$(rpm --root "${destdir}" -q --qf '%{VERSION}-%{RELEASE}.%{ARCH}' kernel)
printf 'Building initramfs image for kernel %s\n' "${kver}"
cd "${destdir}"
mkdir -p boot dev proc sys tmp
mountpoint -q dev || mount -o bind /dev dev
mountpoint -q proc || mount -t proc proc proc
mountpoint -q sys || mount -t sysfs sysfs sys
mountpoint -q tmp || mount -t tmpfs tmpfs tmp
echo 'Copying kernel image to /boot/ ...' >&2
cp -a "${destdir}"/lib/modules/"${kver}"/vmlinuz \
"${destdir}"/boot/
echo 'Running depmod ...' >&2
chroot "${destdir}" depmod -a "${kver}"
echo 'Building initramfs image ...' 2>&1
chroot "${destdir}" dracut \
--no-hostonly \
--add 'nbd' \
--add-drivers 'genet nbd squashfs' \
--force \
/boot/initramfs.img \
"${kver}"
echo 'Fixing boot file pemissions ...' 2>&1
find "${destdir}"/boot \
-type d -exec chmod a+rx {} + \
-or \
-type f -exec chmod a+r {} +
umount tmp sys proc dev

74
mkrootfs.sh Normal file
View File

@ -0,0 +1,74 @@
#!/bin/sh
set -e
srcdir="$(dirname "$0")"
destdir="$(mkdir -p "$1" && readlink -e "$1")"
dest=basementhud.squashfs
releasever=35
mkdir -p "${destdir}"
dnf --installroot "${destdir}" install -y \
--releasever ${releasever} \
fedora-release
cp /etc/dnf/dnf.conf "${destdir}/etc/dnf/"
echo install_weak_deps=False >> "${destdir}"/etc/dnf/dnf.conf
dnf --installroot "${destdir}" install -y \
bcm2711-firmware \
dracut-network \
firefox \
hostname \
kmod \
matchbox-window-manager \
mesa-dri-drivers \
nbd \
openssh-server \
rsyslog \
systemd \
systemd-resolved \
xinit \
xorg-x11-server-Xorg \
xset \
--
dnf --installroot "${destdir}" install -y \
--setopt tsflags=noscripts \
kernel \
--
cp -p \
"${srcdir}"/cmdline.txt \
"${srcdir}"/config.txt \
"${destdir}"/boot/efi
for x in ed25519 rsa ecdsa; do
chroot "${destdir}" /usr/libexec/openssh/sshd-keygen $x
done
tar --owner root:0 -C "${srcdir}/overlay" -c . \
| tar -C "${destdir}" -x
chown -R 1000:1000 "${destdir}"/home/user
if ! grep -q ^user: "${destdir}"/etc/group; then
chroot "${destdir}" groupadd -g 1000 user
fi
if ! grep -q ^user: "${destdir}"/etc/passwd; then
chroot "${destdir}" useradd -u 1000 -g 1000 user
fi
if ! grep -qE '^video:.*:.+:.*,?user' "${destdir}"/etc/group; then
chroot "${destdir}" gpasswd -a user video
fi
chroot "${destdir}" systemctl enable \
systemd-time-wait-sync \
systemd-timesyncd \
xinit@user
umask 0022
mksquashfs "${destdir}" "${destdir}/boot/${dest}" \
-comp lz4 \
-noappend \
-ef "${srcdir}"/squashfs-exclude.txt \
-no-exports \
-wildcards

4
overlay/etc/fstab Normal file
View File

@ -0,0 +1,4 @@
tmpfs /var/lib/rsyslog tmpfs defaults 0 0
tmpfs /var/log tmpfs defaults 0 0
tmpfs /var/lib/systemd tmpfs defaults 0 0
tmpfs /var/lib/NetworkManager tmpfs defaults 0 0

17
overlay/etc/pam.d/xinit Normal file
View File

@ -0,0 +1,17 @@
#%PAM-1.0
auth substack system-auth
auth include postlogin
account required pam_nologin.so
account include system-auth
password include system-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session required pam_selinux.so open
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include system-auth
session required pam_exec.so /usr/local/libexec/home-overlay.sh
session include postlogin
-session optional pam_ck_connector.so

4
overlay/etc/rsyslog.conf Normal file
View File

@ -0,0 +1,4 @@
global(workDirectory="/var/lib/rsyslog")
module(load="imjournal"
StateFile="imjournal.state")
*.* @172.30.0.28

View File

@ -0,0 +1,21 @@
[Unit]
Description=Start X.org for user %I
Wants=network-online.target
After=network-online.target
Wants=time-sync.target
After=time-sync.target
[Service]
Type=simple
User=%I
WorkingDirectory=~
PAMName=xinit
TTYPath=/dev/tty7
StandardInput=tty
StandardOutput=journal
StandardError=journal
ExecStart=/usr/bin/startx
Restart=always
[Install]
WantedBy=graphical.target

View File

@ -0,0 +1,9 @@
[Unit]
Description=Firefox web browser
[Service]
Type=simple
ExecStart=/usr/bin/firefox
Restart=always
StandardInput=null
StandardOutput=journal

View File

@ -0,0 +1,4 @@
[Unit]
Description=Graphical Interface
After=default.target
AllowIsolate=yes

View File

@ -0,0 +1 @@
../firefox.service

View File

@ -0,0 +1,7 @@
#!/bin/sh
xset s off
xset -dpms
systemctl --user import-environment DISPLAY
systemctl --user start graphical.target
exec matchbox-window-manager -use_titlebar no

View File

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJsL5fSylmiJmBtW0DH/viAAmtU2E/2M17GPvysiyRs+ dustin@rosalina

View File

@ -0,0 +1,2 @@
pref("general.config.filename", "firefox.cfg");
pref("general.config.obscure_value", 0);

View File

@ -0,0 +1,10 @@
{
"policies": {
"BlockAboutConfig": true,
"Extensions": {
"Install": [
"https://addons.mozilla.org/firefox/downloads/file/1105247/auto_fullscreen-1.0.0.2-fx.xpi"
]
}
}
}

View File

@ -0,0 +1,2 @@
// Load preferences from remote
pref("autoadmin.global_config_url","http://rosalina.pyrocufflink.blue/~dustin/autoconfigfile.js");

View File

@ -0,0 +1,17 @@
#!/bin/sh
if mountpoint -q "${HOME}"; then
exit 0
fi
upperdir="${XDG_RUNTIME_DIR}"/home/rw
workdir="${XDG_RUNTIME_DIR}"/home/.work
mkdir -p "${upperdir}"
mkdir -p "${workdir}"
mount overlay \
-t overlay \
-o lowerdir="${HOME}",upperdir="${upperdir}",workdir="${workdir}" \
"${HOME}"
chown "${PAM_USER}": "${HOME}"

13
prepare.sh Normal file
View File

@ -0,0 +1,13 @@
#!/bin/bash
set -e
shopt -s nullglob
dnf install -y \
make \
rsync \
squashfs-tools \
tar \
unzip \
util-linux \
--

15
publish.sh Normal file
View File

@ -0,0 +1,15 @@
#!/bin/sh
set -eu
destdir="$(readlink -e "$1")"
bootdir="${destdir}/boot"
rsync -rtliO --chmod=a=rwX \
"${bootdir}"/efi/ \
"${bootdir}"/initramfs.img \
"${bootdir}"/vmlinuz \
pxe0.pyrocufflink.blue:/var/lib/tftpboot/basementhud/
rsync -ti --chmod=a=rwX --no-W \
"${bootdir}"/basementhud.squashfs \
pxe0.pyrocufflink.blue:/var/lib/nbd/basementhud.squashfs

70
squashfs-exclude.txt Normal file
View File

@ -0,0 +1,70 @@
boot/*
dev/*
etc/dnf*
etc/pki/CA
etc/pki/rpm-gpg
etc/pki/tls/certs/Makefile
etc/yum*
proc/*
run/*
sys/*
tmp/*
usr/bin/as
usr/bin/c++filt
usr/bin/dwp
usr/bin/elfedit
usr/bin/gmake
usr/bin/gprof
usr/bin/ld
usr/bin/ld.*
usr/bin/make
usr/bin/makedb
usr/bin/objcopy
usr/bin/objdump
usr/bin/perl*
usr/bin/pip*
usr/bin/ranlib
usr/bin/rpm*
usr/bin/size
usr/bin/strings
usr/games
usr/lib/dracut
usr/lib/games
usr/lib/modules/*/.vmlinuz*.hmac
usr/lib/modules/*/System.map*
usr/lib/modules/*/config*
usr/lib/modules/*/dtb
usr/lib/modules/*/initramfs*
usr/lib/modules/*/symvers*
usr/lib/modules/*/vmlinuz*
usr/lib/pkgconfig
usr/lib64/games
usr/lib64/pkgconfig
usr/share/GeoIP
usr/share/applications
usr/share/bash-completions/completions/pip*
usr/share/doc
usr/share/games
usr/share/info
usr/share/locale/*/*/bfd.mo
usr/share/locale/*/*/gas.mo
usr/share/locale/*/*/gold.mo
usr/share/locale/*/*/gprof.mo
usr/share/locale/*/*/ld.mo
usr/share/locale/*/*/make.mo
usr/share/man
usr/share/pkgconfig
usr/src
var/cache/dnf
var/cache/yum
var/games
var/lib/Makefile
var/lib/dnf
var/lib/games
var/lib/rpm
var/lib/yum
var/local
var/log/yum.log
var/nis
var/opt
var/yp