diff --git a/system/machine/RPi5/docker.nix b/system/machine/RPi5/docker.nix new file mode 100644 index 0000000..ff4dc88 --- /dev/null +++ b/system/machine/RPi5/docker.nix @@ -0,0 +1,34 @@ +# Docker host with the daemon socket exposed over the network. +# +# SECURITY: the daemon listens on plain TCP 2375 with NO TLS and NO auth. Access +# to that port is root-equivalent on this host (the Docker API can mount the +# host filesystem and run privileged containers). The ONLY thing protecting it +# is the nftables rule below, which accepts 2375 solely from the trusted LAN +# subnet. Do not widen that subnet to anything you do not fully trust. The +# secure upgrade path is mutual TLS on 2376 (--tlsverify with client certs); +# that needs out-of-band cert provisioning and is intentionally not wired here. +{ ... }: +{ + virtualisation.docker.enable = true; + + # Expose the daemon over TCP by extending systemd socket activation rather than + # setting daemon.settings.hosts. The NixOS docker unit starts dockerd with + # `-H fd://` and takes its listeners from this socket; putting `hosts` in + # daemon.json as well would conflict with that and dockerd would refuse to + # start. Adding the TCP listener here keeps a single source of truth. + # The leading "" resets the unit's default (unix-socket-only) ListenStream list. + systemd.sockets.docker.socketConfig.ListenStream = [ + "" + "/run/docker.sock" + "0.0.0.0:2375" + ]; + + # Source-restricted firewall rule for the Docker TCP port. 2375 is deliberately + # NOT added to networking.firewall.allowedTCPPorts (that would open it to every + # source); instead nftables accepts it only from the trusted subnet. Adjust the + # CIDR to match the LAN that should reach the Docker API. + networking.nftables.enable = true; + networking.firewall.extraInputRules = '' + ip saddr 10.187.1.0/24 tcp dport 2375 accept + ''; +}