OS Setups

DietPi

Headless Configuration

$ timezone=<timezone>
$ hostname=<hostname>
$ password=<password>
$ sed -e 's/AUTO_SETUP_LOCALE.*/AUTO_SETUP_LOCALE=en_US.UTF-8/' \
      -e 's/AUTO_SETUP_KEYBOARD_LAYOUT.*/AUTO_SETUP_KEYBOARD_LAYOUT=us/' \
      -e 's/AUTO_SETUP_TIMEZONE.*/AUTO_SETUP_TIMEZONE=$timezone/' \
      -e 's/AUTO_SETUP_NET_HOSTNAME.*/AUTO_SETUP_NET_HOSTNAME=$hostname/' \
      -e 's/AUTO_SETUP_HEADLESS.*/AUTO_SETUP_HEADLESS=1/' \
      -e 's/AUTO_SETUP_SSH_SERVER_INDEX.*/AUTO_SETUP_SSH_SERVER_INDEX=-2/' \
      -e 's/AUTO_SETUP_LOGGING_INDEX.*/AUTO_SETUP_LOGGING_INDEX=-3/' \
      -e 's/AUTO_SETUP_WEB_SERVER_INDEX.*/AUTO_SETUP_WEB_SERVER_INDEX=-2/' \
      -e 's/AUTO_SETUP_AUTOMATED.*/AUTO_SETUP_AUTOMATED=1/' \
      -e 's/AUTO_SETUP_GLOBAL_PASSWORD.*/AUTO_SETUP_GLOBAL_PASSWORD=$password/' \
      -i /path/to/boot/diet.pi.txt

Static IP Address Configuration

$ ip=<static ip>
$ mask=<subnet mask>
$ gw=<gateway>
$ dns=<dns>
$ sed -e 's/AUTO_SETUP_NET_USESTATIC.*/AUTO_SETUP_NET_USESTATIC=1/' \
      -e 's/AUTO_SETUP_NET_STATIC_IP.*/AUTO_SETUP_NET_STATIC_IP=$ip/' \
      -e 's/AUTO_SETUP_NET_STATIC_MASK.*/AUTO_SETUP_NET_STATIC_MASK=$mask/' \
      -e 's/AUTO_SETUP_NET_STATIC_GATEWAY.*/AUTO_SETUP_NET_STATIC_GATEWAY=$gw/' \
      -e 's/AUTO_SETUP_NET_STATIC_DNS.*/AUTO_SETUP_NET_STATIC_DNS=$dns/' \
      -i /path/to/boot/diet.pi.txt

Post-Boot Configuration

Raspberry Pi OS

WiFi Configuration

$ ssid=<SSID>
$ psk=<PSK>
$ cat > /path/to/boot/wpa_supplicant.conf <<END
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=us

network={
     ssid="$ssid"
      psk="$psk"
}
END

Ubuntu

Wifi Static IP Configuration

$ ip=<ip/cidr>
$ dns="<dns 1, dns 2>"
$ gw=<gw>
$ ssid=<SSID>
$ psk=<PSK>
$ cat >> /path/to/boot/network-config <<END
wifis:
    wlan0:
    dhcp4: false
    addresses:
        - $ip
    nameservers:
        addresses: [$dns]
    gateway4: $gw
    optional: true
    access-points:
        "$ssid":
            password: "$psk"
END

Ethernet Static IP Configuration

$ ip=<ip/cidr>
$ dns="<dns 1, dns 2>"
$ gw=<gw>
$ ssid=<SSID>
$ psk=<PSK>
$ cat >> /path/to/boot/network-config <<END
ethernets:
    eth0:
    dhcp4: false
    optional: true
    addresses:
        - $ip
    nameservers:
        addresses: [$dns]
    gateway4: $gw
END

Post-Boot Configuration

$ sudo apt update
$ sudo apt upgrade
$ sudo sed -i -e 's/^en_GB.UTF-8/# en_GB.UTF-8/' \
              -e 's/^# en_US.UTF-8/en_US.UTF-8/' \
              /etc/locale.gen
$ sudo locale-gen

Alpine Linux

Based on Alpine Linux Wiki

Prepare SD Card

DISKPART> list disk
DISKPART> select disk <n>
DISKPART> clean
DISKPART> create partition primary size=256
DISKPART> active
DISKPART> format quick label=boot fs=fat32
DISKPART> assign letter=e
DISKPART> create partition primary
DISKPART> exit
$ sed -i /path/to/boot/usercfg.txt -e 's/.*enable_uart=.*/enable_uart=1/'
$ sed -i /path/to/boot/cmdline.txt -e 's/.*modules=.*/modules=loop,squashfs,sd-mod,usb-storage quiet console=tty1 console=serial0,115200/'
$ cp -R /path/to/boot/boot /path/to/boot
- Edit `/path/to/boot/config.txt` to adjust paths

Post-Boot Configuration

$ fdisk /dev/mmcblk0
Command: n
Partition type p
First sector: <enter>
Last sector: <enter>
Command: w

$ reboot
$ apk add e2fsprogs

## apkvol and apk cache partition
$ mkfs.ext2 -L cache /dev/mmcblk0p2
$ echo "LABEL=cache /media/mmcblk0p2 ext2 rw,relatime 0 0" >> /etc/fstab

## bootcache partition
$ mkfs.ext2 -L bootcache /dev/mmcblk0p3
$ mkdir /media/bootcache
$ echo "LABEL=bootcache /media/bootcache ext2 noauto,rw,relatime 0 0" >> /etc/fstab
$ mount /media/bootcache
$ setup-alpine -f /media/mmcblk0p1/setup-answers.txt
Which disk(s) would you like to use? none
## Sync time now
chronyc makestep

$ cat <<END > /etc/conf.d/swclock
## /etc/conf.d/swclock: config file for /etc/init.d/swclock

# Where to store system time on shutdown
# This must be a persistent location
clock_file="/media/bootcache/swclock/savedtime"
END

$ cat <<END > /etc/init.d.swclock
##!/sbin/openrc-run
## Copyright (c) 2009-2015 The OpenRC Authors.
## See the Authors file at the top-level directory of this distribution and
## https://github.com/OpenRC/openrc/blob/master/AUTHORS
#
## This file is part of OpenRC. It is subject to the license terms in
## the LICENSE file found in the top-level directory of this
## distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
## This file may not be copied, modified, propagated, or distributed
## except according to the terms contained in the LICENSE file.

description="Sets the local clock to the mtime of a given file."
clock_file=${cock_file:-/media/bootcache/swclock/savedtime}
mkdir -p $(dirname $clock_file)

depend()
{
    provide clock
    keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -
}

## swclock is an OpenRC built in

start()
{
    ebegin "Setting the local clock based on last shutdown time"
    if ! swclock 2> /dev/null; then
        mount /media/bootcache
        sleep 1
        swclock --warn $clock_file
    fi
    eend $?
}

stop()
{
    ebegin "Saving the shutdown time"
    swclock --save $clock_file
    sleep 1
    umount /media/bootcache
    eend $?
}
END

# Create link to saved time
ln -s ../../media/bootcache/swclock /var/lib/swclock

## Add swclock script to LBU backup
lbu add /etc/init.d/swclock
$ setup-sshd -c dropbear
$ lbu commit -d
$ reboot

Setup Disks

$ fdisk /dev/sda

## Clear partitions
Command: o

## Create swap partition
Command: n
Partition type p
Partition number: 1
First sector: <enter>
Last sector or +size: +2G
Command: t
Hex code: 82

## Create var partition
Command: n
Partition type p
Partition number: 2
First sector: <enter>
Last sector or +size: +2G

## Create LXD pool partition
Command: n
Partition type p
Partition number: 3
First sector: <enter>
Last sector or +size: <enter>

## Write partition table
Command: w

## Format swap and var partitions
##  (force rereading partition table by removing and
##   reinserting USB drive)

$ mkswap    -L swap /dev/sda1
$ mkfs.ext4 -L var  /dev/sda2
$ cat <<END >> /etc/fstab
LABEL=swap swap swap defaults 0 0
LABEL=var  /var ext4 defaults 0 0
# This doesn't seem to work until the clock skew is fixed
# because fdisk keeps thinking the parition is corrupt
#LABEL=var  /var ext4 defaults 1 2
END
$ mv /var /root
$ mkdir /var
$ mount /var
$ mv /root/var/* /var
$ rmdir /root/var
$ service syslog --quiet condrestart
$ apk del e2fsprogs
$ apk cache -v sync
$ lbu commit -d
$ reboot

Additional Configuration

$ cat <<END > /etc/local.d/01-apkcache.stop
##!/bin/sh

## verify the local cache on shutdown
apk cache -v sync

## always return 0
return 0
END
$ chmod +x /etc/local.d/01-cache.stop
$ apk add sudo
$ sed -i '/NOPASSWD/!s/^# %wheel/%wheel/' /etc/sudoers
$ adduser <username>
$ adduser <username> wheel
$ lbu add /home/<username>

## On main system:
$ ssh-copy-id <ip>
$ sed -i 's@DROPBEAR_OPTS.*@DROPBEAR_OPTS="-b /etc/issue -w -s"@' \
      /etc/conf.d/dropbear
$ cat <<END > /etc/issue
          _         _
      ___(_)_ __ __| | __ _ _ __
     / __| | '__/ _` |/ _` | '_ \
    | (__| | | | (_| | (_| | | | |
     \___|_|_|  \__,_|\__,_|_| |_|

Unauthorized access to this machine is prohibited
END
$ cat <<END > /etc/motd
Welcome to cirdan!

Running on Alpine Linux 
END

$ service dropbear restart