Box
Setup for my personal (pet) server.
Contributing
Found an error or have a suggestion? Please open an issue on GitHub (github.com/pojntfx/box)!
If you like the docs, a GitHub star is always appreciated :)
License
Box (c) 2022 Felicitas Pojtinger and contributors
SPDX-License-Identifier: AGPL-3.0
Linux
Debian
Debian, also known as Debian GNU/Linux, is a GNU/Linux distribution composed of free and open-source software, developed by the community-supported Debian Project, which was established by Ian Murdock on August 16, 19931.
First, download and flash a prebuilt vanilla Debian image for your Raspberry Pi model:
Adjust
/dev/sda
to the path of your SD card.
# Raspberry Pi Zero (W)/1
curl -L 'https://raspi.debian.net/tested/20220121_raspi_1_bullseye.img.xz' | xzcat >/tmp/debian.img
# Raspberry Pi 2
curl -L 'https://raspi.debian.net/tested/20220121_raspi_2_bullseye.img.xz' | xzcat >/tmp/debian.img
# Raspberry Pi 3
curl -L 'https://raspi.debian.net/tested/20220121_raspi_3_bullseye.img.xz' | xzcat >/tmp/debian.img
# Raspberry Pi 4/400
curl -L 'https://raspi.debian.net/tested/20220121_raspi_4_bullseye.img.xz' | xzcat >/tmp/debian.img
sudo umount /dev/sda{,0,1,2}
sudo dd if=/tmp/debian.img of=/dev/sda bs=4M status=progress
sync
sudo umount /dev/sda{,0,1,2}
For vanilla Debian, you can now mount the SD card and set the root password to a random string, add your authorized_keys
and set the hostname like so:
sudo umount /dev/sda{,0,1,2}
sudo mkdir -p /mnt/raspi-boot
sudo mount /dev/sda1 /mnt/raspi-boot
sudo tee -a /mnt/raspi-boot/sysconf.txt<<EOT
root_pw=$(openssl rand -base64 12)
root_authorized_key=$(cat ~/.ssh/id_rsa.pub)
hostname=jeans-box
EOT
sync
sudo umount /dev/sda{,0,1,2}
Raspbian
Raspberry Pi OS (formerly Raspbian) is a Debian-based operating system for Raspberry Pi2.
Alternatively, you may want to download and flash Raspbian instead of vanilla Debian by using the Raspberry Pi Imager. You can set the options mentioned above using the imager GUI; don't configure WLAN using it, as we'll use a static method instead.
From Wikipedia, last checked 2022-02-19 (https://en.wikipedia.org/wiki/Debian) 2: From Wikipedia, last checked 2022-03-07 (https://en.wikipedia.org/wiki/Raspberry_Pi_OS)
Wireless Networking
Debian
Adjust the IPv6 address, SSID and PSK to your own values.
sudo umount /dev/sda{,0,1,2}
sudo mkdir -p /mnt/raspi-root
sudo mount /dev/sda2 /mnt/raspi-root
# For a static IPv6 address
sudo tee /mnt/raspi-root/etc/network/interfaces.d/wlan0<<'EOT'
allow-hotplug wlan0
iface wlan0 inet dhcp
iface wlan0 inet6 static
address 2003:ef:1f01:7f00:76c9:d842:c369:8bf2
autoconf 1
accept_ra 2
wpa-ssid myssid
wpa-psk mypsk
EOT
# For a dynamic IPv6 address
sudo tee /mnt/raspi-root/etc/network/interfaces.d/wlan0<<'EOT'
allow-hotplug wlan0
iface wlan0 inet dhcp
iface wlan0 inet6 auto
wpa-ssid myssid
wpa-psk mypsk
EOT
sync
sudo umount /dev/sda{,0,1,2}
Raspbian
Adjust the IPv6 address, SSID and PSK to your own values.
sudo umount /dev/sda{,0,1,2}
sudo mkdir -p /mnt/raspi-{boot,root}
sudo mount /dev/sda1 /mnt/raspi-boot
sudo mount /dev/sda2 /mnt/raspi-root
sudo tee /mnt/raspi-boot/wpa_supplicant.conf<<'EOT'
country=de
update_config=1
ctrl_interface=/var/run/wpa_supplicant
network={
scan_ssid=1
ssid="myssid"
psk="mypsk"
}
EOT
# For a static IPv6 address
sudo tee /mnt/raspi-root/etc/network/interfaces.d/wlan0<<'EOT'
allow-hotplug wlan0
iface wlan0 inet dhcp
iface wlan0 inet6 static
address 2003:ef:1f01:7f00:76c9:d842:c369:8bf2
autoconf 1
accept_ra 2
EOT
# For a dynamic IPv6 address
sudo tee /mnt/raspi-root/etc/network/interfaces.d/wlan0<<'EOT'
allow-hotplug wlan0
iface wlan0 inet dhcp
iface wlan0 inet6 auto
EOT
sync
sudo umount /dev/sda{,0,1,2}
Wired Networking
Adjust the IPv6 address to your own value.
sudo umount /dev/sda{,0,1,2}
sudo mkdir -p /mnt/raspi-root
sudo mount /dev/sda2 /mnt/raspi-root
# For a static IPv6 address
sudo tee /mnt/raspi-root/etc/network/interfaces.d/eth0<<'EOT'
auto eth0
iface eth0 inet dhcp
iface eth0 inet6 static
address 2003:ef:1f01:7f00:76c9:d842:c369:8bf3
autoconf 1
accept_ra 2
EOT
# For a dynamic IPv6 address
sudo tee /mnt/raspi-root/etc/network/interfaces.d/eth0<<'EOT'
auto eth0
iface eth0 inet dhcp
iface eth0 inet6 auto
EOT
sync
sudo umount /dev/sda{,0,1,2}
DNS
sudo umount /dev/sda{,0,1,2}
sudo mkdir -p /mnt/raspi-root
sudo mount /dev/sda2 /mnt/raspi-root
sudo tee /mnt/raspi-root/etc/resolv.conf<<'EOT'
nameserver 2606:4700:4700::1111
nameserver 2606:4700:4700::1001
nameserver 1.1.1.1
nameserver 1.0.0.1
EOT
sudo chattr +i /mnt/raspi-root/etc/resolv.conf
sudo sed -i /mnt/raspi-root/etc/hosts -e 's/\tlocalhost/\tlocalhost jeans-box/g'
sync
sudo umount /dev/sda{,0,1,2}
You can now also add the AAAA
records for the device to your DNS zone (assuming that you've chosen a static IPv6 address):
Adjust the IPv6 address to either the address you gave the wireless or wired network interface previously.
jeans-box 10800 IN AAAA 2003:ef:1f01:7f00:76c9:d842:c369:8bf2
*.jeans-box 10800 IN AAAA 2003:ef:1f01:7f00:76c9:d842:c369:8bf2
SSH
The Secure Shell Protocol (SSH) is a cryptographic network protocol for operating network services securely over an unsecured network1.
Access the server:
# Debian
ssh root@jeans-box.alphahorizon.io
# Raspbian
ssh -tt pi@jeans-box.alphahorizon.io sudo su -l
If your Raspberry Pi doesn't have a static IPv6 address, you can connect to it by using jeans-box
instead of jeans-box.alphahorizon.io
, e.g. by using ssh root@jeans-box
, which uses mDNS to resolve the Raspberry Pi's address.
Create the user:
echo "LC_ALL=en_US.UTF-8" | tee -a /etc/environment
echo "en_US.UTF-8 UTF-8" | tee /etc/locale.gen
echo "LANG=en_US.UTF-8" | tee /etc/locale.conf
locale-gen en_US.UTF-8
adduser jean
su jean -c "mkdir -m 700 -p ~/.ssh && curl 'https://github.com/jean.keys' | tee -a ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
usermod -aG sudo jean
# Only on Raspbian: Delete the default `pi` user
sh -c 'killall -u pi && deluser --remove-home pi'
Setup SSH:
ssh jean@jeans-box.alphahorizon.io
sudo apt update
sudo apt install -y sudo curl openssh-server locales
sudo systemctl enable --now ssh
echo 'PermitRootLogin no' | sudo tee /etc/ssh/ssh_config.d/no-root.conf
sudo passwd -d root
sudo passwd -l root
sudo chsh -s /sbin/nologin
sudo rm -f /root/.ssh/authorized_keys
sudo systemctl restart ssh
From Wikipedia, last checked 2022-02-19 (https://en.wikipedia.org/wiki/Secure_Shell)
firewalld
firewalld is a firewall management tool for Linux operating systems1.
ssh jean@jeans-box.alphahorizon.io
sudo apt update
sudo apt install -y firewalld
sudo systemctl enable --now firewalld
sudo firewall-cmd --zone=public --add-interface=wlan0 --permanent
sudo firewall-cmd --zone=public --add-interface=eth0 --permanent
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-service=mdns
sudo firewall-cmd --permanent --add-service=llmnr
sudo firewall-cmd --reload
From Wikipedia, last checked 2022-02-19 (https://en.wikipedia.org/wiki/Firewalld)
APT
Advanced package tool, or APT, is a free-software user interface that works with core libraries to handle the installation and removal of software on Debian, and Debian-based Linux distributions1.
ssh jean@jeans-box.alphahorizon.io
sudo apt update
sudo apt install -y unattended-upgrades
sudo tee /etc/apt/apt.conf.d/50unattended-upgrades <<'EOT'
Unattended-Upgrade::Origins-Pattern {
"origin=*";
}
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "02:00";
EOT
sudo systemctl enable --now unattended-upgrades
sudo unattended-upgrades --debug
From Wikipedia, last checked 2022-02-19 (https://en.wikipedia.org/wiki/APT_(software))
Podman
Podman is a daemonless container engine for developing, managing, and running OCI Containers on your Linux System1.
ssh jean@jeans-box.alphahorizon.io
echo 'deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_11/ /' | sudo tee /etc/apt/sources.list.d/libcontainers.list
curl -L "https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_11/Release.key" | sudo apt-key add -
sudo apt update
sudo apt upgrade -y # Prevent conflicts with eventual prior Podman install from Debian repos
sudo apt install -t Debian_11 -y podman
sudo apt install -y containernetworking-plugins
echo 'unqualified-search-registries=["docker.io"]' | sudo tee /etc/containers/registries.conf.d/docker.conf
sudo systemctl unmask podman-auto-update.service
sudo systemctl unmask podman-auto-update.timer
sudo systemctl enable --now podman-auto-update.timer
sudo systemctl enable --now podman-restart
From the Podman website, last checked 2022-02-19 (https://podman.io/)
Traefik
Traefik (pronounced traffic) is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy1.
ssh jean@jeans-box.alphahorizon.io
sudo mkdir -p /etc/traefik
sudo tee /etc/traefik/traefik.yaml<<'EOT'
entryPoints:
web:
address: ":80"
http:
redirections:
entrypoint:
to: websecure
scheme: https
websecure:
address: ":443"
sshalt:
address: ":2222"
websecurealt:
address: ":8443"
providers:
file:
filename: /etc/traefik/services.yaml
watch: true
api:
dashboard: true
certificatesResolvers:
letsencrypt:
acme:
email: jean@example.com
storage: /var/lib/traefik/acme.json
httpChallenge:
entryPoint: web
log:
level: INFO
EOT
sudo tee /etc/traefik/services.yaml<<'EOT'
tcp:
routers:
ssh:
entryPoints:
- websecurealt
rule: HostSNI(`*`)
service: ssh
giteaSSH:
entryPoints:
- sshalt
rule: HostSNI(`*`)
service: giteaSSH
sshOverTLS:
entryPoints:
- websecure
rule: HostSNI(`ssh.jeans-box.alphahorizon.io`)
service: ssh
tls:
certResolver: letsencrypt
domains:
- main: ssh.jeans-box.alphahorizon.io
services:
ssh:
loadBalancer:
servers:
- address: localhost:22
giteaSSH:
loadBalancer:
servers:
- address: localhost:3022
http:
routers:
dashboard:
rule: Host(`traefik.jeans-box.alphahorizon.io`)
tls:
certResolver: letsencrypt
domains:
- main: traefik.jeans-box.alphahorizon.io
service: api@internal
entryPoints:
- websecure
middlewares:
- dashboard
cockpit:
rule: Host(`cockpit.jeans-box.alphahorizon.io`)
tls:
certResolver: letsencrypt
domains:
- main: cockpit.jeans-box.alphahorizon.io
service: cockpit
entryPoints:
- websecure
gitea:
rule: Host(`gitea.jeans-box.alphahorizon.io`)
tls:
certResolver: letsencrypt
domains:
- main: gitea.jeans-box.alphahorizon.io
service: gitea
entryPoints:
- websecure
dex:
rule: Host(`dex.jeans-box.alphahorizon.io`)
tls:
certResolver: letsencrypt
domains:
- main: dex.jeans-box.alphahorizon.io
service: dex
entryPoints:
- websecure
liwasc:
rule: Host(`liwasc.jeans-box.alphahorizon.io`)
tls:
certResolver: letsencrypt
domains:
- main: liwasc.jeans-box.alphahorizon.io
service: liwasc
entryPoints:
- websecure
bofied:
rule: Host(`bofied.jeans-box.alphahorizon.io`)
tls:
certResolver: letsencrypt
domains:
- main: bofied.jeans-box.alphahorizon.io
service: bofied
entryPoints:
- websecure
middlewares:
dashboard:
basicauth:
users:
- "jean:$apr1$dYdt8Zrl$TsEfzaedPGyjdrDk8EfRN." # htpasswd -nb jean asdf
services:
cockpit:
loadBalancer:
serversTransport: cockpit
servers:
- url: https://localhost:9090
gitea:
loadBalancer:
servers:
- url: http://localhost:3000
dex:
loadBalancer:
servers:
- url: http://localhost:5556
liwasc:
loadBalancer:
servers:
- url: http://localhost:15124
bofied:
loadBalancer:
servers:
- url: http://localhost:15256
serversTransports:
cockpit:
insecureSkipVerify: true
EOT
sudo mkdir -p /var/lib/traefik
sudo podman run -d --restart=always --label "io.containers.autoupdate=image" --net=host -v /var/lib/traefik/:/var/lib/traefik -v /etc/traefik/:/etc/traefik --name traefik traefik
sudo podman generate systemd --new traefik | sudo tee /lib/systemd/system/traefik.service
sudo systemctl daemon-reload
sudo systemctl enable --now traefik
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-port=8443/tcp
sudo firewall-cmd --reload
curl -Lu jean:asdf https://traefik.jeans-box.alphahorizon.io/ # Test the Traefik dashboard
ssh -p 8443 jean@jeans-box.alphahorizon.io # Test SSH over TCP
ssh -o ProxyCommand="openssl s_client -connect ssh.jeans-box.alphahorizon.io:443 -quiet" jean # Test SSH over TLS
From GitHub, last checked 2022-02-19 (https://github.com/traefik/traefik)
Cockpit
Cockpit is a web-based graphical interface for servers1.
ssh jean@jeans-box.alphahorizon.io
echo 'deb http://deb.debian.org/debian bullseye-backports main' | sudo tee /etc/apt/sources.list.d/backports.list
sudo apt update
sudo apt install -t bullseye-backports -y cockpit cockpit-podman cockpit-pcp
curl https://cockpit.jeans-box.alphahorizon.io/ # Test Cockpit
From the Cockpit website, last checked 2022-02-19 (https://cockpit-project.org/)
Gitea
Gitea is an open-source forge software package for hosting software development version control using Git as well as other collaborative features like bug tracking, wikis and code review1.
ssh jean@jeans-box.alphahorizon.io
sudo mkdir -p /var/lib/gitea
sudo podman run -d --restart=always --label "io.containers.autoupdate=image" --net slirp4netns:allow_host_loopback=true,enable_ipv6=true -p 3000:3000 -p 3022:22 -v /var/lib/gitea/:/data -v /etc/timezone:/etc/timezone:ro -v /etc/localtime:/etc/localtime:ro -e 'USER_UID=1000' -e 'USER_GID=1000' --name gitea gitea/gitea
sudo podman generate systemd --new gitea | sudo tee /lib/systemd/system/gitea.service
sudo systemctl daemon-reload
sudo systemctl enable --now gitea
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
curl https://gitea.jeans-box.alphahorizon.io/ # Test Gitea
Visit https://gitea.jeans-box.alphahorizon.io/ and run the Wizard; use the following values:
- Site Title: Jean's Gitea
- SSH Server Domain: gitea.jeans-box.alphahorizon.io
- SSH Server Port: 2222
- Gitea Base URL: https://gitea.jeans-box.alphahorizon.io/
- Use your email SMTP server in
Email Settings
, enableEmail Notifications
andRequire Email Confirmation to Register
- Under
Server and Third-Party Service Settings
, enableDisable Self-Registration
(if you want to prevent others from using Gitea) - Under
Administrator Account Settings
, create your admin account
Note that the installation might take a while (about 1 minute)
From Wikipedia, last checked 2022-02-19 (https://en.wikipedia.org/wiki/Gitea)
Dex
Dex is an identity service that uses OpenID Connect to drive authentication for other apps1.
First, setup Gitea by visiting https://gitea.jeans-box.alphahorizon.io/user/settings/applications and adding a new OAuth2 application with Application Name Dex
and Redirect URI https://dex.jeans-box.alphahorizon.io/callback
. Note the client ID and client secret; we'll need them in the following.
ssh jean@jeans-box.alphahorizon.io
sudo mkdir -p /etc/dex /var/lib/dex
sudo touch /var/lib/dex/dex.db
sudo chown -R 1001:1001 /var/lib/dex/
sudo tee /etc/dex/config.yaml<<'EOT'
issuer: https://dex.jeans-box.alphahorizon.io
storage:
type: sqlite3
config:
file: /var/dex/dex.db
web:
http: 0.0.0.0:5556
allowedOrigins: ['*']
staticClients:
- id: liwasc
redirectURIs:
- https://pojntfx.github.io/liwasc/
name: "liwasc"
public: true
- id: bofied
redirectURIs:
- https://pojntfx.github.io/bofied/
name: "bofied"
public: true
connectors:
- type: gitea
id: gitea
name: Gitea
config:
clientID: yourclientidfromgiteahere
clientSecret: yourclientsecretfromgiteahere
redirectURI: https://dex.jeans-box.alphahorizon.io/callback
baseURL: https://gitea.jeans-box.alphahorizon.io
EOT
sudo podman run -d --restart=always --label "io.containers.autoupdate=image" --net slirp4netns:allow_host_loopback=true,enable_ipv6=true -p 5556:5556 -v /var/lib/dex:/var/dex -v /etc/dex:/etc/dex --name dex ghcr.io/dexidp/dex dex serve /etc/dex/config.yaml
sudo podman generate systemd --new dex | sudo tee /lib/systemd/system/dex.service
sudo systemctl daemon-reload
sudo systemctl enable --now dex
You can test it out by visiting https://pojntfx.github.io/liwasc/ and trying to log in using the following credentials:
- Backend URL:
ws://example.com/
(we'll set this later; this is just to try out the login) - OIDC Issuer:
https://dex.jeans-box.alphahorizon.io
- OIDC Client ID:
liwasc
- OIDC Redirect URL:
https://pojntfx.github.io/liwasc/
And authorization prompt from Gitea and Dex should show up, after which liwasc's home page should load (showing an error like Failed to construct 'WebSocket': An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.
).
From the Dex website, last checked 2022-02-19 (https://dexidp.io/)
liwasc
liwasc is a high-performance network and port scanner1.
ssh jean@jeans-box.alphahorizon.io
sudo mkdir -p /var/lib/liwasc
sudo podman run -d --restart=always --label "io.containers.autoupdate=image" --net host --cap-add NET_RAW --ulimit nofile=16384:16384 -v /var/lib/liwasc:/root/.local/share/liwasc -e LIWASC_BACKEND_OIDCISSUER=https://dex.jeans-box.alphahorizon.io -e LIWASC_BACKEND_OIDCCLIENTID=liwasc -e LIWASC_BACKEND_DEVICENAME=eth0 -e LIWASC_BACKEND_PERIODICSCANCRONEXPRESSION='0 0 * * *' --name liwasc pojntfx/liwasc-backend
sudo podman generate systemd --new liwasc | sudo tee /lib/systemd/system/liwasc.service
sudo systemctl daemon-reload
sudo systemctl enable --now liwasc
Visit https://pojntfx.github.io/liwasc/ as we did before and use wss://liwasc.jeans-box.alphahorizon.io/
as the backend URL (note the trailing slash!).
From GitHub, last checked 2022-02-19 (https://github.com/pojntfx/liwasc)
bofied
bofied is a network boot server1.
ssh jean@jeans-box.alphahorizon.io
sudo mkdir -p /var/lib/bofied
sudo podman run -d --restart=always --label "io.containers.autoupdate=image" --net host --cap-add NET_BIND_SERVICE -v /var/lib/bofied:/root/.local/share/bofied -e BOFIED_BACKEND_OIDCISSUER=https://dex.jeans-box.alphahorizon.io -e BOFIED_BACKEND_OIDCCLIENTID=bofied -e BOFIED_BACKEND_ADVERTISEDIP=143.198.37.173 --name bofied pojntfx/bofied-backend
sudo podman generate systemd --new bofied | sudo tee /lib/systemd/system/bofied.service
sudo systemctl daemon-reload
sudo systemctl enable --now bofied
sudo firewall-cmd --permanent --add-port=67/udp
sudo firewall-cmd --permanent --add-port=69/udp
sudo firewall-cmd --permanent --add-port=4011/udp
sudo firewall-cmd --reload
Visit https://pojntfx.github.io/bofied/ and login using the following credentials:
- Backend URL:
https://bofied.jeans-box.alphahorizon.io/
- OIDC Issuer:
https://dex.jeans-box.alphahorizon.io
- OIDC Client ID:
bofied
- OIDC Redirect URL:
https://pojntfx.github.io/bofied/
From GitHub, last checked 2022-02-19 (https://github.com/pojntfx/bofied)