# Raspberry Pi 5 (`lyrathorpe-rpi5`) Headless `aarch64-linux` server with two roles: - **Docker host** — daemon exposed over the network (`docker.nix`). - **nginx reverse proxy** — declarative `virtualHosts` (`reverse-proxy.nix`). ## Install 1. Flash a NixOS `aarch64` SD image (or USB) and boot the Pi. The `raspberry-pi-5` profile from `nixos-hardware` (wired in the flake host table) supplies the kernel, firmware and device tree; boot is U-Boot + extlinux. 2. Partition/mount the target, then **regenerate the hardware config on the device** and replace the committed placeholder: ```sh nixos-generate-config --root /mnt # copy /mnt/etc/nixos/hardware-configuration.nix over # system/machine/RPi5/hardware-configuration.nix in this repo, then commit ``` `hardware-configuration.nix` in this directory is a **placeholder** committed only so the host evaluates in CI. The machine will not boot correctly until it is replaced with the generated one. 3. Set the host name to match the flake attribute (already done in `configuration.nix`: `lyrathorpe-rpi5`) and build: ```sh sudo nixos-rebuild switch --flake .#lyrathorpe-rpi5 # or, once the hostname is live: nh os switch ``` 4. Give the login user a password (`passwd lyrathorpe`) and confirm the key in `system/modules/ssh.nix` is the one you will connect with. ## Docker socket (security) The daemon listens on **plain TCP `2375`, no TLS, no auth**. Access is root-equivalent on this host. The only protection is the nftables rule in `docker.nix`, which accepts `2375` **only** from the trusted LAN subnet (`10.187.1.0/24` by default — change it to match your network). Do not widen that subnet to anything untrusted. From a LAN client: ```sh export DOCKER_HOST=tcp://lyrathorpe-rpi5:2375 docker info ``` The secure upgrade path is mutual TLS on `2376` (`--tlsverify` with a CA and client certs); it needs out-of-band cert provisioning and is intentionally not wired here. ## Adding a reverse-proxy site Each proxied service is a Nix entry in `reverse-proxy.nix`: ```nix services.nginx.virtualHosts."app.example.lan" = { # enableACME = true; forceSSL = true; # once a DNS name + cert exist locations."/" = { proxyPass = "http://127.0.0.1:8080"; # e.g. a local container proxyWebsockets = true; }; }; ``` The example vhost is HTTP-only by design. Turn on `enableACME`/`forceSSL` per-vhost once the host has a real DNS name and the ACME challenge can be met; `443` is already open in the firewall.