{ config, pkgs, lib, ... }: # Portable system + service config. Contains NO bootloader or filesystem # settings, so it can be reused by both the real host (configuration.nix) # and the VirtualBox test image (see flake.nix). { # ---- Networking ---- networking.hostName = "jupiter"; networking.networkmanager.enable = true; networking.firewall = { enable = true; allowedTCPPorts = [ 22 # ssh 445 139 # samba 80 443 # reverse proxy (caddy) ]; }; # ---- Locale / time ---- time.timeZone = "Europe/Berlin"; i18n.defaultLocale = "en_US.UTF-8"; # ---- Users ---- users.users.darman = { isNormalUser = true; description = "darman"; extraGroups = [ "wheel" "networkmanager" "docker" ]; # Password login for ssh is disabled below — these keys are the only way in. openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGZpkPVhzi1zG5JI9hWyUgdyvNIQbp4ts4jw3idpMhhN erik@laptop" ]; }; security.sudo.wheelNeedsPassword = false; # ---- SSH ---- services.openssh = { enable = true; settings = { PasswordAuthentication = false; PermitRootLogin = "no"; }; }; # ---- Storage / NAS ---- services.samba = { enable = true; openFirewall = true; settings = { global = { "workgroup" = "WORKGROUP"; "server string" = "jupiter"; "security" = "user"; }; data = { "path" = "/mnt/data"; "browseable" = "yes"; "read only" = "no"; "guest ok" = "no"; "valid users" = "darman"; }; }; }; # Samba keeps its own NTLM password DB, separate from the system password. # `services.samba` never sets it, so logins fail until provisioned. # This runs AFTER samba-smbd so its state dir (/var/lib/samba/private) exists # — an activation script runs too early and smbpasswd fails to init the passdb. # Reads a single-line password from the first file that exists: # Real host: /run/secrets/samba_password (sops-nix, see secrets.nix) # VM test: /etc/samba/smb-password (plaintext, see vm.nix) # smbpasswd prompts new + confirm, so the value is fed twice. systemd.services.samba-smbpasswd = { description = "Provision Samba password for darman"; after = [ "samba-smbd.service" ]; requires = [ "samba-smbd.service" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; script = '' for f in /run/secrets/samba_password /etc/samba/smb-password; do if [ -f "$f" ]; then pw=$(head -n1 "$f") printf '%s\n%s\n' "$pw" "$pw" | ${pkgs.samba}/bin/smbpasswd -a -s darman exit 0 fi done echo "no samba password source found" >&2 ''; }; services.avahi = { enable = true; nssmdns4 = true; publish = { enable = true; userServices = true; }; }; # ---- Audiobookshelf ---- # Native module. Listens on localhost only; reached through caddy. # Library/media paths are set in the web UI — point them at /mnt/data/... # The service runs as user `audiobookshelf`, which must be able to READ those # dirs on the RAID (chown/chmod or add it to the owning group as needed). services.audiobookshelf = { enable = true; host = "127.0.0.1"; port = 8000; # openFirewall stays off — access is via the caddy reverse proxy. }; # ---- Containers ---- virtualisation.podman = { enable = true; dockerCompat = true; defaultNetwork.settings.dns_enabled = true; }; virtualisation.oci-containers = { backend = "podman"; containers = { whoami = { image = "traefik/whoami:latest"; ports = [ "8080:80" ]; autoStart = true; }; }; }; # ---- Reverse proxy ---- # Caddy binds nothing unless it has a vhost. This proxies the whoami # container so :80 actually serves. Add one block per service. # Real host: swap `http://localhost` for your domain to get automatic HTTPS, # e.g. `services.caddy.virtualHosts."jelly.example.com".extraConfig`. services.caddy = { enable = true; virtualHosts."http://localhost".extraConfig = '' reverse_proxy localhost:8080 ''; # Reach at http://audiobookshelf.sol — add a pihole local-DNS record # audiobookshelf.sol -> jupiter's IP. (Or browse jupiter.sol directly if you # set services.audiobookshelf.host = "0.0.0.0" + openFirewall instead.) virtualHosts."http://audiobookshelf.sol".extraConfig = '' reverse_proxy localhost:8000 ''; }; # ---- System packages ---- environment.systemPackages = with pkgs; [ vim git htop tmux curl ]; # ---- Nix settings ---- nix.settings.experimental-features = [ "nix-command" "flakes" ]; nix.gc = { automatic = true; dates = "weekly"; options = "--delete-older-than 30d"; }; system.stateVersion = "26.05"; }