# NixOS configuration for homeserver-1 # Headless server environment (Command Line Interface only) { config , pkgs , lib , inputs , ... }: { imports = [ ../../modules/core/common.nix (import ../../modules/storage/disko.nix { inherit inputs lib config; diskoConfigPath = ./disko-config.nix; }) ./hardware-configuration.nix ../../modules/core/management.nix ../../modules/core/podman.nix ../../modules/hardware/nvidia.nix ../../modules/core/known-hosts.nix ../../modules/services/immich.nix ../../modules/services/jellyfin.nix ../../modules/services/backrest.nix ../../modules/services/homepage.nix ../../modules/services/gitea.nix ./homepage.nix ]; services.backrest = { enable = true; host = "0.0.0.0"; port = 9898; dataDir = "/data/backrest"; }; systemd.services.backrest = { after = [ "restic-ssh-key-format.service" ]; wants = [ "restic-ssh-key-format.service" ]; }; # Allow backrest to read backup source directories recursively. # Uses ACLs with a default mask so newly created files also inherit access. # Runs after immich and the postgresql backup so the dirs/files exist. systemd.services.backrest-permissions = { description = "Grant backrest read access to backup source dirs"; wantedBy = [ "multi-user.target" ]; after = [ "immich-server.service" "postgresqlBackup-immich.service" ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; script = '' # Recursive read+execute ACL for backrest on immich media ${pkgs.acl}/bin/setfacl -R -m u:backrest:rx -m m::r-x /data/immich # Default ACL so future immich files are readable by backrest ${pkgs.acl}/bin/setfacl -R -m d:u:backrest:rx -m d:m::r-x /data/immich # Recursive read for backrest on postgresql backups ${pkgs.acl}/bin/setfacl -R -m u:backrest:rx -m m::r-x /data/backup/postgresql ${pkgs.acl}/bin/setfacl -R -m d:u:backrest:rx -m d:m::r-x /data/backup/postgresql # Recursive read for backrest on gitea (repos + dump) ${pkgs.acl}/bin/setfacl -R -m u:backrest:rx -m m::r-x /data/gitea ${pkgs.acl}/bin/setfacl -R -m d:u:backrest:rx -m d:m::r-x /data/gitea ''; }; services.immich-server = { enable = true; port = 2283; mediaLocation = "/data/immich"; }; services.jellyfin-server = { enable = true; port = 8096; mediaLocation = "/data/jellyfin"; }; # Gitea git server. Public at https://gitea.edley.me via an external reverse # proxy (TLS terminator) that reaches us over Tailscale. Only that proxy's # Tailscale IP is allowed through the firewall (see modules/services/gitea.nix). services.gitea-server = { enable = true; port = 3000; domain = "gitea.edley.me"; proxyIp = "100.109.85.40"; }; services.postgresqlBackup = { enable = true; databases = [ "immich" "gitea" ]; location = "/data/backup/postgresql"; compression = "zstd"; startAt = "weekly"; }; # The services.postgresqlBackup module creates a tmpfiles `d` rule that sets # the backup directory to 0700 on every rebuild/switch. On a directory with # POSIX ACLs, `chmod 0700` resets the ACL mask to `---`, which nullifies the # `user:backrest` read ACL that backrest uses to back up these dumps. Override # the mode so rebuilds keep the directory group-traversable (mask stays rx). # Note: systemd-tmpfiles dedupes conflicting rules and keeps the FIRST one for # a path, so our override must appear before the module's rule. systemd.tmpfiles.rules = lib.mkBefore [ "d /data/backup/postgresql 0750 postgres - - -" ]; sops.secrets = { "users/petere-password" = { neededForUsers = true; }; "pocket-id-env" = { neededForUsers = false; }; "homeserver-1/restic-passphrase" = { }; "homeserver-1/restic-ssh-key" = { }; "homeserver-1/homepage-env" = { }; "homeserver-1/samba-petere-password" = { }; }; # Set petere's Samba password from SOPS at boot. Samba keeps its own password # database (smbpasswd/tdbsam), separate from Linux login, so this must run # smbpasswd. Idempotent: re-applied on every boot from the secret. systemd.services.samba-set-petere-password = { description = "Set petere's Samba password from SOPS"; wantedBy = [ "multi-user.target" ]; after = [ "sops-nix.service" ]; before = [ "samba-smbd.service" ]; serviceConfig.Type = "oneshot"; script = '' PASS="$(cat ${config.sops.secrets."homeserver-1/samba-petere-password".path})" ${pkgs.samba}/bin/smbpasswd -s -a petere < /data/backrest/.ssh/config <