diff --git a/flake.lock b/flake.lock index d8fc650..7f57fc2 100644 --- a/flake.lock +++ b/flake.lock @@ -538,11 +538,11 @@ }, "nix-secrets": { "locked": { - "lastModified": 1736868005, - "narHash": "sha256-ijKkZEq9W5L6ymFQd6O21657ws6FRroNrfaIVZnuW+c=", + "lastModified": 1736984538, + "narHash": "sha256-SAoVXTVwLL4hYpHQFJqI+91eIqIS0Mug0URqh6KqeIM=", "ref": "refs/heads/master", - "rev": "657823c04eb7b392d3f71cf9047470e93fbed61a", - "revCount": 202, + "rev": "b28890d455676809e9130945ea267fa16b02d44d", + "revCount": 208, "type": "git", "url": "ssh://git@git.bitlab21.com/sam/nix-secrets.git" }, diff --git a/hosts/citadel/default.nix b/hosts/citadel/default.nix index 8795eb3..cf2ad82 100644 --- a/hosts/citadel/default.nix +++ b/hosts/citadel/default.nix @@ -16,7 +16,7 @@ else "/dev/root_vg/root"; user = "sam"; impermanence = true; - pieholeIp = configVars.networking.addresses.piehole.ip; + piholeIp = configVars.networking.addresses.pihole.ip; gatewayIp = configVars.networking.addresses.gateway.ip; in { imports = [ @@ -195,7 +195,7 @@ in { hostName = "citadel"; networkmanager.enable = true; enableIPv6 = false; - nameservers = ["${pieholeIp}" "${gatewayIp}" "8.8.8.8"]; + nameservers = ["${piholeIp}" "${gatewayIp}" "8.8.8.8"]; }; services.libinput.enable = true; diff --git a/hosts/common/optional/arion-containers/photoprism.nix b/hosts/common/optional/arion-containers/photoprism.nix new file mode 100644 index 0000000..55dae6c --- /dev/null +++ b/hosts/common/optional/arion-containers/photoprism.nix @@ -0,0 +1,79 @@ +{ + sops.secrets = { + "software/photoprism" = { + path = "/run/secrets/photoprism/config.yaml"; + mode = "0600"; + }; + }; + virtualisation.arion = { + backend = "podman-socket"; + projects.photoprism = { + settings = { + services.photoprism.service = { + ports = [ + "8096:8096" + ]; + container_name = "photoprism"; + image = "photoprism/photoprism:latest"; + restart = "always"; + depends_on = ["mariadb"]; + volumes = [ + "/media/photos/sam/originals:/photoprism/originals" + "/media/photos/sam/imports:/photoprism/import" + "/srv/docker/photoprism/storage:/photoprism/storage" + "/run/secrets/photoprism/config.yaml:/etc/photoprism/config.yaml" + ]; + environment = { + PHOTOPRISM_CONFIG_PATH = "/etc/photoprism/config.yaml"; + PHOTOPRISM_INIT = "intel"; + PHOTOPRISM_ORIGINALS_LIMIT = 5000; + PHOTOPRISM_HTTP_COMPRESSION = "gzip"; + PHOTOPRISM_DEBUG = "false"; + PHOTOPRISM_LOG = "trace"; + PHOTOPRISM_PUBLIC = "false"; + PHOTOPRISM_READONLY = "false"; + PHOTOPRISM_EXPERIMENTAL = "false"; + PHOTOPRISM_DISABLE_CHOWN = "false"; + PHOTOPRISM_DISABLE_WEBDAV = "false"; + PHOTOPRISM_DISABLE_SETTINGS = "false"; + PHOTOPRISM_DISABLE_TENSORFLOW = "false"; + PHOTOPRISM_DISABLE_FACES = "false"; + PHOTOPRISM_DISABLE_CLASSIFICATION = "false"; + PHOTOPRISM_DARKTABLE_PRESETS = "false"; + PHOTOPRISM_DETECT_NSFW = "false"; + PHOTOPRISM_UPLOAD_NSFW = "true"; + PHOTOPRISM_DATABASE_DRIVER = "mysql"; + PHOTOPRISM_DATABASE_SERVER = "mariadb:3306"; + PHOTOPRISM_DATABASE_NAME = "photoprism"; + PHOTOPRISM_DATABASE_USER = "photoprism"; + PHOTOPRISM_SITE_TITLE = "PhotoPrism"; + PHOTOPRISM_SITE_CAPTION = "AI-Powered Photos App"; + PHOTOPRISM_UID = 0; + PHOTOPRISM_GID = 0; + PHOTOPRISM_FFMPEG_ENCODER = "intel"; + PHOTOPRISM_FFMPEG_SIZE = "1920"; + PHOTOPRISM_FFMPEG_BITRATE = "50"; + HOME = "/photoprism"; + }; + devices = ["/dev/dri:/dev/dri"]; + }; + + services.mariadb.service = { + container_name = "photoprism-mariadb"; + image = "mariadb:10.11"; + restart = "always"; + command = "mysqld --innodb-buffer-pool-size=4G --innodb_log_file_size=1G --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120"; + volumes = [ + "/srv/docker/photoprism/database:/var/lib/mysql" + ]; + environment = { + MARIADB_AUTO_UPGRADE = "1"; + MARIADB_INITDB_SKIP_TZINFO = "1"; + MYSQL_DATABASE = "photoprism"; + MYSQL_USER = "photoprism"; + }; + }; + }; + }; + }; +} diff --git a/hosts/common/optional/arion-containers/pihole.nix b/hosts/common/optional/arion-containers/pihole.nix new file mode 100644 index 0000000..3636ed0 --- /dev/null +++ b/hosts/common/optional/arion-containers/pihole.nix @@ -0,0 +1,26 @@ +{ + virtualisation.arion = { + backend = "podman-socket"; + projects.pihole = { + settings = { + services.pihole.service = { + ports = [ + "53:53/tcp" + "53:53/udp" + "80:80/tcp" + ]; + container_name = "pihole"; + image = "pihole/pihole:latest"; + restart = "always"; + volumes = [ + "/srv/docker/pihole/etc-pihole:/etc/pihole" + "/srv/docker/pihole/etc-dnsmasq.d:/etc/dnsmasq.d" + ]; + environment = { + TZ = "Europe/London"; + }; + }; + }; + }; + }; +} diff --git a/hosts/common/optional/arion-containers/semitamaps-tileserver.nix b/hosts/common/optional/arion-containers/semitamaps-tileserver.nix new file mode 100644 index 0000000..c8c1d8f --- /dev/null +++ b/hosts/common/optional/arion-containers/semitamaps-tileserver.nix @@ -0,0 +1,31 @@ +{ + virtualisation.arion = { + backend = "podman-socket"; + projects.semitamaps-tileserver = { + settings = { + services.tileserver-gl.service = { + ports = [ + "8080:8080" + ]; + container_name = "tileserver-gl"; + image = "maptiler/tileserver-gl"; + restart = "always"; + volumes = [ + "/data/semitamaps-data/tileserver-gl/data:/data" + ]; + command = "-c /data/config.json --public_url https://tiles.semitamaps.com/"; + }; + + services.mbgl-renderer.service = { + ports = [ + "8081:80" + ]; + container_name = "mbgl-renderer"; + image = "mbgl-renderer"; + restart = "always"; + }; + }; + }; + }; +} + diff --git a/hosts/common/optional/nixos-containers/docker.nix b/hosts/common/optional/nixos-containers/docker.nix index f9a2ce9..874de43 100644 --- a/hosts/common/optional/nixos-containers/docker.nix +++ b/hosts/common/optional/nixos-containers/docker.nix @@ -140,6 +140,7 @@ in { sops-nix.nixosModules.sops ../arion-containers/arrstack.nix ../arion-containers/jellyfin.nix + ../arion-containers/photoprism.nix ]; environment.systemPackages = [ diff --git a/hosts/common/optional/nixos-containers/pihole.nix b/hosts/common/optional/nixos-containers/pihole.nix new file mode 100644 index 0000000..924c758 --- /dev/null +++ b/hosts/common/optional/nixos-containers/pihole.nix @@ -0,0 +1,119 @@ +{ + pkgs, + lib, + inputs, + configVars, + ... +}: let + containerName = "pihole"; + containerIp = configVars.networking.addresses.pihole.ip; + gatewayIp = configVars.networking.addresses.gateway.ip; + piholeContainerData = configVars.locations.dockerContainerData; + pubKeys = lib.filesystem.listFilesRecursive ../../users/keys; + arion = inputs.arion; +in { + networking.nat.enable = true; + networking.nat.internalInterfaces = ["ve-+"]; + networking.nat.externalInterface = "br0"; + + services.restic.backups = { + daily = { + paths = [ + piholeContainerData + ]; + exclude = [ + ]; + }; + }; + + environment.persistence."/persist" = { + hideMounts = true; + directories = [ + "/var/lib/nixos-containers/${containerName}" + ]; + }; + + containers."${containerName}" = { + enableTun = true; + + # configuration to run docker/podman in systemd-nspawn container + # https://discourse.nixos.org/t/podman-docker-in-nixos-container-ideally-in-unprivileged-one/22909/12 + additionalCapabilities = [ + ''all" --system-call-filter="add_key keyctl bpf" --capability="all'' + ]; + extraFlags = ["--private-users-ownership=chown"]; + allowedDevices = [ + ]; + ###### + + autoStart = true; + privateNetwork = true; + hostBridge = "br0"; + nixpkgs = pkgs.path; + bindMounts = { + "/srv/docker/pihole" = { + hostPath = piholeContainerData; + isReadOnly = false; + }; + }; + + config = { + pkgs, + lib, + ... + }: { + networking = { + defaultGateway = "${gatewayIp}"; + interfaces.eth0.ipv4.addresses = [ + { + "address" = "${containerIp}"; + "prefixLength" = 24; + } + ]; + firewall = { + enable = true; + allowedTCPPorts = [ + ]; + }; + useHostResolvConf = lib.mkForce false; + }; + + services.resolved.enable = true; + + imports = [ + arion.nixosModules.arion + ../arion-containers/pihole.nix + ]; + + environment.systemPackages = [ + pkgs.vim + pkgs.git + pkgs.arion + ]; + + virtualisation = { + podman = { + enable = true; + dockerSocket.enable = true; + defaultNetwork.settings.dns_enabled = true; + dockerCompat = true; + }; + }; + + networking.firewall.interfaces."podman+".allowedUDPPorts = [53]; + + services.openssh = { + enable = true; + settings.PasswordAuthentication = false; + }; + + users.users = { + root = { + openssh.authorizedKeys.keys = lib.lists.forEach pubKeys (key: builtins.readFile key); + }; + }; + + system.stateVersion = "24.05"; + }; + }; +} diff --git a/hosts/common/optional/nixos-containers/semitamaps-worker.nix b/hosts/common/optional/nixos-containers/semitamaps-worker.nix index 4522cae..0800157 100644 --- a/hosts/common/optional/nixos-containers/semitamaps-worker.nix +++ b/hosts/common/optional/nixos-containers/semitamaps-worker.nix @@ -11,6 +11,7 @@ semitamapsData = configVars.locations.semitamapsData; containerIp = configVars.networking.addresses.sm-worker.ip; gatewayIp = configVars.networking.addresses.gateway.ip; + arion = inputs.arion; in { networking.nat.enable = true; networking.nat.internalInterfaces = ["ve-+"]; @@ -33,30 +34,6 @@ in { ]; extraFlags = ["--private-users-ownership=chown"]; allowedDevices = [ - { - node = "/dev/fuse"; - modifier = "rwm"; - } - { - node = "/dev/mapper/control"; - modifier = "rw"; - } - { - node = "/dev/console"; - modifier = "rwm"; - } - { - node = "/dev/dri/card1"; - modifier = "rwm"; - } - { - node = "/dev/dri/renderD128"; - modifier = "rwm"; - } - { - node = "/dev/net/tun"; - modifier = "rw"; - } ]; ###### @@ -115,15 +92,14 @@ in { imports = [ sops-nix.nixosModules.sops + arion.nixosModules.arion + ../arion-containers/semitamaps-tileserver.nix ]; environment.systemPackages = [ pkgs.vim pkgs.git pkgs.arion - pkgs.dive - pkgs.podman-tui - pkgs.podman-compose pkgs.jdk ]; @@ -138,18 +114,6 @@ in { networking.firewall.interfaces."podman+".allowedUDPPorts = [53]; - systemd.services.podman-autostart = { - enable = true; - after = ["podman.service"]; - wantedBy = ["multi-user.target"]; - description = "Automatically start containers with --restart=always tag"; - serviceConfig = { - Type = "idle"; - ExecStartPre = ''${pkgs.coreutils}/bin/sleep 1''; - ExecStart = ''/run/current-system/sw/bin/podman start --all --filter restart-policy=always''; - }; - }; - systemd.services.photon = { wantedBy = ["multi-user.target"]; after = ["network.target"]; diff --git a/hosts/semita/default.nix b/hosts/semita/default.nix index 63ec365..78ddc29 100644 --- a/hosts/semita/default.nix +++ b/hosts/semita/default.nix @@ -15,7 +15,7 @@ else "/dev/root_vg/root"; user = "sam"; impermanence = true; - pieholeIp = configVars.networking.addresses.piehole.ip; + piholeIp = configVars.networking.addresses.pihole.ip; gatewayIp = configVars.networking.addresses.gateway.ip; semitaIp = configVars.networking.addresses.semita.ip; in { @@ -47,7 +47,7 @@ in { ../common/optional/pipewire.nix ../common/optional/openssh.nix ../common/optional/dwm.nix - ../common/optional/printing.nix + # ../common/optional/printing.nix ../common/optional/docker.nix ../common/optional/nix-ld.nix ../common/optional/gaming.nix @@ -65,6 +65,7 @@ in { ../common/optional/nixos-containers/semitamaps-worker.nix ../common/optional/nixos-containers/backup-server.nix ../common/optional/nixos-containers/docker.nix + # ../common/optional/nixos-containers/pihole.nix # # Build nix derivations on remote machine # ../common/optional/distributed-builds/local-machine.nix @@ -139,7 +140,7 @@ in { networking = { hostName = "semita"; - nameservers = ["${pieholeIp}" "${gatewayIp}" "8.8.8.8"]; + nameservers = ["${piholeIp}" "${gatewayIp}" "8.8.8.8"]; defaultGateway = "${gatewayIp}"; useDHCP = false; bridges = { diff --git a/hosts/sparky/default.nix b/hosts/sparky/default.nix index 4564812..692a36e 100644 --- a/hosts/sparky/default.nix +++ b/hosts/sparky/default.nix @@ -14,7 +14,7 @@ then "/dev/mapper/crypted" else "/dev/root_vg/root"; impermanence = true; - pieholeIp = configVars.networking.addresses.piehole.ip; + piholeIp = configVars.networking.addresses.pihole.ip; gatewayIp = configVars.networking.addresses.gateway.ip; in { imports = [ @@ -61,7 +61,7 @@ in { hostName = "sparky"; networkmanager.enable = true; enableIPv6 = false; - nameservers = ["${pieholeIp}" "${gatewayIp}" "8.8.8.8"]; + nameservers = ["${piholeIp}" "${gatewayIp}" "8.8.8.8"]; }; nixpkgs.config.allowUnfreePredicate = pkg: diff --git a/vars/default.nix b/vars/default.nix index 8307b2e..ab11a57 100644 --- a/vars/default.nix +++ b/vars/default.nix @@ -9,6 +9,7 @@ photosDataMountPoint = "/media/photos"; dockerContainerData = "/mnt/main-ssd/docker"; + piholeContainerData = "/mnt/main-ssd/docker/pihole"; bitcoinNodeContainerData = "/mnt/main-ssd/nix-bitcoin"; backupContainerData = "/mnt/main-ssd/backup"; postgresContainerData = "/mnt/main-ssd/postgresql";