diff --git a/flake.lock b/flake.lock index 45c3966..bd642ee 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,26 @@ { "nodes": { + "arion": { + "inputs": { + "flake-parts": "flake-parts", + "haskell-flake": "haskell-flake", + "hercules-ci-effects": "hercules-ci-effects", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1707923576, + "narHash": "sha256-vch1hvgoB2TEl1+0J9h5uPkTrL4zNFUxE/razagkqQQ=", + "owner": "hercules-ci", + "repo": "arion", + "rev": "2b1fa9a8e9e40bb8e65a677c6fdd66dae4f4676e", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "arion", + "type": "github" + } + }, "arkenfox": { "inputs": { "flake-compat": "flake-compat", @@ -62,7 +83,7 @@ }, "devshell": { "inputs": { - "nixpkgs": "nixpkgs_7", + "nixpkgs": "nixpkgs_8", "systems": "systems_5" }, "locked": { @@ -156,7 +177,10 @@ }, "flake-parts": { "inputs": { - "nixpkgs-lib": "nixpkgs-lib" + "nixpkgs-lib": [ + "arion", + "nixpkgs" + ] }, "locked": { "lastModified": 1706830856, @@ -173,6 +197,45 @@ } }, "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "arion", + "hercules-ci-effects", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1701473968, + "narHash": "sha256-YcVE5emp1qQ8ieHUnxt1wCZCC3ZfAS+SRRWZ2TMda7E=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "34fed993f1674c8d06d58b37ce1e0fe5eebcb9f5", + "type": "github" + }, + "original": { + "id": "flake-parts", + "type": "indirect" + } + }, + "flake-parts_3": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1706830856, + "narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_4": { "inputs": { "nixpkgs-lib": "nixpkgs-lib_3" }, @@ -243,7 +306,7 @@ }, "flatpaks": { "inputs": { - "nixpkgs": "nixpkgs_2", + "nixpkgs": "nixpkgs_3", "utils": "utils" }, "locked": { @@ -298,10 +361,26 @@ "type": "github" } }, + "haskell-flake": { + "locked": { + "lastModified": 1675296942, + "narHash": "sha256-u1X1sblozi5qYEcLp1hxcyo8FfDHnRUVX3dJ/tW19jY=", + "owner": "srid", + "repo": "haskell-flake", + "rev": "c2cafce9d57bfca41794dc3b99c593155006c71e", + "type": "github" + }, + "original": { + "owner": "srid", + "ref": "0.1.0", + "repo": "haskell-flake", + "type": "github" + } + }, "heliox-cli": { "inputs": { - "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_3", + "flake-parts": "flake-parts_3", + "nixpkgs": "nixpkgs_4", "systems": "systems_4", "treefmt-nix": "treefmt-nix" }, @@ -319,6 +398,28 @@ "url": "https://git.ghoscht.com/heliox/cli/" } }, + "hercules-ci-effects": { + "inputs": { + "flake-parts": "flake-parts_2", + "nixpkgs": [ + "arion", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1704029560, + "narHash": "sha256-a4Iu7x1OP+uSYpqadOu8VCPY+MPF3+f6KIi+MAxlgyw=", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "rev": "d5cbf433a6ae9cae05400189a8dbc6412a03ba16", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -342,7 +443,7 @@ }, "home-manager_2": { "inputs": { - "nixpkgs": "nixpkgs_8" + "nixpkgs": "nixpkgs_9" }, "locked": { "lastModified": 1701071203, @@ -361,7 +462,7 @@ "hyprland": { "inputs": { "hyprland-protocols": "hyprland-protocols", - "nixpkgs": "nixpkgs_9", + "nixpkgs": "nixpkgs_10", "systems": "systems_6", "wlroots": "wlroots", "xdph": "xdph" @@ -448,16 +549,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1704842529, - "narHash": "sha256-OTeQA+F8d/Evad33JMfuXC89VMetQbsU4qcaePchGr4=", + "lastModified": 1707689078, + "narHash": "sha256-UUGmRa84ZJHpGZ1WZEBEUOzaPOWG8LZ0yPg1pdDF/yM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "eabe8d3eface69f5bb16c18f8662a702f50c20d5", + "rev": "f9d39fb9aff0efee4a3d5f4a6d7c17701d38a1d8", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } @@ -562,6 +663,22 @@ } }, "nixpkgs_10": { + "locked": { + "lastModified": 1700612854, + "narHash": "sha256-yrQ8osMD+vDLGFX7pcwsY/Qr5PUd6OmDMYJZzZi0+zc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "19cbff58383a4ae384dea4d1d0c823d72b49d614", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_11": { "locked": { "lastModified": 1701336116, "narHash": "sha256-kEmpezCR/FpITc6yMbAh4WrOCiT2zg5pSjnKrq51h5Y=", @@ -578,6 +695,22 @@ } }, "nixpkgs_2": { + "locked": { + "lastModified": 1704842529, + "narHash": "sha256-OTeQA+F8d/Evad33JMfuXC89VMetQbsU4qcaePchGr4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabe8d3eface69f5bb16c18f8662a702f50c20d5", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { "locked": { "lastModified": 1706098335, "narHash": "sha256-r3dWjT8P9/Ah5m5ul4WqIWD8muj5F+/gbCdjiNVBKmU=", @@ -593,7 +726,7 @@ "type": "github" } }, - "nixpkgs_3": { + "nixpkgs_4": { "locked": { "lastModified": 1706732774, "narHash": "sha256-hqJlyJk4MRpcItGYMF+3uHe8HvxNETWvlGtLuVpqLU0=", @@ -609,7 +742,7 @@ "type": "github" } }, - "nixpkgs_4": { + "nixpkgs_5": { "locked": { "lastModified": 1705856552, "narHash": "sha256-JXfnuEf5Yd6bhMs/uvM67/joxYKoysyE3M2k6T3eWbg=", @@ -625,7 +758,7 @@ "type": "github" } }, - "nixpkgs_5": { + "nixpkgs_6": { "locked": { "lastModified": 1709218635, "narHash": "sha256-nytX/MkfqeTD4z7bMq4QRXcHxO9B3vRo9tM6fMtPFA8=", @@ -641,7 +774,7 @@ "type": "github" } }, - "nixpkgs_6": { + "nixpkgs_7": { "locked": { "lastModified": 1709356872, "narHash": "sha256-mvxCirJbtkP0cZ6ABdwcgTk0u3bgLoIoEFIoYBvD6+4=", @@ -657,7 +790,7 @@ "type": "github" } }, - "nixpkgs_7": { + "nixpkgs_8": { "locked": { "lastModified": 1677383253, "narHash": "sha256-UfpzWfSxkfXHnb4boXZNaKsAcUrZT9Hw+tao1oZxd08=", @@ -673,7 +806,7 @@ "type": "github" } }, - "nixpkgs_8": { + "nixpkgs_9": { "locked": { "lastModified": 1700794826, "narHash": "sha256-RyJTnTNKhO0yqRpDISk03I/4A67/dp96YRxc86YOPgU=", @@ -689,28 +822,12 @@ "type": "github" } }, - "nixpkgs_9": { - "locked": { - "lastModified": 1700612854, - "narHash": "sha256-yrQ8osMD+vDLGFX7pcwsY/Qr5PUd6OmDMYJZzZi0+zc=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "19cbff58383a4ae384dea4d1d0c823d72b49d614", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, "pre-commit": { "inputs": { "flake-compat": "flake-compat_2", "flake-utils": "flake-utils_2", "gitignore": "gitignore", - "nixpkgs": "nixpkgs", + "nixpkgs": "nixpkgs_2", "nixpkgs-stable": "nixpkgs-stable" }, "locked": { @@ -729,6 +846,7 @@ }, "root": { "inputs": { + "arion": "arion", "arkenfox": "arkenfox", "disko": "disko", "firefox-addons": "firefox-addons", @@ -738,7 +856,7 @@ "home-manager": "home-manager", "nh": "nh", "nix-colors": "nix-colors", - "nixpkgs": "nixpkgs_5", + "nixpkgs": "nixpkgs_6", "nixpkgs-unstable": "nixpkgs-unstable", "sops-nix": "sops-nix", "xremap": "xremap" @@ -746,7 +864,7 @@ }, "sops-nix": { "inputs": { - "nixpkgs": "nixpkgs_6", + "nixpkgs": "nixpkgs_7", "nixpkgs-stable": "nixpkgs-stable_2" }, "locked": { @@ -855,7 +973,7 @@ }, "treefmt-nix": { "inputs": { - "nixpkgs": "nixpkgs_4" + "nixpkgs": "nixpkgs_5" }, "locked": { "lastModified": 1706462057, @@ -944,10 +1062,10 @@ "inputs": { "crane": "crane", "devshell": "devshell", - "flake-parts": "flake-parts_2", + "flake-parts": "flake-parts_4", "home-manager": "home-manager_2", "hyprland": "hyprland", - "nixpkgs": "nixpkgs_10", + "nixpkgs": "nixpkgs_11", "xremap": "xremap_2" }, "locked": { diff --git a/flake.nix b/flake.nix index 45cf3c6..e199c53 100644 --- a/flake.nix +++ b/flake.nix @@ -37,6 +37,7 @@ flatpaks.url = "github:GermanBread/declarative-flatpak/stable"; heliox-cli.url = "git+https://git.ghoscht.com/heliox/cli/"; sops-nix.url = "github:Mic92/sops-nix"; + arion.url = "github:hercules-ci/arion"; }; outputs = { diff --git a/hosts/franz/arion/default.nix b/hosts/franz/arion/default.nix new file mode 100644 index 0000000..3cab51a --- /dev/null +++ b/hosts/franz/arion/default.nix @@ -0,0 +1,45 @@ +{ + inputs, + pkgs, + config, + ... +}: { + imports = [inputs.arion.nixosModules.arion]; + + environment.systemPackages = with pkgs; [arion]; + + virtualisation.arion = { + backend = "docker"; + projects = { + infrastructure.settings = { + imports = [./infrastructure/arion-compose.nix]; + }; + dns.settings = { + imports = [./dns/arion-compose.nix]; + }; + push.settings = { + imports = [./push/arion-compose.nix]; + }; + }; + }; + + systemd.services.init-dmz-bridge-network = { + description = "Create the network bridge dmz for the Docker stack."; + after = ["network.target"]; + wantedBy = ["multi-user.target"]; + + serviceConfig.Type = "oneshot"; + script = let + dockercli = "${config.virtualisation.docker.package}/bin/docker"; + in '' + # Put a true at the end to prevent getting non-zero return code, which will + # crash the whole service. + check=$(${dockercli} network ls | grep "dmz" || true) + if [ -z "$check" ]; then + ${dockercli} network create dmz + else + echo "dmz already exists in docker" + fi + ''; + }; +} diff --git a/hosts/franz/arion/dns/arion-compose.nix b/hosts/franz/arion/dns/arion-compose.nix new file mode 100644 index 0000000..63df1a6 --- /dev/null +++ b/hosts/franz/arion/dns/arion-compose.nix @@ -0,0 +1,81 @@ +{pkgs, ...}: { + project.name = "dns"; + + networks.dmz = { + name = "dmz"; + external = true; + }; + + networks.dns = { + name = "dns"; + driver = "bridge"; + ipam.config = [ + { + subnet = "172.28.1.0/24"; + ip_range = "172.28.1.5/30"; + gateway = "172.28.1.1"; + } + ]; + }; + + services = { + pihole.service = { + image = "pihole/pihole:latest"; + container_name = "pihole"; + environment = { + IPv6 = "True"; + TZ = "Europe/Berlin"; + SKIPGRAVITYONBOOT = 1; + VIRTUAL_HOST = "pihole.ghoscht.com"; + }; + volumes = [ + "/home/ghoscht/.docker/dns/pihole_data:/etc/pihole" + "/home/ghoscht/.docker/dns/pihole_dnsmasq:/etc/dnsmasq.d" + ]; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.pihole.entrypoints" = "websecure"; + "traefik.http.routers.pihole.rule" = "Host(`pihole.ghoscht.com`)"; + "traefik.http.services.pihole.loadbalancer.server.port" = "80"; + "traefik.docker.network" = "traefik-net"; + "traefik.http.routers.pihole.tls" = "true"; + "traefik.http.routers.pihole.tls.certresolver" = "letsencrypt"; + }; + restart = "always"; + networks = { + dmz = {}; + dns = { + ipv4_address = "172.28.1.6"; + }; + }; + dns = [ + "1.1.1.1" + ]; + capabilities = { + NET_ADMIN = true; + }; + ports = [ + "8420:80" + "53:53/tcp" + "53:53/udp" + ]; + }; + unbound.service = { + image = "mvance/unbound:latest"; + container_name = "unbound"; + useHostStore = true; + volumes = [ + "/home/ghoscht/.docker/dns/unbound_data:/opt/unbound/etc/unbound" + ]; + restart = "always"; + networks = { + dns = { + ipv4_address = "172.28.1.5"; + }; + }; + dns = [ + "1.1.1.1" + ]; + }; + }; +} diff --git a/hosts/franz/arion/dns/arion-pkgs.nix b/hosts/franz/arion/dns/arion-pkgs.nix new file mode 100644 index 0000000..69aad13 --- /dev/null +++ b/hosts/franz/arion/dns/arion-pkgs.nix @@ -0,0 +1,6 @@ +# Instead of pinning Nixpkgs, we can opt to use the one in NIX_PATH +import { + # We specify the architecture explicitly. Use a Linux remote builder when + # calling arion from other platforms. + system = "x86_64-linux"; +} diff --git a/hosts/franz/arion/infrastructure/arion-compose.nix b/hosts/franz/arion/infrastructure/arion-compose.nix new file mode 100644 index 0000000..d3a3042 --- /dev/null +++ b/hosts/franz/arion/infrastructure/arion-compose.nix @@ -0,0 +1,84 @@ +{pkgs, ...}: { + project.name = "infrastructure"; + + networks.dmz = { + name = "dmz"; + external = true; + }; + + docker-compose.volumes = { + traefik_letsencrypt = null; + scrutiny_data = null; + scrutiny_db = null; + }; + + services = { + traefik.service = { + image = "traefik"; + container_name = "traefik"; + useHostStore = true; + ports = [ + "80:80" + "443:443" + "8421:8080" + ]; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.dashboard.rule" = "Host(`traefik.ghoscht.com`)"; + "traefik.http.routers.dashboard.entrypoints" = "websecure"; + "traefik.http.services.dashboard.loadbalancer.server.port" = "8080"; + "traefik.http.routers.dashboard.tls" = "true"; + "traefik.http.routers.dashboard.tls.certresolver" = "letsencrypt"; + }; + volumes = [ + "traefik_letsencrypt:/letsencrypt" + "/home/ghoscht/.docker/infrastructure/traefik_data:/etc/traefik" + "/var/run/docker.sock:/var/run/docker.sock:ro" + ]; + env_file = [ + "/home/ghoscht/.docker/infrastructure/traefik.env" + ]; + restart = "always"; + networks = [ + "dmz" + ]; + }; + cloudflared.service = { + image = "cloudflare/cloudflared:latest"; + container_name = "cloudflared"; + env_file = [ + "/home/ghoscht/.docker/infrastructure/cloudflared.env" + ]; + restart = "always"; + command = "tunnel --no-autoupdate --protocol http2 run"; + networks = [ + "dmz" + ]; + }; + scrutiny.service = { + image = "ghcr.io/analogj/scrutiny:master-omnibus"; + container_name = "scrutiny"; + restart = "always"; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.scrutiny.entrypoints" = "websecure"; + "traefik.http.routers.scrutiny.rule" = "Host(`scrutiny.ghoscht.com`)"; + "traefik.http.services.scrutiny.loadbalancer.server.port" = "8080"; + "traefik.http.routers.scrutiny.tls" = "true"; + "traefik.http.routers.scrutiny.tls.certresolver" = "letsencrypt"; + }; + capabilities = { + SYS_RAWIO = true; + }; + volumes = [ + "/run/udev:/run/udev:ro" + "scrutiny_data:/opt/scrutiny/config" + "scrutiny_db:/opt/scrutiny/influxdb" + ]; + devices = []; + networks = [ + "dmz" + ]; + }; + }; +} diff --git a/hosts/franz/arion/infrastructure/arion-pkgs.nix b/hosts/franz/arion/infrastructure/arion-pkgs.nix new file mode 100644 index 0000000..69aad13 --- /dev/null +++ b/hosts/franz/arion/infrastructure/arion-pkgs.nix @@ -0,0 +1,6 @@ +# Instead of pinning Nixpkgs, we can opt to use the one in NIX_PATH +import { + # We specify the architecture explicitly. Use a Linux remote builder when + # calling arion from other platforms. + system = "x86_64-linux"; +} diff --git a/hosts/franz/arion/push/arion-compose.nix b/hosts/franz/arion/push/arion-compose.nix new file mode 100644 index 0000000..c80523b --- /dev/null +++ b/hosts/franz/arion/push/arion-compose.nix @@ -0,0 +1,35 @@ +{pkgs, ...}: { + project.name = "push"; + + networks.dmz = { + name = "dmz"; + external = true; + }; + + services = { + ntfy.service = { + image = "binwiederhier/ntfy"; + container_name = "ntfy"; + user = "1000:1000"; + command = "serve"; + useHostStore = true; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.ntfy.entrypoints" = "websecure"; + "traefik.http.routers.ntfy.rule" = "Host(`push.ghoscht.com`)"; + "traefik.http.routers.ntfy.tls" = "true"; + "traefik.http.routers.ntfy.tls.certresolver" = "letsencrypt"; + }; + volumes = [ + "/home/ghoscht/.docker/push/ntfy_data/server.yml:/etc/ntfy/server.yml" + ]; + environment = { + TZ = "Europe/Berlin"; + }; + restart = "always"; + networks = [ + "dmz" + ]; + }; + }; +} diff --git a/hosts/franz/arion/push/arion-pkgs.nix b/hosts/franz/arion/push/arion-pkgs.nix new file mode 100644 index 0000000..69aad13 --- /dev/null +++ b/hosts/franz/arion/push/arion-pkgs.nix @@ -0,0 +1,6 @@ +# Instead of pinning Nixpkgs, we can opt to use the one in NIX_PATH +import { + # We specify the architecture explicitly. Use a Linux remote builder when + # calling arion from other platforms. + system = "x86_64-linux"; +} diff --git a/hosts/franz/default.nix b/hosts/franz/default.nix index 88074ac..5a6c7e0 100644 --- a/hosts/franz/default.nix +++ b/hosts/franz/default.nix @@ -22,7 +22,7 @@ in { ../common/optional/docker.nix ../common/optional/vsftpd.nix ./sops.nix - ./docker.nix + ./arion ]; users.mutableUsers = true; diff --git a/hosts/franz/docker.nix b/hosts/franz/docker.nix deleted file mode 100644 index c4756cf..0000000 --- a/hosts/franz/docker.nix +++ /dev/null @@ -1,21 +0,0 @@ -{config, ...}: { - systemd.services.init-traefik-net-bridge-network = { - description = "Create the network bridge traefik-net for the Docker stack."; - after = ["network.target"]; - wantedBy = ["multi-user.target"]; - - serviceConfig.Type = "oneshot"; - script = let - dockercli = "${config.virtualisation.docker.package}/bin/docker"; - in '' - # Put a true at the end to prevent getting non-zero return code, which will - # crash the whole service. - check=$(${dockercli} network ls | grep "traefik-net" || true) - if [ -z "$check" ]; then - ${dockercli} network create traefik-net - else - echo "traefik-net already exists in docker" - fi - ''; - }; -} diff --git a/hosts/franz/sops.nix b/hosts/franz/sops.nix index 9005ad8..0e72d14 100644 --- a/hosts/franz/sops.nix +++ b/hosts/franz/sops.nix @@ -20,6 +20,9 @@ in { owner = vars.user; }; + sops.secrets."traefik/acme_email" = { + owner = vars.user; + }; sops.secrets."traefik/cloudflare_email" = { owner = vars.user; }; @@ -40,31 +43,65 @@ in { owner = vars.user; }; - systemd.services.docker-env-secrets = { - description = "Populate the .env files for the docker stack with values from SOPS"; - after = ["home-manager-${vars.user}.service"]; - wantedBy = ["multi-user.target"]; - - script = '' - echo " - TUNNEL_TOKEN="$(cat ${config.sops.secrets."cloudflared/tunnel_token".path})" - " > /home/${vars.user}/.docker/infrastructure/cloudflared.env - - echo " - CLOUDFLARE_EMAIL="$(cat ${config.sops.secrets."traefik/cloudflare_email".path})" - CLOUDFLARE_API_KEY="$(cat ${config.sops.secrets."traefik/cloudflare_api_key".path})" - " > /home/${vars.user}/.docker/infrastructure/traefik.env - - echo " - MYSQL_ROOT_PASSWORD="$(cat ${config.sops.secrets."nextcloud/mysql_root_password".path})" - MYSQL_PASSWORD="$(cat ${config.sops.secrets."nextcloud/mysql_password".path})" - MYSQL_DATABASE="$(cat ${config.sops.secrets."nextcloud/mysql_database".path})" - MYSQL_USER="$(cat ${config.sops.secrets."nextcloud/mysql_user".path})" - " > /home/${vars.user}/.docker/nas/nextcloud.env + sops.templates."cloudflared.env" = { + path = "/home/${vars.user}/.docker/infrastructure/cloudflared.env"; + owner = vars.user; + mode = "0775"; + content = '' + TUNNEL_TOKEN="${config.sops.placeholder."cloudflared/tunnel_token"}" + ''; + }; + + sops.templates."traefik.env" = { + path = "/home/${vars.user}/.docker/infrastructure/traefik.env"; + owner = vars.user; + mode = "0775"; + content = '' + CLOUDFLARE_EMAIL="${config.sops.placeholder."traefik/cloudflare_email"}" + CLOUDFLARE_API_KEY="${config.sops.placeholder."traefik/cloudflare_api_key"}" + ''; + }; + + sops.templates."nextcloud.env" = { + path = "/home/${vars.user}/.docker/nas/nextcloud.env"; + owner = vars.user; + mode = "0775"; + content = '' + MYSQL_ROOT_PASSWORD="${config.sops.placeholder."nextcloud/mysql_root_password"}" + MYSQL_PASSWORD="${config.sops.placeholder."nextcloud/mysql_password"}" + MYSQL_DATABASE="${config.sops.placeholder."nextcloud/mysql_database"}" + MYSQL_USER="${config.sops.placeholder."nextcloud/mysql_user"}" + ''; + }; + + sops.templates."traefik.toml" = { + path = "/home/${vars.user}/.docker/infrastructure/traefik_data/traefik.toml"; + owner = vars.user; + mode = "0775"; + content = '' + [entryPoints] + [entryPoints.web] + address = ":80" + [entryPoints.websecure] + address = ":443" + [api] + dashboard = true + insecure = true + + [certificatesResolvers.letsencrypt.acme] + email = "${config.sops.placeholder."traefik/acme_email"}" + storage = "/letsencrypt/acme.json" + [certificatesResolvers.letsencrypt.acme.dnsChallenge] + provider = "cloudflare" + resolvers = ["1.1.1.1:53", "1.0.0.1:53"] + + [serversTransport] + insecureSkipVerify = true + + [providers.docker] + watch = true + network = "web" + exposedByDefault = false ''; - serviceConfig = { - User = "ghoscht"; - WorkingDirectory = "/home/${vars.user}/.docker"; - }; }; } diff --git a/rsc/docker/franz/dns/docker-compose.yml b/rsc/docker/franz/dns/docker-compose.yml index 77841a9..7db1c59 100644 --- a/rsc/docker/franz/dns/docker-compose.yml +++ b/rsc/docker/franz/dns/docker-compose.yml @@ -5,8 +5,8 @@ services: hostname: pihole image: pihole/pihole:latest volumes: - - pihole_dnsmasq:/etc/dnsmasq.d - - pihole_data:/etc/pihole + - ./pihole_dnsmasq:/etc/dnsmasq.d + - ./pihole_data:/etc/pihole restart: always environment: - IPv6=True @@ -38,7 +38,7 @@ services: container_name: unbound image: mvance/unbound:latest volumes: - - unbound_data:/opt/unbound/etc/unbound + - ./unbound_data:/opt/unbound/etc/unbound dns: - 1.1.1.1 restart: always @@ -58,10 +58,3 @@ networks: - subnet: 172.28.1.0/24 ip_range: 172.28.1.5/30 gateway: 172.28.1.1 -volumes: - pihole_dnsmasq: - name: pihole_dnsmasq - pihole_data: - name: pihole_data - unbound_data: - name: unbound_data diff --git a/rsc/docker/franz/dns/unbound_data/a-records.conf b/rsc/docker/franz/dns/unbound_data/a-records.conf new file mode 100644 index 0000000..0795015 --- /dev/null +++ b/rsc/docker/franz/dns/unbound_data/a-records.conf @@ -0,0 +1,6 @@ +# A Record + #local-data: "somecomputer.local. A 192.168.1.1" + +# PTR Record + #local-data-ptr: "192.168.1.1 somecomputer.local." + diff --git a/rsc/docker/franz/dns/unbound_data/forward-records.conf b/rsc/docker/franz/dns/unbound_data/forward-records.conf new file mode 100644 index 0000000..8159fce --- /dev/null +++ b/rsc/docker/franz/dns/unbound_data/forward-records.conf @@ -0,0 +1,48 @@ +forward-zone: + # Forward all queries (except those in cache and local zone) to + # upstream recursive servers + name: "." + # Queries to this forward zone use TLS + forward-tls-upstream: yes + + # https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Test+Servers + + ## Cloudflare + forward-addr: 1.1.1.1@853#cloudflare-dns.com + forward-addr: 1.0.0.1@853#cloudflare-dns.com + #forward-addr: 2606:4700:4700::1111@853#cloudflare-dns.com + #forward-addr: 2606:4700:4700::1001@853#cloudflare-dns.com + + ## CleanBrowsing Security Filter + # forward-addr: 185.228.168.9@853#security-filter-dns.cleanbrowsing.org + # forward-addr: 185.228.169.9@853#security-filter-dns.cleanbrowsing.org + # forward-addr: 2a0d:2a00:1::2@853#security-filter-dns.cleanbrowsing.org + # forward-addr: 2a0d:2a00:2::2@853#security-filter-dns.cleanbrowsing.org + + ## CleanBrowsing Adult Filter + # forward-addr: 185.228.168.10@853#adult-filter-dns.cleanbrowsing.org + # forward-addr: 185.228.169.11@853#adult-filter-dns.cleanbrowsing.org + # forward-addr: 2a0d:2a00:1::1@853#adult-filter-dns.cleanbrowsing.org + # forward-addr: 2a0d:2a00:2::1@853#adult-filter-dns.cleanbrowsing.org + + ## CleanBrowsing Family Filter + # forward-addr: 185.228.168.168@853#family-filter-dns.cleanbrowsing.org + # forward-addr: 185.228.169.168@853#family-filter-dns.cleanbrowsing.org + # forward-addr: 2a0d:2a00:1::@853#family-filter-dns.cleanbrowsing.org + # forward-addr: 2a0d:2a00:2::@853#family-filter-dns.cleanbrowsing.org + + ## Quad9 + # forward-addr: 9.9.9.9@853#dns.quad9.net + # forward-addr: 149.112.112.112@853#dns.quad9.net + # forward-addr: 2620:fe::fe@853#dns.quad9.net + # forward-addr: 2620:fe::9@853#dns.quad9.net + + ## getdnsapi.net + # forward-addr: 185.49.141.37@853#getdnsapi.net + # forward-addr: 2a04:b900:0:100::37@853#getdnsapi.net + + ## Surfnet + # forward-addr: 145.100.185.15@853#dnsovertls.sinodun.com + # forward-addr: 145.100.185.16@853#dnsovertls1.sinodun.com + # forward-addr: 2001:610:1:40ba:145:100:185:15@853#dnsovertls.sinodun.com + # forward-addr: 2001:610:1:40ba:145:100:185:16@853#dnsovertls1.sinodun.com diff --git a/rsc/docker/franz/dns/unbound_data/srv-records.conf b/rsc/docker/franz/dns/unbound_data/srv-records.conf new file mode 100644 index 0000000..fccdd51 --- /dev/null +++ b/rsc/docker/franz/dns/unbound_data/srv-records.conf @@ -0,0 +1,2 @@ +# SRV records +# _service._proto.name. | TTL | class | SRV | priority | weight | port | target. diff --git a/rsc/docker/franz/dns/unbound_data/unbound.conf b/rsc/docker/franz/dns/unbound_data/unbound.conf new file mode 100644 index 0000000..2342b91 --- /dev/null +++ b/rsc/docker/franz/dns/unbound_data/unbound.conf @@ -0,0 +1,308 @@ +server: + ########################################################################### + # BASIC SETTINGS + ########################################################################### + # Time to live maximum for RRsets and messages in the cache. If the maximum + # kicks in, responses to clients still get decrementing TTLs based on the + # original (larger) values. When the internal TTL expires, the cache item + # has expired. Can be set lower to force the resolver to query for data + # often, and not trust (very large) TTL values. + cache-max-ttl: 86400 + + # Time to live minimum for RRsets and messages in the cache. If the minimum + # kicks in, the data is cached for longer than the domain owner intended, + # and thus less queries are made to look up the data. Zero makes sure the + # data in the cache is as the domain owner intended, higher values, + # especially more than an hour or so, can lead to trouble as the data in + # the cache does not match up with the actual data any more. + cache-min-ttl: 300 + + # Set the working directory for the program. + directory: "/opt/unbound/etc/unbound" + + # RFC 6891. Number of bytes size to advertise as the EDNS reassembly buffer + # size. This is the value put into datagrams over UDP towards peers. + # The actual buffer size is determined by msg-buffer-size (both for TCP and + # UDP). Do not set higher than that value. + # Default is 1232 which is the DNS Flag Day 2020 recommendation. + # Setting to 512 bypasses even the most stringent path MTU problems, but + # is seen as extreme, since the amount of TCP fallback generated is + # excessive (probably also for this resolver, consider tuning the outgoing + # tcp number). + edns-buffer-size: 1232 + + # Listen to for queries from clients and answer from this network interface + # and port. + interface: 0.0.0.0@53 + + # Rotates RRSet order in response (the pseudo-random number is taken from + # the query ID, for speed and thread safety). + rrset-roundrobin: yes + + # Drop user privileges after binding the port. + username: "_unbound" + + ########################################################################### + # LOGGING + ########################################################################### + + # Do not print log lines to inform about local zone actions + log-local-actions: no + + # Do not print one line per query to the log + log-queries: no + + # Do not print one line per reply to the log + log-replies: no + + # Do not print log lines that say why queries return SERVFAIL to clients + log-servfail: no + + # Further limit logging + logfile: /dev/null + + # Only log errors + verbosity: 0 + + ########################################################################### + # PRIVACY SETTINGS + ########################################################################### + + # RFC 8198. Use the DNSSEC NSEC chain to synthesize NXDO-MAIN and other + # denials, using information from previous NXDO-MAINs answers. In other + # words, use cached NSEC records to generate negative answers within a + # range and positive answers from wildcards. This increases performance, + # decreases latency and resource utilization on both authoritative and + # recursive servers, and increases privacy. Also, it may help increase + # resilience to certain DoS attacks in some circumstances. + aggressive-nsec: yes + + # Extra delay for timeouted UDP ports before they are closed, in msec. + # This prevents very delayed answer packets from the upstream (recursive) + # servers from bouncing against closed ports and setting off all sort of + # close-port counters, with eg. 1500 msec. When timeouts happen you need + # extra sockets, it checks the ID and remote IP of packets, and unwanted + # packets are added to the unwanted packet counter. + delay-close: 10000 + + # Prevent the unbound server from forking into the background as a daemon + do-daemonize: no + + # Add localhost to the do-not-query-address list. + do-not-query-localhost: no + + # Number of bytes size of the aggressive negative cache. + neg-cache-size: 4M + + # Send minimum amount of information to upstream servers to enhance + # privacy (best privacy). + qname-minimisation: yes + + ########################################################################### + # SECURITY SETTINGS + ########################################################################### + # Only give access to recursion clients from LAN IPs + access-control: 127.0.0.1/32 allow + access-control: 192.168.0.0/16 allow + access-control: 172.16.0.0/12 allow + access-control: 10.0.0.0/8 allow + # access-control: fc00::/7 allow + # access-control: ::1/128 allow + + # File with trust anchor for one zone, which is tracked with RFC5011 + # probes. + auto-trust-anchor-file: "var/root.key" + + # Enable chroot (i.e, change apparent root directory for the current + # running process and its children) + chroot: "/opt/unbound/etc/unbound" + + # Deny queries of type ANY with an empty response. + deny-any: yes + + # Harden against algorithm downgrade when multiple algorithms are + # advertised in the DS record. + harden-algo-downgrade: yes + + # RFC 8020. returns nxdomain to queries for a name below another name that + # is already known to be nxdomain. + harden-below-nxdomain: yes + + # Require DNSSEC data for trust-anchored zones, if such data is absent, the + # zone becomes bogus. If turned off you run the risk of a downgrade attack + # that disables security for a zone. + harden-dnssec-stripped: yes + + # Only trust glue if it is within the servers authority. + harden-glue: yes + + # Ignore very large queries. + harden-large-queries: yes + + # Perform additional queries for infrastructure data to harden the referral + # path. Validates the replies if trust anchors are configured and the zones + # are signed. This enforces DNSSEC validation on nameserver NS sets and the + # nameserver addresses that are encountered on the referral path to the + # answer. Experimental option. + harden-referral-path: no + + # Ignore very small EDNS buffer sizes from queries. + harden-short-bufsize: yes + + # Refuse id.server and hostname.bind queries + hide-identity: yes + + # Refuse version.server and version.bind queries + hide-version: yes + + # Report this identity rather than the hostname of the server. + identity: "DNS" + + # These private network addresses are not allowed to be returned for public + # internet names. Any occurrence of such addresses are removed from DNS + # answers. Additionally, the DNSSEC validator may mark the answers bogus. + # This protects against DNS Rebinding + private-address: 10.0.0.0/8 + private-address: 172.16.0.0/12 + private-address: 192.168.0.0/16 + private-address: 169.254.0.0/16 + # private-address: fd00::/8 + # private-address: fe80::/10 + # private-address: ::ffff:0:0/96 + + # Enable ratelimiting of queries (per second) sent to nameserver for + # performing recursion. More queries are turned away with an error + # (servfail). This stops recursive floods (e.g., random query names), but + # not spoofed reflection floods. Cached responses are not rate limited by + # this setting. Experimental option. + ratelimit: 1000 + + # Use this certificate bundle for authenticating connections made to + # outside peers (e.g., auth-zone urls, DNS over TLS connections). + tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt + + # Set the total number of unwanted replies to eep track of in every thread. + # When it reaches the threshold, a defensive action of clearing the rrset + # and message caches is taken, hopefully flushing away any poison. + # Unbound suggests a value of 10 million. + unwanted-reply-threshold: 10000 + + # Use 0x20-encoded random bits in the query to foil spoof attempts. This + # perturbs the lowercase and uppercase of query names sent to authority + # servers and checks if the reply still has the correct casing. + # This feature is an experimental implementation of draft dns-0x20. + # Experimental option. + use-caps-for-id: yes + + # Help protect users that rely on this validator for authentication from + # potentially bad data in the additional section. Instruct the validator to + # remove data from the additional section of secure messages that are not + # signed properly. Messages that are insecure, bogus, indeterminate or + # unchecked are not affected. + val-clean-additional: yes + + ########################################################################### + # PERFORMANCE SETTINGS + ########################################################################### + # https://nlnetlabs.nl/documentation/unbound/howto-optimise/ + # https://nlnetlabs.nl/news/2019/Feb/05/unbound-1.9.0-released/ + + # Number of slabs in the infrastructure cache. Slabs reduce lock contention + # by threads. Must be set to a power of 2. + infra-cache-slabs: 4 + + # Number of incoming TCP buffers to allocate per thread. Default + # is 10. If set to 0, or if do-tcp is "no", no TCP queries from + # clients are accepted. For larger installations increasing this + # value is a good idea. + incoming-num-tcp: 10 + + # Number of slabs in the key cache. Slabs reduce lock contention by + # threads. Must be set to a power of 2. Setting (close) to the number + # of cpus is a reasonable guess. + key-cache-slabs: 4 + + # Number of bytes size of the message cache. + # Unbound recommendation is to Use roughly twice as much rrset cache memory + # as you use msg cache memory. + msg-cache-size: 120634709 + + # Number of slabs in the message cache. Slabs reduce lock contention by + # threads. Must be set to a power of 2. Setting (close) to the number of + # cpus is a reasonable guess. + msg-cache-slabs: 4 + + # The number of queries that every thread will service simultaneously. If + # more queries arrive that need servicing, and no queries can be jostled + # out (see jostle-timeout), then the queries are dropped. + # This is best set at half the number of the outgoing-range. + # This Unbound instance was compiled with libevent so it can efficiently + # use more than 1024 file descriptors. + num-queries-per-thread: 4096 + + # The number of threads to create to serve clients. + # This is set dynamically at run time to effectively use available CPUs + # resources + num-threads: 3 + + # Number of ports to open. This number of file descriptors can be opened + # per thread. + # This Unbound instance was compiled with libevent so it can efficiently + # use more than 1024 file descriptors. + outgoing-range: 8192 + + # Number of bytes size of the RRset cache. + # Use roughly twice as much rrset cache memory as msg cache memory + rrset-cache-size: 241269418 + + # Number of slabs in the RRset cache. Slabs reduce lock contention by + # threads. Must be set to a power of 2. + rrset-cache-slabs: 4 + + # Do no insert authority/additional sections into response messages when + # those sections are not required. This reduces response size + # significantly, and may avoid TCP fallback for some responses. This may + # cause a slight speedup. + minimal-responses: yes + + # # Fetch the DNSKEYs earlier in the validation process, when a DS record + # is encountered. This lowers the latency of requests at the expense of + # little more CPU usage. + prefetch: yes + + # Fetch the DNSKEYs earlier in the validation process, when a DS record is + # encountered. This lowers the latency of requests at the expense of little + # more CPU usage. + prefetch-key: yes + + # Have unbound attempt to serve old responses from cache with a TTL of 0 in + # the response without waiting for the actual resolution to finish. The + # actual resolution answer ends up in the cache later on. + serve-expired: yes + + # Open dedicated listening sockets for incoming queries for each thread and + # try to set the SO_REUSEPORT socket option on each socket. May distribute + # incoming queries to threads more evenly. + so-reuseport: yes + + ########################################################################### + # LOCAL ZONE + ########################################################################### + + # Include file for local-data and local-data-ptr + include: /opt/unbound/etc/unbound/a-records.conf + include: /opt/unbound/etc/unbound/srv-records.conf + + ########################################################################### + # FORWARD ZONE + ########################################################################### + + include: /opt/unbound/etc/unbound/forward-records.conf + + ########################################################################### + # WILDCARD INCLUDE + ########################################################################### + #include: "/opt/unbound/etc/unbound/*.conf" + +remote-control: + control-enable: no diff --git a/rsc/docker/franz/infrastructure/docker-compose.yml b/rsc/docker/franz/infrastructure/docker-compose.yml index d9d97b5..d7ea165 100644 --- a/rsc/docker/franz/infrastructure/docker-compose.yml +++ b/rsc/docker/franz/infrastructure/docker-compose.yml @@ -29,8 +29,8 @@ services: image: ghcr.io/ajnart/homarr:latest restart: always volumes: - - homarr_data:/app/data/configs - - homarr_icons:/app/public/imgs + - ./homarr_data:/app/data/configs + - ./homarr_icons:/app/public/imgs networks: traefik_net: labels: @@ -49,8 +49,8 @@ services: - SYS_RAWIO volumes: - /run/udev:/run/udev:ro - - scrutiny_data:/opt/scrutiny/config - - scrutiny_db:/opt/scrutiny/influxdb + - ./scrutiny_data:/opt/scrutiny/config + - ./scrutiny_db:/opt/scrutiny/influxdb labels: - traefik.enable=true - traefik.http.routers.scrutiny.entrypoints=websecure @@ -111,14 +111,4 @@ services: networks: traefik_net: name: traefik-net - driver: bridge external: true -volumes: - homarr_data: - name: homarr_data - homarr_icons: - name: homarr_icons - scrutiny_data: - name: scrutiny_data - scrutiny_db: - name: scrutiny_db diff --git a/rsc/docker/franz/infrastructure/ntfy_data/server.yml b/rsc/docker/franz/push/ntfy_data/server.yml similarity index 100% rename from rsc/docker/franz/infrastructure/ntfy_data/server.yml rename to rsc/docker/franz/push/ntfy_data/server.yml diff --git a/secrets/franz.yaml b/secrets/franz.yaml index 3f88544..3c6629e 100644 --- a/secrets/franz.yaml +++ b/secrets/franz.yaml @@ -1,6 +1,7 @@ cloudflared: tunnel_token: ENC[AES256_GCM,data:KEnrTkTCuicpUg51AHrAj08aexQKyPdS42QexuOeK/OeQ4/px3Xrz/95XYztEjdF5eg4c0GNnJidJ2nx7UlGYq+Wp8NINZtrOWB3Vm3pq/4pjdfyX7sMTCvrYE23/pT6kAC1KH/hkhFnauCeqgOlqBDe+I3kM0lVBzIakmSfnHNWJ3PzM9kFpRSD/EprzYyUJoFW7bKY3TlngheQhXc+v0rCMXj/EsZZQRS0L3sGkvbK/xA3PKKsBA==,iv:Xsx/CwGmkr5FoL8zOsfD6ZwhHq8qLgpKEihiAg1iCsI=,tag:mewbduDjTYsAR/f+4h3y4w==,type:str] traefik: + acme_email: ENC[AES256_GCM,data:EZHrh9Xa3KqrBGkebvCfOo+G3cuyEwG5rtisX6UkxzViUYM=,iv:YyaUhB49lML8CUN8/xyvw62wLWbDdmTvRXBdQ+EwbUY=,tag:7sBUPAaagLy8QSuGEnfviw==,type:str] cloudflare_email: ENC[AES256_GCM,data:MXd2rbFmRiQFb+N4d5Ncm0FxYg==,iv:bwVm5+j+zvdw4XecSnBIVWwmvaEkwQtI8J3XQpq/lOc=,tag:7ptLXgQ9pxkuWquPkYKgCA==,type:str] cloudflare_api_key: ENC[AES256_GCM,data:S4iozYRQSK9Gd1UWiV1MqZE8vCTZ7aSU83SH83n17VoJFuQbSA==,iv:CEqAUMW9SUrS6ndo9meiY4DQFwuivWOJMzWi5UHXFqI=,tag:4V7S107Lr5qyh4UyNSVsjw==,type:str] nextcloud: @@ -23,8 +24,8 @@ sops: VUUxcEhvYi8zeXlCUUViUTl0eWdhcU0KXOfbnDc+zc8lnBcyEAV5EiJSjcSU6AgI EfeRw8qVqwChrYn1agslcNnDbE0WQsOCBuA6cE4V3kRofp9HU949ig== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-03-03T16:00:04Z" - mac: ENC[AES256_GCM,data:TvA9zrLlN6AIxYFOuoVIpo/mhzymxhMqq+iyExy0vXUUI94D2yNs8lexPko3HxJBp7FisNpLkIaNxNKkr0qno39ZTwDWcws86fTW9dSpB1uhQP/A8hrjUirjOxX0hqk+vI1Uh4Ungwrc/5itz+1NmrYYJCM62KGv73RDYKEUqzE=,iv:I4N0L6Dp4YJC5QrHfToQb65v6KSa/V0e/88CUzM3Pms=,tag:RZjgAiuCf6UmNE4s8A3dvg==,type:str] + lastmodified: "2024-03-03T19:42:11Z" + mac: ENC[AES256_GCM,data:jMTVK6KR/qbOg1K8TyS4hKHcp0byv/KJSpvbg9y2c3skKNRDHwvb62xtSQHHDFtzqoegmLtxycqW29EneXeHrqwbxM2i/O1jdqacybnieIAVPixG6nN/onZ9f1Pqoc7TpX5Mgw5Fj6qxJUfT3u+susz31BsE1U4Za/+mimfZHdQ=,iv:JmM+hRclxgvIz80PM9zYLZ3NsIBOTkO4ItusgZzHjmE=,tag:cTpl5atAqz5yGDaKpkk3AQ==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.8.1