diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..890d970 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,23 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +charset = utf-8 + +[*.nix] +indent_size = 2 +trim_trailing_whitespace = true + +[*.md] +indent_size = 2 +trim_trailing_whitespace = false + +[*.json] +indent_size = 2 +trim_trailing_whitespace = true + +[*.yaml] +indent_size = 2 +trim_trailing_whitespace = true diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..9bb3323 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,123 @@ +keys: + - &admin_gpg_jtbx 18DFCE01456DAB52EA38A6584EDC64F35FA1D6A5 + - &admin_gpg_yuri 87AB00D45D37C9E9167B5A5A333448678B60E505 + - &admin_gpg_june 057870A2C72CD82566A3EC983695F4FCBCAE4912 + - &admin_gpg_haegar F38C9D4228FC6F674E322D9C3326D914EB9B8F55 + - &admin_gpg_dario 5DA93D5C9D7320E1BD3522C79C78172B3551C9FD + - &admin_gpg_echtnurich 8996B62CBD159DCADD3B6DC08BB33A8ABCF7BC4A + - &admin_gpg_c6ristian B71138A6A8964A3C3B8899857B4F70C356765BAB + - &admin_gpg_dante 3D70F61E07F64EC4E4EF417BEFCD9D20F58784EF + - &admin_age_lilly age19h7xtfmt3py3ydgl8d8fgh8uakxqxjr74flrxev3pgmvvx94kvtq5d932d + - &host_age_git age18zaq9xg9nhqyl8g7mvrqhsx4qstay5l9cekq2g80vx4920pswdfqpeafd7 + - &host_age_forgejo_actions_runner age10xz2l7ghul7023awcydf4q3wurmszy2tafnadlarj0tvm7kl033sjw5f8t + - &host_age_matrix age1f7ams0n2zy994pzt0u30h8tex6xdcernj59t4d70z4kjsyzrr3wsy87xzk + - &host_age_public_web_static age19s7r8sf7j6zk24x9vumawgxpd2q8epyv7p9qsjntw7v9s3v045mqhmsfp0 + - &host_age_yate age1kxzl00cfa5v926cvtcp0l3fncwh6fgmk8jvpf4swkl4vh3hv9e5qyqsrnt + - &host_age_woodpecker age1klxtcr23hers0lh4f5zdd53tyrtg0jud35rhydstyjq9fjymf9hsn2a8ch + - &host_age_penpot age10ku5rphtsf2lcxg78za7f2dad5cx5x9urgkce0d7tyqwq2enva9sqf7g8r +creation_rules: + - path_regex: config/hosts/git/.* + key_groups: + - pgp: + - *admin_gpg_jtbx + - *admin_gpg_yuri + - *admin_gpg_june + - *admin_gpg_haegar + - *admin_gpg_dario + - *admin_gpg_echtnurich + - *admin_gpg_c6ristian + age: + - *admin_age_lilly + - *host_age_git + - path_regex: config/hosts/forgejo-actions-runner/.* + key_groups: + - pgp: + - *admin_gpg_jtbx + - *admin_gpg_yuri + - *admin_gpg_june + - *admin_gpg_haegar + - *admin_gpg_dario + - *admin_gpg_echtnurich + - *admin_gpg_c6ristian + age: + - *admin_age_lilly + - *host_age_forgejo_actions_runner + - path_regex: config/hosts/matrix/.* + key_groups: + - pgp: + - *admin_gpg_jtbx + - *admin_gpg_yuri + - *admin_gpg_june + - *admin_gpg_haegar + - *admin_gpg_dario + - *admin_gpg_echtnurich + - *admin_gpg_c6ristian + age: + - *admin_age_lilly + - *host_age_matrix + - path_regex: config/hosts/public-web-static/.* + key_groups: + - pgp: + - *admin_gpg_jtbx + - *admin_gpg_yuri + - *admin_gpg_june + - *admin_gpg_haegar + - *admin_gpg_dario + - *admin_gpg_echtnurich + - *admin_gpg_c6ristian + age: + - *admin_age_lilly + - *host_age_public_web_static + - path_regex: config/hosts/woodpecker/.* + key_groups: + - pgp: + - *admin_gpg_jtbx + - *admin_gpg_yuri + - *admin_gpg_june + - *admin_gpg_haegar + - *admin_gpg_dario + - *admin_gpg_echtnurich + - *admin_gpg_c6ristian + age: + - *admin_age_lilly + - *host_age_woodpecker + - path_regex: config/hosts/penpot/.* + key_groups: + - pgp: + - *admin_gpg_jtbx + - *admin_gpg_yuri + - *admin_gpg_june + - *admin_gpg_haegar + - *admin_gpg_dario + - *admin_gpg_echtnurich + - *admin_gpg_c6ristian + age: + - *admin_age_lilly + - *host_age_penpot + - path_regex: config/hosts/yate/.* + key_groups: + - pgp: + - *admin_gpg_jtbx + - *admin_gpg_yuri + - *admin_gpg_june + - *admin_gpg_haegar + - *admin_gpg_dario + - *admin_gpg_echtnurich + - *admin_gpg_c6ristian + age: + - *admin_age_lilly + - *host_age_yate + - key_groups: + - pgp: + - *admin_gpg_jtbx + - *admin_gpg_yuri + - *admin_gpg_june + - *admin_gpg_haegar + - *admin_gpg_dario + - *admin_gpg_echtnurich + - *admin_gpg_c6ristian + - age: + - *admin_age_lilly +stores: + yaml: + indent: 2 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..37eee6c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) CCCHH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..34690bd --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +# nix-infra + +nix infrastructure configuration for CCCHH. + +For deployment we're using [infra-rebuild](https://git.hamburg.ccc.de/CCCHH/infra-rebuild). \ +To easily get a shell with `infra-rebuild` going, use the following command: + +``` +nix shell git+https://git.hamburg.ccc.de/CCCHH/infra-rebuild#infra-rebuild +``` + +After that you can simply run the following to deploy e.g. the git and matrix hosts: + +``` +infra-rebuild switch git matrix +``` + +By default infra-rebuild tries to use the FQDN from the nixosConfiguration of the host for deployment. +However to override individual parts of the deployment target, a [`deployment_configuration.json`](./deployment_configuration.json) can be used. +This is exactly what we're doing to set the default deployment user to `colmena-deploy` and have custom target hostnames for Chaosknoten hosts, since they don't have an FQDN defined in their nixosConfiguration. + +## Setting up secrets with sops-nix for a host + +1. Convert the hosts SSH host public key to an age public key. + This can be done by connecting to the host and running: + ``` + cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age + ``` +2. Add the resulting age public key to the `.sops.yaml` as a YAML anchor in keys. + It should be named something like: `host_age_hostname` +3. Add a new creation rule for the hosts config directory. + It should probably have all admin keys and the hosts age key. \ + You can use existing creation rules as a reference. +4. Create a file containing the relevant secrets in the hosts config directory. + This can be accomplished with a command similar to this: + ``` + sops config/hosts/hostname/secrets.yaml + ``` + Note: Nested keys don't seem to be compatible with sops-nix. +5. Add the following entry to the modules of the hosts `nixosConfiguration`: + ```nix + sops-nix.nixosModules.sops + ``` +6. Create a `sops.nix` in the hosts config directory containing the following content to include the `secrets.yaml`: + ```nix + { ... }: + + { + sops = { + defaultSopsFile = ./secrets.yaml; + }; + } + ``` +7. Make sure the `sops.nix` gets imported. For example in the `default.nix`. +8. To use a secret stored under e.g. `forgejo_git_smtp_password`, you can then do something like the following: + ```nix + sops.secrets."forgejo_git_smtp_password" = { + mode = "0440"; + owner = "forgejo"; + group = "forgejo"; + restartUnits = [ "forgejo.service" ]; + }; + ``` + This secret would then be available under `/run/secrets/forgejo_git_smtp_password` on the host. + +## Build NixOS Proxmox VE Template + +Build a new NixOS Proxmox VE Template for the thinkcccore's: +```shell +nix build .#proxmox-nixos-template +``` +Build a new NixOS Proxmox VE Template for the chaosknoten: +```shell +nix build .#proxmox-chaosknoten-nixos-template +``` + +## License + +This CCCHH nix-infra repository is licensed under the [MIT License](./LICENSE). +[`librespot_PR1528_conflicts_resolved.patch`](patches/librespot_PR1528_conflicts_resolved.patch) is a modified version of [librespot PR 1528](https://github.com/librespot-org/librespot/pull/1528) and is licensed under the [MIT license](https://github.com/librespot-org/librespot/blob/dev/LICENSE). diff --git a/config/common/admin-environment.nix b/config/common/admin-environment.nix new file mode 100644 index 0000000..5af7454 --- /dev/null +++ b/config/common/admin-environment.nix @@ -0,0 +1,22 @@ +{ config, pkgs, ... }: + +{ + environment.systemPackages = with pkgs; [ + vim + joe + nano + htop + btop + ripgrep + fd + tmux + git + curl + rsync + ssh-to-age + usbutils + nix-tree + # For kitty terminfo. + kitty + ]; +} diff --git a/config/common/default-state-version.nix b/config/common/default-state-version.nix index 090e729..a3343c7 100644 --- a/config/common/default-state-version.nix +++ b/config/common/default-state-version.nix @@ -13,5 +13,5 @@ # this value at the release version of the first install of this system. # Before changing this value read the documentation for this option # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). - system.stateVersion = lib.mkDefault "23.05"; + system.stateVersion = lib.mkDefault "24.05"; } diff --git a/config/common/default.nix b/config/common/default.nix index 76bece1..5457e4e 100644 --- a/config/common/default.nix +++ b/config/common/default.nix @@ -3,6 +3,7 @@ { imports = [ ./acme.nix + ./admin-environment.nix ./default-host-platform.nix ./default-state-version.nix ./localization.nix diff --git a/config/common/ssh.nix b/config/common/ssh.nix index 9bc97b9..c05234e 100644 --- a/config/common/ssh.nix +++ b/config/common/ssh.nix @@ -20,6 +20,7 @@ "ecdh-sha2-nistp384" "ecdh-sha2-nistp256" "diffie-hellman-group-exchange-sha256" + "mlkem768x25519-sha256" ]; # Macs seem reasonable as the default of NixOS 23.05 is a subset of the Mozilla Modern guideline as of 2023-09-09. # Ciphers seem reasonable as the default of NixOS 23.05 matches the Mozilla Modern guideline as of 2023-09-09. diff --git a/config/common/users.nix b/config/common/users.nix index c36e20a..4ddef2a 100644 --- a/config/common/users.nix +++ b/config/common/users.nix @@ -6,14 +6,9 @@ # - https://git.grzb.de/yuri/nix-infra/-/blob/342a2f732da042d04e579d98e9f834418b7ebf25/users/colmena-deploy/default.nix # - https://nixos.org/manual/nix/stable/command-ref/conf-file.html?highlight=nix.conf#available-settings -{ config, pkgs, lib, ... }: +{ config, pkgs, lib, authorizedKeysRepo, ... }: let - authorizedKeysRepo = builtins.fetchGit { - url = "forgejo@git.hamburg.ccc.de:CCCHH/infrastructure-authorized-keys.git"; - ref = "trunk"; - rev = "0db6df46b68c07edbefe2a5f9ce4002fb6462980"; - }; authorizedKeys = builtins.filter (item: item != "") (lib.strings.splitString "\n" (builtins.readFile "${authorizedKeysRepo}/authorized_keys")); in { diff --git a/config/extra/prometheus-exporter.nix b/config/extra/prometheus-exporter.nix new file mode 100644 index 0000000..46477ed --- /dev/null +++ b/config/extra/prometheus-exporter.nix @@ -0,0 +1,8 @@ +{ ... }: + +{ + services.prometheus.exporters.node = { + enable = true; + openFirewall = true; + }; +} diff --git a/config/hosts/audio-hauptraum-kueche/audio.nix b/config/hosts/audio-hauptraum-kueche/audio.nix index aa49f2f..2a75d8a 100644 --- a/config/hosts/audio-hauptraum-kueche/audio.nix +++ b/config/hosts/audio-hauptraum-kueche/audio.nix @@ -8,6 +8,7 @@ enable = true; name = "Audio Hauptraum Küche"; }; + services.mpd.musicDirectory = "smb://beamer:beamer@beamer.z9.ccchh.net/music"; users.users.chaos.extraGroups = [ "pipewire" ]; } diff --git a/config/hosts/audio-hauptraum-kueche/configuration.nix b/config/hosts/audio-hauptraum-kueche/configuration.nix index afab440..93a6b53 100644 --- a/config/hosts/audio-hauptraum-kueche/configuration.nix +++ b/config/hosts/audio-hauptraum-kueche/configuration.nix @@ -2,6 +2,7 @@ { networking = { hostName = "audio-hauptraum-kueche"; + domain = "z9.ccchh.net"; }; system.stateVersion = "23.05"; diff --git a/config/hosts/audio-hauptraum-kueche/networking.nix b/config/hosts/audio-hauptraum-kueche/networking.nix index ee01d0b..6e1e7d8 100644 --- a/config/hosts/audio-hauptraum-kueche/networking.nix +++ b/config/hosts/audio-hauptraum-kueche/networking.nix @@ -1,20 +1,19 @@ -{ config, pkgs, ... }: +{ ... }: { networking = { interfaces.net0 = { ipv4.addresses = [ { - address = "10.31.210.10"; + address = "172.31.200.14"; prefixLength = 23; } ]; }; - defaultGateway = "10.31.210.1"; - nameservers = [ - "10.31.210.1" - ]; + defaultGateway = "172.31.200.1"; + nameservers = [ "172.31.200.1" ]; }; + systemd.network.links."10-net0" = { matchConfig.MACAddress = "1E:EF:2D:92:81:DA"; linkConfig.Name = "net0"; diff --git a/config/hosts/audio-hauptraum-tafel/audio.nix b/config/hosts/audio-hauptraum-tafel/audio.nix index 3389720..f090fd9 100644 --- a/config/hosts/audio-hauptraum-tafel/audio.nix +++ b/config/hosts/audio-hauptraum-tafel/audio.nix @@ -8,6 +8,7 @@ enable = true; name = "Audio Hauptraum Tafel"; }; + services.mpd.musicDirectory = "smb://beamer:beamer@beamer.z9.ccchh.net/music"; users.users.chaos.extraGroups = [ "pipewire" ]; } diff --git a/config/hosts/audio-hauptraum-tafel/configuration.nix b/config/hosts/audio-hauptraum-tafel/configuration.nix index d7b128c..2f14d0c 100644 --- a/config/hosts/audio-hauptraum-tafel/configuration.nix +++ b/config/hosts/audio-hauptraum-tafel/configuration.nix @@ -2,6 +2,7 @@ { networking = { hostName = "audio-hauptraum-tafel"; + domain = "z9.ccchh.net"; }; system.stateVersion = "23.05"; diff --git a/config/hosts/audio-hauptraum-tafel/networking.nix b/config/hosts/audio-hauptraum-tafel/networking.nix index 6052909..e357d38 100644 --- a/config/hosts/audio-hauptraum-tafel/networking.nix +++ b/config/hosts/audio-hauptraum-tafel/networking.nix @@ -1,20 +1,19 @@ -{ config, pkgs, ... }: +{ ... }: { networking = { interfaces.net0 = { ipv4.addresses = [ { - address = "10.31.210.13"; + address = "172.31.200.15"; prefixLength = 23; } ]; }; - defaultGateway = "10.31.210.1"; - nameservers = [ - "10.31.210.1" - ]; + defaultGateway = "172.31.200.1"; + nameservers = [ "172.31.200.1" ]; }; + systemd.network.links."10-net0" = { matchConfig.MACAddress = "D2:10:33:B1:72:C3"; linkConfig.Name = "net0"; diff --git a/config/hosts/esphome/configuration.nix b/config/hosts/esphome/configuration.nix index fc13d89..0ef1dce 100644 --- a/config/hosts/esphome/configuration.nix +++ b/config/hosts/esphome/configuration.nix @@ -2,6 +2,7 @@ { networking = { hostName = "esphome"; + domain = "z9.ccchh.net"; }; system.stateVersion = "23.05"; diff --git a/config/hosts/esphome/default.nix b/config/hosts/esphome/default.nix index cfe47bc..8d5150d 100644 --- a/config/hosts/esphome/default.nix +++ b/config/hosts/esphome/default.nix @@ -3,6 +3,7 @@ imports = [ ./configuration.nix ./esphome.nix + ./networking.nix ./nginx.nix ]; } diff --git a/config/hosts/esphome/networking.nix b/config/hosts/esphome/networking.nix new file mode 100644 index 0000000..8a84112 --- /dev/null +++ b/config/hosts/esphome/networking.nix @@ -0,0 +1,29 @@ +{ ... }: + +{ + networking = { + interfaces.net0 = { + ipv4.addresses = [ + { + address = "10.31.208.24"; + prefixLength = 23; + } + ]; + ipv6.addresses = [ + { + address = "2a07:c481:1:d0::66"; + prefixLength = 64; + } + ]; + }; + defaultGateway = "10.31.208.1"; + defaultGateway6 = "2a07:c481:1:d0::1"; + nameservers = [ "10.31.208.1" "2a07:c481:1:d0::1" ]; + search = [ "z9.ccchh.net" ]; + }; + + systemd.network.links."10-net0" = { + matchConfig.MACAddress = "7E:3C:F0:77:8A:F4"; + linkConfig.Name = "net0"; + }; +} diff --git a/config/hosts/esphome/nginx.nix b/config/hosts/esphome/nginx.nix index 3c5cfb9..2b154f0 100644 --- a/config/hosts/esphome/nginx.nix +++ b/config/hosts/esphome/nginx.nix @@ -1,35 +1,34 @@ { config, ... }: + { services.nginx = { enable = true; virtualHosts = { - "acme-esphome.ccchh.net" = { - enableACME = true; - serverName = "esphome.ccchh.net"; - - listen = [ - { - addr = "0.0.0.0"; - port = 31820; - } - ]; - }; - "esphome.ccchh.net" = { forceSSL = true; - useACMEHost = "esphome.ccchh.net"; + enableACME = true; + serverName = "esphome.ccchh.net"; listen = [ { addr = "0.0.0.0"; port = 80; } + { + addr = "[::]"; + port = 80; + } { addr = "0.0.0.0"; port = 443; ssl = true; } + { + addr = "[::]"; + port = 443; + ssl = true; + } ]; locations."/" = { @@ -37,9 +36,38 @@ proxyWebsockets = true; }; }; + "esphome.z9.ccchh.net" = { + forceSSL = true; + useACMEHost = "esphome.ccchh.net"; + serverName = "esphome.z9.ccchh.net"; + listen = [ + { + addr = "0.0.0.0"; + port = 80; + } + { + addr = "[::]"; + port = 80; + } + { + addr = "0.0.0.0"; + port = 443; + ssl = true; + } + { + addr = "[::]"; + port = 443; + ssl = true; + } + ]; + + globalRedirect = "esphome.ccchh.net"; + redirectCode = 307; + }; }; }; + security.acme.certs."esphome.ccchh.net".extraDomainNames = [ "esphome.z9.ccchh.net" ]; - networking.firewall.allowedTCPPorts = [ 80 443 31820 ]; + networking.firewall.allowedTCPPorts = [ 80 443 ]; } diff --git a/config/hosts/forgejo-actions-runner/default.nix b/config/hosts/forgejo-actions-runner/default.nix index 6a01b20..f5a8ddd 100644 --- a/config/hosts/forgejo-actions-runner/default.nix +++ b/config/hosts/forgejo-actions-runner/default.nix @@ -6,5 +6,6 @@ ./docker.nix ./forgejo-actions-runner.nix ./networking.nix + ./sops.nix ]; } diff --git a/config/hosts/forgejo-actions-runner/forgejo-actions-runner.nix b/config/hosts/forgejo-actions-runner/forgejo-actions-runner.nix index b2efcbe..d5a93c1 100644 --- a/config/hosts/forgejo-actions-runner/forgejo-actions-runner.nix +++ b/config/hosts/forgejo-actions-runner/forgejo-actions-runner.nix @@ -7,24 +7,54 @@ { services.gitea-actions-runner = { - package = pkgs.forgejo-actions-runner; + package = pkgs.forgejo-runner; instances.ccchh-forgejo-global-docker = { enable = true; name = "Global Docker Forgejo Actions Runner"; url = "https://git.hamburg.ccc.de/"; - tokenFile = "/secrets/registration-token.secret"; + tokenFile = "/run/secrets/forgejo_actions_runner_registration_token"; labels = [ "docker:docker://node:current-bookworm" ]; + settings = { + cache = { + proxy_port = 45540; + }; + runner = { + capacity = 4; + }; + }; + }; + + instances.ccchh-codeberg-org-diday = { + enable = true; + name = "ccchh runner for codeberg.org/di-day"; + url = "https://codeberg.org/"; + tokenFile = "/run/secrets/codeberg_org_diday_runner_registration_token"; + labels = [ + "docker:docker://node:current-bookworm" + "debian-latest:docker://node:current-bookworm" + "alpine-latest:docker://node:current-alpine" + ]; + settings = { + cache = { + proxy_port = 45541; + }; + runner = { + capacity = 4; + }; + }; }; }; - deployment.keys = { - "registration-token.secret" = { - keyCommand = [ "pass" "noc/services/forgejo-actions-runner/registration_token" ]; - destDir = "/secrets"; - user = "gitea-runner"; - group = "gitea-runner"; - permissions = "0640"; - uploadAt = "pre-activation"; - }; + sops.secrets."forgejo_actions_runner_registration_token" = { + mode = "0440"; + owner = "root"; + group = "root"; + restartUnits = [ "gitea-runner-ccchh\\x2dforgejo\\x2dglobal\\x2ddocker.service" ]; + }; + sops.secrets."codeberg_org_diday_runner_registration_token" = { + mode = "0440"; + owner = "root"; + group = "root"; + restartUnits = [ "gitea-runner-ccchh\\x2dcodeberg\\x2dorg\\x2ddiday.service" ]; }; } diff --git a/config/hosts/forgejo-actions-runner/networking.nix b/config/hosts/forgejo-actions-runner/networking.nix index 7c5e178..71aa47a 100644 --- a/config/hosts/forgejo-actions-runner/networking.nix +++ b/config/hosts/forgejo-actions-runner/networking.nix @@ -1,20 +1,27 @@ -{ config, pkgs, ... }: - -{ - networking.interfaces.net0 = { - ipv4.addresses = [ - { - address = "172.31.17.155"; - prefixLength = 25; - } - ]; +{ lib, config, ... }: +let + runnerInstances = lib.attrValues config.services.gitea-actions-runner.instances; + runnerCachePorts = lib.map (i: i.settings.cache.proxy_port) runnerInstances; +in { + networking = { + interfaces.net0 = { + ipv4.addresses = [ + { + address = "172.31.17.155"; + prefixLength = 25; + } + ]; + }; + defaultGateway = "172.31.17.129"; + nameservers = [ "212.12.50.158" "192.76.134.90" ]; + search = [ "hamburg.ccc.de" ]; }; - networking.defaultGateway = "172.31.17.129"; - networking.nameservers = [ "212.12.50.158" "192.76.134.90" ]; - networking.search = [ "hamburg.ccc.de" ]; systemd.network.links."10-net0" = { matchConfig.MACAddress = "1E:E0:4E:D0:DA:BE"; linkConfig.Name = "net0"; }; + + # open ports for runner cache proxy so that we can use the cache action + networking.firewall.allowedTCPPorts = runnerCachePorts; } diff --git a/config/hosts/forgejo-actions-runner/secrets.yaml b/config/hosts/forgejo-actions-runner/secrets.yaml new file mode 100644 index 0000000..79df4d5 --- /dev/null +++ b/config/hosts/forgejo-actions-runner/secrets.yaml @@ -0,0 +1,149 @@ +forgejo_actions_runner_registration_token: ENC[AES256_GCM,data:gAR2ffrffeuuaOwO6mWcif2e6csKIVoLqrux19iBlrTkFHgo/IlHVL0eSUGqnw==,iv:i12yx/quwT9kj6fPECszo/iG9cVhKX+7dAA6/N09URc=,tag:eO+mWhumgvWzQxYqiRUXbA==,type:str] +codeberg_org_diday_runner_registration_token: ENC[AES256_GCM,data:thTsLo/eXVPbXt4b8ldae+kGnOR4GbYKOqr1hVJgaL7wZ5GgqWSPcOuhow96Jw==,iv:Fzi+DsKj+4PrwQGEosUntm9l7s78NwzhkmF6e/sfF+s=,tag:oa7mnbGR0J5xi9ruCgRJtQ==,type:str] +sops: + age: + - recipient: age19h7xtfmt3py3ydgl8d8fgh8uakxqxjr74flrxev3pgmvvx94kvtq5d932d + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjZEpMZkt6OU5nMEtYcHc0 + OGdsVDZBcE5nK2ZLbDhaWEVMM2lJcllLVnlzCmNUTXpaVHBLMjlILzJwdDFLMVky + ZXdEVmE3aTFMZDJnQ2tqWGRMb1NnZUkKLS0tIDhGWGpoYWNtL24wRnVRejQ5ZkVN + YjZFMTh3OTNkOUE0SmZTQXpKSmdGWlEK+Xb6blAdiWoKvffLEQagu5tFpWALJaXm + F65M+RNNkJ/YsSJGAWFJepw3ncCMFbmQgGXw5XnyqTlYFhrQ8x5qJg== + -----END AGE ENCRYPTED FILE----- + - recipient: age10xz2l7ghul7023awcydf4q3wurmszy2tafnadlarj0tvm7kl033sjw5f8t + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQblJIdFAwOFRqbWEvQzVF + ODVpQ04xTVpxTERGU3BOMjV4KytBU21neEYwCmoraHhlNjhDelAzR0VxcVNlekhT + QkI5ckd1dVFjMHBoTVFTQjlzbTdnTzgKLS0tIGlTY1p0bWxrQWoyM0RwSmx1aDhy + TklLZWM0cDBKaGJJM2tQQWRLZXhFYU0Ko7cyvzMvwlGCCP3UAX1+5uTI4srhZ5l9 + DPaHySiC+rLy+8R9UqEuTKbP4/Aw4NZ/UcfjNnVkqqqNJIODmLoOhg== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-02-18T09:51:37Z" + mac: ENC[AES256_GCM,data:4fWsE3U6WxRqlKHKC4ipE+RQ7MPjiZZcTFMSblxty7JjJHAdKUHbthFB+R8gIWxZEjX5WG+IPgUP+AcCLSI9fdcXMqIFMuDun2hiktwqxzLPGYAoCXdTBAd1uCUagvB/rFty6y8umD4J5ITgEGba9pvGdUcng9WVRV+LGDftS1g=,iv:tD9tlcylQWapNCARxPXrKofZXf2BHTt2c4PQqFNj6X8=,tag:pQ8lOqJEFCcCcJot3BYTmQ==,type:str] + pgp: + - created_at: "2026-02-17T22:21:57Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAz5uSgHG2iMJAQ/7BFboCbCEG1DY5Twf+1cRSAmXs8CSrnoJcmyxrF9daqTB + GAqItZcym6I7YbtYMb33jTZDAMFcexvJ+V7+WVBK/v/TISzinJ3m5BafE0DrgsB5 + HQT8tsFzxIdu/KsUp0C5VQg6gsb2u2T7aFG0wTS4vas2FjcsoJRKNWTv7a1sNWYZ + dFRxeyklWEX14kCHeKIxO7+Qe3NVV+6MuwYR8X3YJaAyLtVMIdBp/poE+7Gcsa58 + rOewheWW/FROTxLZIk3sren6z7M0ZrOz5res2evRDMI9noN3pYMnkNCL/XIvRf9U + GqFSruzDoC0a2JcEvSmthSmEHA6wXeOY/EuzXKLoW4luZDsSXshFgBxK0qqGvzbd + jIXXYvBWPCMYWRMSqQenLkjfhOQXuSXcywGfKpuQblUL8RiflIqia2o68Vbd9Hq4 + x9Od+qkauMHZUzsKQoym9pkbrEWpjckg6FevZ1W4o5Qhe9i+JMmE2KIvoYH8tK9F + 5KQ87jktx4i9df9TJy3n/xbbrWXpo76y5Aoa2LaiD9Nc6lo7sFs3Pegq4wKmYSIh + 6uaZxa5sto/5kywHrJQGqEyh/fDdNmsh5FlDW7gfFEm9Ti2KSE3m9IvIwppFD4j0 + xFkHiwHvNn/WMLciVh9qG8auGyxjoXnRRx61QHF31RIYprxWgDoyH/rVz95IuxzS + XgEIJk7MnHv9tYCy/lOjbgqLAUGO0+xuO+IfmsvtiD4nfrnaEJAh0+SW3wuCKzaF + tx1ZHCYH9j3s50Q624pUgtzDad5QV5IIEgCRyr0NvEvrXvG6U0aXkOEbOcFSZsk= + =v3FY + -----END PGP MESSAGE----- + fp: 18DFCE01456DAB52EA38A6584EDC64F35FA1D6A5 + - created_at: "2026-02-17T22:21:57Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAw5vwmoEJHQ1AQ/9H+Kn4rF7yUsIdTp5rYhG6EkYkJ/jCeUBJvaOuA95b8HM + 6csTXj+ttVcFvbU1hQVbOsd7J8Wpmuj/TqMrpFvu/0EYUW5n04y1YI8kpNXDMrFF + X/0gk+I+w2eF2X3gJQasVY39DNx56KSRJ0BwGYw287rdeKh8cbiFw64r0rs6zX5j + 2nqrWgSqxXtWcjhC7Y4Rq8ysWv7dEF2E9Tt2cHYVjn5cs9Vb52PWUA0TxzBzUUqa + M1YWat3fwLah6qEs6/9c89LB66SbgH088lEzQHtRIXdOZ9tPOu7/E3iNqYExuIKB + eMV0bdW0/tZlnWxAwXrL4rptxjGDqB+Ynv36IeLKZ86ljqSPqaQA7ihCVXnMo2TW + IfdlbOtAJiE3IliQf8C1Ajyn32epePBAUyw8o0k2D6UyNyvk8fe0z9++H6Uz+Z7G + oLRrxzOHjh6oWK9WBwJQhZ9dnb1n1UYZfvCDwFZBTmUkhIs6UQllIiF5ZjMy4/cc + E3FEouu/6VPPjq9d8pGEFcjOvXkLtUErhXP+A8Xvl/fHmtfM0/o1e6gPnMmxGn4k + 0yXvU+pNO/ID6fc6qMs0nBZRAKGraaeH+wTjpm1exUhhNB2yJviySnElJFyq9vtr + AfacrbuW//JQ+19rSKViV9xStRG//xfW7EpknOh3juB7WfnyOXqdfZqT2zQwrvjS + XgEoHXmbR7aiDvBCc4CGTmBhWD4An+p3m3m7iSOp27kBqJ3+YSKdVA7mdIo0tpTn + 9p5Pgz6GHBA5eMwZCb/z3Y7+20PuuEb4/tEBAniw9/Rp0sDJ+9C+V1SdHtbYq8k= + =kkQW + -----END PGP MESSAGE----- + fp: 87AB00D45D37C9E9167B5A5A333448678B60E505 + - created_at: "2026-02-17T22:21:57Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DerEtaFuTeewSAQdAdgME/v0CVfcRZ1zr9SRZksN7vDHDk63g+5k5a/FOvmow + 0l/6kH1l7p4aOKaAGFbMHzDzljuACB1a4IOJypRA2DokYWRUgqBKwvcHplgXr4l0 + 0l4B2vxPl9W1kcbAg4m+V4PlvXTBGhPUglljtjWy80TisUL1zCXpl3PEvmrypZs7 + NM47K09RsDiicwTKjxd0Oii2Evz8riLFIth8IWOKXPHoKhiYwN891g1qLSvsrDzE + =6B/b + -----END PGP MESSAGE----- + fp: 057870A2C72CD82566A3EC983695F4FCBCAE4912 + - created_at: "2026-02-17T22:21:57Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAxjNhCKPP69fARAAjz8RObyKYVAmNwiBsNVNGt0qSIexSYpsMR5SyuBMKShJ + NSD4yA6B7Tj+h/ik4VyggOT+9Qfr7zFvFyEHYFXI7k/r+Noyw4uscqr9gNnz0t9N + rx4/ZNowsW/3dL+Gab3hjDKObHF41Y1lzojNwcieU8qZmssHZMjIIzyAUePL210f + 2i87hix9PkK6kKuisORDShnFifEOEPOcijXFL4kH9DilVoZ0Ut5fJoiA+QkQQpaa + uHd+Q7F6u9jZrzRLN1SJkb76ElxQAvJYcgTN2s3+c4002DkKVdwCW0qyPlF9wOxT + xTngl46NyZ1MH3ByW2xeOgaDYUcBt8qUF4gTMmIaDTIZ+K5XWGu3hmCzNZHD5Nxi + bhVKJ8jGENUhM/IfT8CjppRIg5wwU0K/EQE/QQHhIykpz9NaIjikDCxcraBa9DkA + rgjp74W9vgR3pBwXJIAsylOZZHy+35rca/JvWWxm2tdeao2WxTA9jdsNdsUOhNyz + 3xQGGM63ZSUcV0ZgCyhEYeKBzCyRWpFX+GQHboZDp7IaYK68qYZgxnQtoSwl3lJR + Qc1IaADnncIDyGEIDTciLbjbDx7TId4wrpRWUPxVY2FVY+hV+oRNaoYMuT2jiDVw + PimQ5iVUhl/ThHWPLqok6d3ypROZtVS6EUFzd4ASUrYRYB5Twvoujr7Yg7jSZV/S + XgFcxQ31/i/Vi9owjwX7u0/eclU/3XE2/MqUCcoMntnq2dCN/IpF3rROit5Tzs+W + BT7i57cpGh9ZXf1dbNSyRwydp/C8tjnwDqf3RJ5hj4fmlK6zLJqtPFPdusOO4SU= + =z1tc + -----END PGP MESSAGE----- + fp: F38C9D4228FC6F674E322D9C3326D914EB9B8F55 + - created_at: "2026-02-17T22:21:57Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA1Hthzn+T1OoAQ/+K1+QTZ8N3Ha0nErrRWClBu5Cxec5/eb2Q/n4dfNGkrxx + xBk0thoGAyoYpifSqhXbVi/MA8+tzHdtPlKJFCn5NETrnEdu84+sJQE4zfDljLiX + fXZZ/+YQ0P3VosR2NI3W1r/hJWs4oJ9oPz4FfMlfPK+/UOOdQEtGkx9rjYaus9Ax + VI6s5qvYM6XD5rkLxTqZZhEa+CjLtSjD5WqNbCT/8fX5ErnU06jW6jXvRNQSq1Mt + hpqMIBygUE39K2apEuphE9RRD3bS1M2VjCB882yVSM2QZyepilRBjS5ryyQhKK/9 + Q0mdIw9mxhdgaCzoglN2k1c6WjddZ409osdnYcMtsH4+NlHDtNfSFLIk6JrxAXIQ + bNR8gtr4D85LoQki/RvEweUd4M40DneIO1dTK4/WG71Lcle3B6p0ynDMjmXq1coY + Qn0c4KAh1RIX/eEJGS23Wle/XZbp89yaFFEF667+HmwL0CY6I5pcVEn/iuXLoNHI + 93y/9h7mhB8ZGICPbF7nXBfQQTrxjfc9vZq0PVdjlXPIMRjZcbZOzlKByYLsQIW0 + UtzLScfFyKsogcUGJIlGrcQyAmLb3dr7i1elVWlanggCXdKnecBRbSkEfK7SmwiN + t8hRaaM06P3kRbTHWxt+4sjTQWofo+C76qsMZYHFpI0TTOP/jwnn/h3E9dQxdaHS + XgHzVEsJkQiQ51w7pPP1LcKkCxQv1KA9QC+LAFGhmWXnQ1m8E3whao2S07UjlTVw + XMAtuOVT2r09dYGgpcEaMiK2Hb9UNg/ma9o29fSm+2rLuxw3qSldgNNx/s8hyzc= + =0kev + -----END PGP MESSAGE----- + fp: 5DA93D5C9D7320E1BD3522C79C78172B3551C9FD + - created_at: "2026-02-17T22:21:57Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA46L6MuPqfJqAQ//ZYw2qRn+YhiEoBpbUsW95NJpZJFizwssh1dC/Lda5qFs + 55G1Jls9FHHQ+LmRnE6wyx26bbpQ257FNzCsxsfwAuiznx31j1yHc6LZbuJ3+DsJ + slRaad13RdLyGgo2psaXbBMEgr22FAFDm+S98aYnyv8yvtOZvutEljGm9yhHLGKy + XnFf8LwvvqdT4RolfxiPncGsd9hbFYZh7/zcJTSzfYSnHI30Ly5Na74vSaamuIwR + oPnSxlf8jIX5RUzssjyOHGLQLd327fKuveVxX9CUK/PGWLgQYuTL5PWZwQGhzgSY + E+2EerpGLVJzSQB0TUU5xGwOQkDlPveSSUg0IoDlivMnrphWUFd+bcIMbipVXolf + qpiJeO1t0YW1WAQBzkQ3J+uXgX0dJqWfzfMsbn3j4/WZq5ZlEX6x+ovHv6Z7ZXTz + 6lcF6Gn0dH/omhkqduK3bLwBWAkmh7gWNssEXdPQWGWA8j3WM+IPZKIegpecflKN + pv7jOyD95othMUul/iiH/E3aSbCggN5maoZHG2Cp1TGXkGOLFCNs143LGTVligOU + yD8n0uAQ8e50J7YwytSi2g0pzFkZyriLmrZqKFt9UUOfANivrO9p8J0Bo9wEHjY0 + OdKKu8ASgjYk0t4VHGeZF3GPSaGE/k7LaUb9+5t02sxypxeVqQXpvjU/D8c/0wPS + XgGQs2bjszJIyRwcTmUHD8YAvuxf0MkyKCKpJSsnbJ4XmgkI+gGQpg0GLQROXjZ4 + 8GqLzKb+3d3QDUPQmh+z5Ur1nFcVS214wycICWSTsIUyam59+4rVxV1i33DcAs4= + =BJfi + -----END PGP MESSAGE----- + fp: 8996B62CBD159DCADD3B6DC08BB33A8ABCF7BC4A + - created_at: "2026-02-17T22:21:57Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DQrf1tCqiJxoSAQdA7rerN+IVKpzyAdXVuAN19+CIjQ6DnHatGr92/YhAEiQw + J913tdR+Yb/FdPWQrn0NR2eTUuKm/Es0NRvJY/YEnhQble+3qYvxFP6dI+vm1cmz + 0l4BNxMhGqyOmsDFf58yrJmrHdnapBOmiqCkJBTc9gAQH534di0Ps+grV04jzkXW + DUO/sIPANPpvqqCJNt1uekKNH2J57OMaagnBTivMBTq0HAuRN1RhcrjGof9ttCj1 + =desh + -----END PGP MESSAGE----- + fp: B71138A6A8964A3C3B8899857B4F70C356765BAB + unencrypted_suffix: _unencrypted + version: 3.11.0 diff --git a/config/hosts/forgejo-actions-runner/sops.nix b/config/hosts/forgejo-actions-runner/sops.nix new file mode 100644 index 0000000..b4548ed --- /dev/null +++ b/config/hosts/forgejo-actions-runner/sops.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + sops = { + defaultSopsFile = ./secrets.yaml; + }; +} diff --git a/config/hosts/git/default.nix b/config/hosts/git/default.nix index 0f4664e..d3494e6 100644 --- a/config/hosts/git/default.nix +++ b/config/hosts/git/default.nix @@ -8,5 +8,6 @@ ./nginx.nix ./opensearch.nix ./redis.nix + ./sops.nix ]; } diff --git a/config/hosts/git/forgejo.nix b/config/hosts/git/forgejo.nix index 103881c..89f83c9 100644 --- a/config/hosts/git/forgejo.nix +++ b/config/hosts/git/forgejo.nix @@ -7,14 +7,20 @@ # - https://codeberg.org/forgejo/forgejo/src/branch/forgejo/docs/content/administration/reverse-proxies.en-us.md # - https://forgejo.org/docs/latest/admin/email-setup/ -{ pkgs-unstable, ... }: +{ pkgs, ... }: { services.forgejo = { enable = true; - package = pkgs-unstable.forgejo; + package = pkgs.forgejo; database.type = "postgres"; - mailerPasswordFile = "/secrets/forgejo-git-smtp-password.secret"; + lfs.enable = true; + + secrets = { + mailer = { + PASSWD = "/run/secrets/forgejo_git_smtp_password"; + }; + }; settings = { DEFAULT = { @@ -43,9 +49,13 @@ }; service = { ALLOW_ONLY_EXTERNAL_REGISTRATION = true; + ENABLE_INTERNAL_SIGNIN = false; DEFAULT_USER_VISIBILITY = "limited"; DEFAULT_KEEP_EMAIL_PRIVATE = true; ENABLE_BASIC_AUTHENTICATION = false; + ENABLE_NOTIFY_MAIL = true; + AUTO_WATCH_NEW_REPOS = false; + AUTO_WATCH_ON_CHANGES = false; }; repo = { DEFAULT_REPO_UNITS = "repo.code,repo.issues,repo.pulls"; @@ -77,14 +87,10 @@ }; }; - deployment.keys = { - "forgejo-git-smtp-password.secret" = { - keyCommand = [ "pass" "noc/vm-secrets/chaosknoten/git/smtp_password" ]; - destDir = "/secrets"; - user = "forgejo"; - group = "forgejo"; - permissions = "0640"; - uploadAt = "pre-activation"; - }; + sops.secrets."forgejo_git_smtp_password" = { + mode = "0440"; + owner = "forgejo"; + group = "forgejo"; + restartUnits = [ "forgejo.service" ]; }; } diff --git a/config/hosts/git/networking.nix b/config/hosts/git/networking.nix index b73b953..34159f9 100644 --- a/config/hosts/git/networking.nix +++ b/config/hosts/git/networking.nix @@ -4,27 +4,30 @@ { ... }: { - networking.interfaces.net0 = { - ipv4.addresses = [ - { - address = "212.12.51.136"; - prefixLength = 28; - } - ]; + networking = { + interfaces.net0 = { + ipv4.addresses = [ + { + address = "212.12.51.136"; + prefixLength = 28; + } + { + address = "172.31.17.154"; + prefixLength = 25; + } + ]; + ipv6.addresses = [ + { + address = "2a00:14b0:f000:23:51:136::1"; + prefixLength = 64; + } + ]; + }; + defaultGateway = "212.12.51.129"; + defaultGateway6 = "2a00:14b0:f000:23::1"; + nameservers = [ "212.12.50.158" "192.76.134.90" ]; + search = [ "hamburg.ccc.de" ]; }; - networking.defaultGateway = "212.12.51.129"; - networking.nameservers = [ "212.12.50.158" "192.76.134.90" ]; - networking.search = [ "hamburg.ccc.de" ]; - - networking.interfaces.net0 = { - ipv6.addresses = [ - { - address = "2a00:14b0:f000:23:51:136::1"; - prefixLength = 64; - } - ]; - }; - networking.defaultGateway6 = "2a00:14b0:f000:23::1"; systemd.network.links."10-net0" = { matchConfig.MACAddress = "92:7B:E6:12:A4:FA"; diff --git a/config/hosts/git/nginx.nix b/config/hosts/git/nginx.nix index 1dd0aad..ea1a2ac 100644 --- a/config/hosts/git/nginx.nix +++ b/config/hosts/git/nginx.nix @@ -34,6 +34,10 @@ return = "200 \"User-agent: *\\nDisallow: /*/*/archive/\\n\""; }; }; + + # Disable checking of client request body size to make container registry + # image uploads work. + clientMaxBodySize = "0"; }; networking.firewall.allowedTCPPorts = [ 80 443 ]; diff --git a/config/hosts/git/secrets.yaml b/config/hosts/git/secrets.yaml new file mode 100644 index 0000000..12b484b --- /dev/null +++ b/config/hosts/git/secrets.yaml @@ -0,0 +1,148 @@ +forgejo_git_smtp_password: ENC[AES256_GCM,data:ZRj5GpQKRlTxdu5CfbJirRGAKPCLAIG1F0V5USz5m5D49V3lu5uLomxHapmEwb0yYoE7e7ZLYK4VQUoQgpUnSw==,iv:K7+9E2gi8cdYu0lX/HgWitLxnxARywIwh5glEL0uOsM=,tag:s9UC8e+E5E3vM6cTKW7Vqw==,type:str] +sops: + age: + - recipient: age19h7xtfmt3py3ydgl8d8fgh8uakxqxjr74flrxev3pgmvvx94kvtq5d932d + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpeGkrV2d0clRqTnNVa25P + VUJTQ1I0YUtSYmRwVWIzaEUycjFkbUQ4NXpZCmNnbTVTdGp3R1VET0k1Z05ySHg3 + M2NWaVNiMnB5RllFb1FzOVRRNkk1c0EKLS0tIHBQL01BMjZNMkFBZU43SE5Yc2RV + SEtGVldxa0l5c2t0d0Z1ME5SNlFPYlEK75G9DZxOUGIAEVtUo6BDFZ3NGB6/cfm7 + 0leD7YW7g4mJ+raI/9wVb41BmGdFrYzr0xSjj/1vjJ2aTJEB7pBiTA== + -----END AGE ENCRYPTED FILE----- + - recipient: age18zaq9xg9nhqyl8g7mvrqhsx4qstay5l9cekq2g80vx4920pswdfqpeafd7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTR21UUEdiZHVKOVBXZlVn + bW8xMGlSbElYQmxQN2IrTzlIeU11WSthSlRVCitIU3ozV0ZDUnhTTk9TRjR3V2Jh + ZDVvcjMzMjhkUmlKSjI5Z09nV3VzSTAKLS0tIDZNQldPcFFWeTJZVWhUMDNKWTVp + VmJxSU1Wa3orQ2tTNEFWdUdKM0RhQmsKfQm3qBSSY/7Pt98HNgXp+THAkOSRRrDF + 8QE6EboB4EJql1hcu2ZHgCGqLNpW/YO5lD3IHt0ujNI0Pd4uYIL1tw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-05-25T14:17:29Z" + mac: ENC[AES256_GCM,data:JeqYsVtogbB4oMWNEpLsF6zxsgUoAt7UzRUL2JzxDUtXDUndW/AxJxVxQaipYvblA3q2MzRyQN+j9khavlL02DR/ANtZFLQmH3OREV7M9eHmeeCa4Lm5D7gFYmqWkULJ7yEJsKz5AaiJTWlWgCcBITB901H3Z12dsz2a1+4WrUc=,iv:5Xm5Rjw8PS7hkTcRD1kj5XS5uiOgsPwXYeaMqUReB7E=,tag:2Y5R1/Why1TQd+ZYTF0qDA==,type:str] + pgp: + - created_at: "2026-02-17T22:21:58Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAz5uSgHG2iMJAQ//aGNw4mAzDqvpfu1FOQwoU6q3C7RlL77VIy6xw93BsahP + c8yIEoTOiDa1wtsLKHMaqxNADsxuQBmx4lQYQZ786SUFMVndfJzU6tf59SnOF+5U + /FztmZQsDEzKzKWESIEQMMavEAanr8DEGpACOITZAe61mTJAn8vcc92jMYhmnsHh + zlhS+ryg+j6VRp5i/s1Yocec/iYR9GlUKn3FVHrVDA0TBxOHJ8KjneN7CG0XFuBg + YmRpokZJrLxLntSyMZVSfksuOK8ORlYYpsGvKZNyzA726WjrYg8bJNN10iZHIbwR + PBmDvvP7SWDcJ1/YuzHE2vwJwbRupE3RLQoFRtmANi5QE0mzyMZPz7IF7d/TrXSV + fW3Hb/73SI+QjgdMtHJCtsxBh7rbGTJMP14TJzmETP7eCwLF+92goz/ruhG+HWFf + vc2g/SLAzUjoiX3MjuPjaLZTfgqhC2b/OnZ+MbFMbpgBtXlNhOkDSb75g/gOaB14 + 9CHmQoJt2JeeCCVkH+YQeq6oK9S5lD2WUhigFxdFaHjE6fmKkwxIBMwPwZ7QY7Ep + ljxJuSfMvl3XkZxpxD1+Ep9C1ZIvDXmvdhXx7H/3SaUtefCHO6Ab46ibtKa8wh2w + 4gzPinJJdDYJfzylNDVMZxJ/P9y8XcYSSDGasG7QOGVNm4T2MrLjFaFhrU7lN9TS + XgHr8/8XgnlBIupmjeJTpLpcF0u5zeKIOiKkJBRQR1aUmzmi76lJVStuEJzfymXl + baOviVQywJOe3bVilDmUuVc71FVICnKgwdAvvgG15nOfOUBagLhM0IrgRrGmGSM= + =+Oww + -----END PGP MESSAGE----- + fp: 18DFCE01456DAB52EA38A6584EDC64F35FA1D6A5 + - created_at: "2026-02-17T22:21:58Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAw5vwmoEJHQ1AQ//VsCz5H85LzK29rlmzv1BZaZb6tj86PsO0TydE6+re29Y + i7uu7i54BbjhyC9C2m2J2dzfDsIZyt80n7/1/QooWw4+/h+CD1aFYFb/fiwV6/oq + IAwdnoEio96r6LZcA1t4MSuAcRlrVMrG+OPh0QdCE0uFNiaDcmD6m0XiKL17m6Mk + F9xoYe5e+QMQdq/IcRLVfnlOWMn9qkqixbe4s6YfwttPV9Zx9fDRNz7qf9JiOdbT + sDbnbCDUVyHaRwQ5KMiJOsv0+vVKmDLqlHuFp+21k8/CSAOHzqD+4x9+JMNG5tja + g7Oh2n62UAsCHAr1BPiiWdRpBpIpEbF2/aKjdnlTKaR+niIg4EllkL4XYiFfz3+j + E+IT439U4eqj6AZyblrNgjL2BKUOvR2sQ/PvKA/JHuHCO8C7md0ID1BGlusuN8qX + AZh73AXe5vrrK16k/BX6Pbq0XOAPv8IKa115ZTmfKNH1Iy/LKiwRZT7/QYvYF+Dx + 4RZJkRZgR5gQ4iDytyKUOeMLZyhEQCmHYL4jGvFVa95eNHM87PqI7Eh97tGyO9V6 + FchBk5MTWXnqyXbaC+NEhFduNOh7lNDGNkjjv9PnYdOAgyFY0x4dkKK7bA0Bnzvj + cSiQyCsnF2epK1t5vmbu74vOIfJrXsvp/JwilqEaIiYLywOuVstKFmDyBWnqblnS + XgEhibKGUk2lqS9CmIAzcTsK0GSRkQaI88NljE2zQfORQcEKQ8HziKFf4NrDRYf+ + heln/SYu+bas1gZQBtQRippUbje9xe8uCUez9tgTwbpxYywcq90LvAUZ9F8lVQM= + =cFEl + -----END PGP MESSAGE----- + fp: 87AB00D45D37C9E9167B5A5A333448678B60E505 + - created_at: "2026-02-17T22:21:58Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DerEtaFuTeewSAQdAo/PITsPBAKUdwzsLGOegBkKgjkMyuBM9ghjsu+rSl3Yw + AmuZrtFRAB1ue+eAkEHRUbw4VzxlTVib717P9JEnKED+MXhoQaJiHT9q6qH1SFMk + 0l4B8FmPdQMGgXuLVGmJuGqcSLiLlFnBR+GXSbMT5mv3JxfTJhdslAss3eaWIeg+ + 3hfMVA27mVcxxmenCpi0tSFMXQqh3mSGtb/p93fFz2bi5uFga+CfmyuJTPClJIyb + =tRXn + -----END PGP MESSAGE----- + fp: 057870A2C72CD82566A3EC983695F4FCBCAE4912 + - created_at: "2026-02-17T22:21:58Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAxjNhCKPP69fAQ/8D7Ili77aorhPn6Eg3+9wpxkhd1KU0a0fZh5O8aV0qQk/ + oAvq3+NZYULpMzPb2utLvFKFmKS2d4odbdTV8BhE6rWukRR7Kv5YZYksVjOobCTj + +uhpSA3BSccC5PNNYODRgUF+2sQkzis8raF/El7f+/Ec/owB5qnrWd7Tja4uW5Qt + 5r5q4nH9tb1HtIalrpI8tRcpZ+0JOzdHm2w65eCEirF+12gTSX1QP71KtjkjlKGy + +20ofHdjXpkUT4E9SsVVHpRK70IrPCqi7iv6dwKzUGhfckHDfGCoPEwk6/0WZsjX + r8EU50QxJIJxXkSBIcNVjvw3NviliJiwtPHR35noyYkXJXWlS/FVauxF44sSVvO4 + T2uTCdMhmKp1on518/bUcYWtINAy5w74hOZ+qojo2g5bAAu4mQ7bFwCK8bs08bL8 + beASn5XYkTr/a/oE5kdj1+EB2/VdZZED7w57NiiOEYXoHXNuHAd1DTCeoPz4VvqM + TrY+Cjal7YBg9GAGm4L8ZtqpfqmU5NQnmEYHhzXZhOjhrMtu8QyvlM2KichKnSfW + /AcADQSYwR6O+pLui9tXwUPNGEYQGHx8Wlmjvq6hvfcD+IlyzK5iM9Jg03nerQCf + 1IlEmyNLVt5kQqdtNh8V7kskgPrDsKuQ1kQta5Vq5btbCbIOlIEuzuv9RWXgNerS + XgGH29dML0Fta1z0/LKkWSA/U4V+jUviQDNpbQ2t/WaGQAAK2Mhj34WT55BFcVCe + CvqsHQ28CjAKKaLZ77Wyy03zFHEZ5HwdmJhpXAJFzUdM8jNBQDqc99iNlerFHxA= + =BLfs + -----END PGP MESSAGE----- + fp: F38C9D4228FC6F674E322D9C3326D914EB9B8F55 + - created_at: "2026-02-17T22:21:58Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA1Hthzn+T1OoAQ/9GiQ8HBWqxVKFiWt1Rpltpjqp2wJG+TSP/6RZNcJxn/Z0 + n6+SYdeeIIBr/cavORPlaY19bMD3NQMgqhNFiLo2q/ZXTm9QF1YJPRFpzEVovia8 + bF6K022kdEQYFirKNXPtyYsqbZ0hHiJG5cTlacfd2k2Nbx6QTWq0f3Ksm49zzdJh + or1hCoPHTqnuRwiBQtkwx+4jo0SAAe0xO2Cs5jCcNt8j7KYwmRKmH1Qgtclsb3cq + vqhh2WQLXD3HoVJxnjcyIElkCPCDpWtLYT+ZEqiWbiSkLwzsBHjtavgSAs3b8ZV1 + v7zq76ofB0YKN2LRbcpdygvFseqNBpU6uukcScpwhIsfj0DrHZQ9sufl/JIFF97S + 27pf/9hyJLmjTclaUfTREtPb8icyhwOE+d/Atw0sZxOKY4+hV4WF9pbDGiUOgZqi + a7E3qY+Iywk7jDgmU1eQGkY+G3PPXHbdhYr8v+Ig2lbp4uU1H+ab+d6r4C83pJzD + PrDXcletKkA4APwq/duyzox6CoxCpoBcFUtz7rHcYi78EfdFi4oMWVYimAlQCdng + JqeDXAArdoz1rj/yDwlFYybnHtXb65T01wF53brPtOkAVq6tE11hxe9dCiD6klk4 + SI5j9VE8wUEV0lf73AFW+gectZzkr5+7/QKe0IG2G5DkftK/J1nHA4ERFw7w0R7S + XgHrnYShza9Jovn/qGjZrvZFf6Pcs/KK92CpSBi1oMl7Lhll4R0tH+uG4b8pWuXF + uLSpKPsnhnxkfVczNRIFeDZ51ZuyjmYSrpt+YZnDGf7H853ROAC83gej00E4Mcg= + =SVTV + -----END PGP MESSAGE----- + fp: 5DA93D5C9D7320E1BD3522C79C78172B3551C9FD + - created_at: "2026-02-17T22:21:58Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA46L6MuPqfJqAQ//czgS1KbONIAv+/0g6iwcMPmBld0BDwJw3G0jlJCuSW6g + nSa1bq87WQzXUL/iM5XzURGzuMY5picYy/QTu/fi/XNG04lZpN7ZzATEkSwwyNzC + JsAei0QKAWPRRFTKSnsoL8QEhKD7asJmgfBDFhj0iYxClBQIXOSjQlAAfeK9o+Xw + oM7EfRSY9zUtJAziZs9LpkQKu7eJlq+n6IGGH9Jy1h0hKcxRuSujgz7MepNvLFc9 + wJO9LGieAgynZgOsvVLHN8N0v/PKew5LXnbDo6I35z4ASG76n+zlFDwYp3RDkU4q + Is9LqLJUAxPtIa2NLGRuFOO7fOg9IhhdRHdhylah1boM7+ElACDDbbt+v9d5qu/L + /GBZIn1pgSe0hlxfa2eAKZCS1cYlpBIKen768hJncKuTzV5LGDguJcQMKaBmbFOH + tCfvNFzWmWZBc/h8xkBpm0Hp9c2XFwcvzTL9BmaOgGzjUbZM8DSwFE+vlg/O7Ggv + lyoi78OEWktVLYUXxSBq3XhVxncOgNifL9w9bIb4lTJLjMVYmughFntHwSZH/8eq + nLw6sPQrINcjIMJEw/LUCnO4kmzrvCgqY5GtDvyV62c8k5nWXhpkl938EX7DZOCe + q5ZKMUfu0cUvyIQWIZly8ZsPDkPz6XQJGu3pifXs3vIiARUJY4qv0iAKRD2u85rS + XgFf4gDAoga+9rJD9Gj4Vhyjps7YmU94588/CeHesl1/Zy9+neRTrHMoo+KqUpC+ + O+CTgW85eVnRT9mgDlLDsFqZElZZWkdn1yJfD9NlhMvswsn/NkbB2yT06HbeKAI= + =Uh/J + -----END PGP MESSAGE----- + fp: 8996B62CBD159DCADD3B6DC08BB33A8ABCF7BC4A + - created_at: "2026-02-17T22:21:58Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DQrf1tCqiJxoSAQdAYl5yJyayyLJfKcs7YoVj5SorGPw8k+39iR3k3bCbSwww + PKSvjI7m1dLxzGqsYIfavX4sYqP1az/ljDxKKgMI5fX2FUGcWT6/MXF0HTLxDPLR + 0l4BbD2ZIYnL39K7vGc0OY4qi/BkPh1xKY5XMBe1tBsTqTHNboIpW5vKYO/lS7bu + PXyFZTolOiZfefybYoD1DEoPgNUCCnnqq+TM6g1eOtTQ4IsoUH3IjZS/QjPy/jsE + =uSMN + -----END PGP MESSAGE----- + fp: B71138A6A8964A3C3B8899857B4F70C356765BAB + unencrypted_suffix: _unencrypted + version: 3.8.1 diff --git a/config/hosts/git/sops.nix b/config/hosts/git/sops.nix new file mode 100644 index 0000000..b4548ed --- /dev/null +++ b/config/hosts/git/sops.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + sops = { + defaultSopsFile = ./secrets.yaml; + }; +} diff --git a/config/hosts/matrix/default.nix b/config/hosts/matrix/default.nix index c0a7703..5ebf182 100644 --- a/config/hosts/matrix/default.nix +++ b/config/hosts/matrix/default.nix @@ -3,9 +3,11 @@ { imports = [ ./configuration.nix + ./mas.nix ./networking.nix ./postgresql.nix ./matrix-synapse.nix ./nginx.nix + ./sops.nix ]; } diff --git a/config/hosts/matrix/mas.nix b/config/hosts/matrix/mas.nix new file mode 100644 index 0000000..0b8c98a --- /dev/null +++ b/config/hosts/matrix/mas.nix @@ -0,0 +1,124 @@ +{ pkgs, ... }: +let + masSettings = { + http = { + listeners = [ + { + name = "web"; + resources = [ + { name = "discovery"; } + { name = "human"; } + { name = "oauth"; } + { name = "compat"; } + { name = "graphql"; } + { + name = "assets"; + path = "${pkgs.matrix-authentication-service}/share/matrix-authentication-service/assets/"; + } + ]; + binds = [{ + host = "localhost"; + port = 8080; + }]; + proxy_protocol = false; + } + { + name = "internal"; + resources = [{ + name = "health"; + }]; + binds = [{ + host = "localhost"; + port = 8081; + }]; + proxy_protocol = false; + } + { + name = "admin"; + resources = [{ + name = "adminapi"; + }]; + binds = [{ + host = "localhost"; + port = 8082; + }]; + proxy_protocol = false; + } + ]; + trusted_proxies = [ + "127.0.0.1/8" + "::1/128" + ]; + public_base = "https://mas.hamburg.ccc.de"; + }; + database = { + uri = "postgresql://mas_user:mas@localhost/mas"; + max_connections = 10; + min_connections = 0; + connect_timeout = 30; + idle_timeout = 600; + max_lifetime = 1800; + }; + email = { + from = "\"Authentication Service\" "; + reply_to = "\"Authentication Service\" "; + # Don't send any emails. + transport = "blackhole"; + }; + passwords = { + enabled = true; + schemes = [ + { + version = 1; + algorithm = "bcrypt"; + unicode_normalization = true; + } + { + version = 2; + algorithm = "argon2id"; + } + ]; + minimum_complexity = 8; + }; + }; + # matrix and secrets sections in secret + masSettingsFile = ((pkgs.formats.yaml { }).generate "mas-config" masSettings); +in +{ + environment.systemPackages = with pkgs; [ + matrix-authentication-service + ]; + + systemd.services.matrix-authentication-service = { + description = "Matrix Authentication Service"; + after = [ "network-online.target" "postgresql.service" ]; + requires = [ "postgresql.service" ]; + wants = [ "network-online.target" ]; + + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.matrix-authentication-service}/bin/mas-cli server --config=${masSettingsFile} --config=/run/secrets/mas_secrets_config --config=/run/secrets/mas_matrix_config"; + WorkingDirectory = "${pkgs.matrix-authentication-service}"; + User = "matrix-synapse"; + Group = "matrix-synapse"; + }; + + wantedBy = [ + "multi-user.target" + ]; + }; + + sops.secrets."mas_secrets_config" = { + mode = "0440"; + owner = "matrix-synapse"; + group = "matrix-synapse"; + restartUnits = [ "matrix-authentication-service.service" ]; + }; + + sops.secrets."mas_matrix_config" = { + mode = "0440"; + owner = "matrix-synapse"; + group = "matrix-synapse"; + restartUnits = [ "matrix-authentication-service.service" ]; + }; +} diff --git a/config/hosts/matrix/matrix-synapse.nix b/config/hosts/matrix/matrix-synapse.nix index bcc097d..51dc590 100644 --- a/config/hosts/matrix/matrix-synapse.nix +++ b/config/hosts/matrix/matrix-synapse.nix @@ -41,23 +41,29 @@ max_upload_size = "500M"; admin_contact = "mailto:yuri+ccchh@nekover.se"; + + default_room_version = "12"; }; extraConfigFiles = [ - "/secrets/matrix-registration-shared-secret.secret" + "/run/secrets/matrix_registration_shared_secret" + "/run/secrets/matrix_mas_config" ]; }; systemd.services.matrix-synapse.serviceConfig.ReadWritePaths = [ config.services.matrix-synapse.settings.media_store_path ]; - deployment.keys = { - "matrix-registration-shared-secret.secret" = { - keyCommand = [ "pass" "noc/vm-secrets/chaosknoten/matrix/registration-shared-secret" ]; - destDir = "/secrets"; - user = "matrix-synapse"; - group = "matrix-synapse"; - permissions = "0640"; - uploadAt = "pre-activation"; - }; + sops.secrets."matrix_registration_shared_secret" = { + mode = "0440"; + owner = "matrix-synapse"; + group = "matrix-synapse"; + restartUnits = [ "matrix-synapse.service" ]; + }; + + sops.secrets."matrix_mas_config" = { + mode = "0440"; + owner = "matrix-synapse"; + group = "matrix-synapse"; + restartUnits = [ "matrix-synapse.service" ]; }; } diff --git a/config/hosts/matrix/networking.nix b/config/hosts/matrix/networking.nix index 370bbbd..5fa1aa1 100644 --- a/config/hosts/matrix/networking.nix +++ b/config/hosts/matrix/networking.nix @@ -1,17 +1,19 @@ { ... }: { - networking.interfaces.net0 = { - ipv4.addresses = [ - { - address = "172.31.17.150"; - prefixLength = 25; - } - ]; + networking = { + interfaces.net0 = { + ipv4.addresses = [ + { + address = "172.31.17.150"; + prefixLength = 25; + } + ]; + }; + defaultGateway = "172.31.17.129"; + nameservers = [ "212.12.50.158" "192.76.134.90" ]; + search = [ "hamburg.ccc.de" ]; }; - networking.defaultGateway = "172.31.17.129"; - networking.nameservers = [ "212.12.50.158" "192.76.134.90" ]; - networking.search = [ "hamburg.ccc.de" ]; systemd.network.links."10-net0" = { matchConfig.MACAddress = "2A:A5:80:C3:8E:32"; diff --git a/config/hosts/matrix/nginx.nix b/config/hosts/matrix/nginx.nix index 74d4291..5a4f716 100644 --- a/config/hosts/matrix/nginx.nix +++ b/config/hosts/matrix/nginx.nix @@ -17,6 +17,18 @@ ]; }; + virtualHosts."acme-mas.hamburg.ccc.de" = { + enableACME = true; + serverName = "mas.hamburg.ccc.de"; + + listen = [ + { + addr = "0.0.0.0"; + port = 31820; + } + ]; + }; + virtualHosts."matrix.hamburg.ccc.de" = { default = true; forceSSL = true; @@ -37,6 +49,11 @@ } ]; + locations."~ ^/_matrix/client/(.*)/(login|logout|refresh)" = { + proxyPass = "http://localhost:8080"; + priority = 999; + }; + locations."~ ^(/_matrix|/_synapse/client)" = { # Only proxy to the local host on IPv4, because localhost doesn't seem to work # even if matrix-synapse is listening on ::1 as well. @@ -48,6 +65,66 @@ ''; }; + locations."~ ^/_synapse/admin" = { + # Only proxy to the local host on IPv4, because localhost doesn't seem to work + # even if matrix-synapse is listening on ::1 as well. + proxyPass = "http://127.0.0.1:8008"; + extraConfig = '' + # Restrict access to admin API. + allow 185.161.129.132/32; # z9 + allow 2a07:c480:0:100::/56; # z9 + allow 2a07:c481:1::/48; # z9 new ipv6 + allow 213.240.180.39/32; # stbe home + allow 2a01:170:118b::1/64; # stbe home + deny all; + # Nginx by default only allows file uploads up to 1M in size + # Increase client_max_body_size to match max_upload_size defined in homeserver.yaml + client_max_body_size ${config.services.matrix-synapse.settings.max_upload_size}; + ''; + }; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + + virtualHosts."mas.hamburg.ccc.de" = { + forceSSL = true; + useACMEHost = "mas.hamburg.ccc.de"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + locations."/" = { + proxyPass = "http://localhost:8080"; + }; + + locations."~ ^/api/admin" = { + proxyPass = "http://localhost:8082"; + extraConfig = '' + # Restrict access to admin API. + allow 185.161.129.132/32; # z9 + allow 2a07:c480:0:100::/56; # z9 + allow 2a07:c481:1::/48; # z9 new ipv6 + allow 213.240.180.39/32; # stbe home + allow 2a01:170:118b::1/64; # stbe home + deny all; + ''; + }; + extraConfig = '' # Make use of the ngx_http_realip_module to set the $remote_addr and # $remote_port to the client address and client port, when using proxy diff --git a/config/hosts/matrix/postgresql.nix b/config/hosts/matrix/postgresql.nix index 62b600e..d81ab6d 100644 --- a/config/hosts/matrix/postgresql.nix +++ b/config/hosts/matrix/postgresql.nix @@ -11,6 +11,11 @@ TEMPLATE template0 LC_COLLATE = "C" LC_CTYPE = "C"; + CREATE ROLE "mas_user" WITH LOGIN PASSWORD 'mas'; + CREATE DATABASE "mas" WITH OWNER "mas_user" + TEMPLATE template0 + LC_COLLATE = "C" + LC_CTYPE = "C"; ''; dataDir = "/mnt/data/postgresql/${config.services.postgresql.package.psqlSchema}"; diff --git a/config/hosts/matrix/secrets.yaml b/config/hosts/matrix/secrets.yaml new file mode 100644 index 0000000..dd8daef --- /dev/null +++ b/config/hosts/matrix/secrets.yaml @@ -0,0 +1,151 @@ +matrix_registration_shared_secret: ENC[AES256_GCM,data:5fKfTqwoUreSIPbua5t1lYZFRnQQjNzFvrIBVIBfKWu20kH4BhlDboL/zYnhWLELq/KykX/EUvijoZxxTnUiN7T8H3L6fKOCQKacZkIwKfg/JjqLVnXIaY0JOwg=,iv:Cazhdo7YR0zSgiyQoHLsk2e4dWGSoSfEtOuMA1LEJcg=,tag:KsbnGvEyRbzbIXuAayQk5A==,type:str] +matrix_mas_config: ENC[AES256_GCM,data:FxZHMYlqAlr/0rtjO3R58h2Au7hXY6zYv56bQD+LufA9Jrzi2vIDQe2RPQmJdkQ48sDgFiSGtJ1kqZVCDc21FPtjbYcJuCYKZK/opJag9MnXae/ZKBlsWk2QWtxGtWM48mwIw+8aBrSctOHA9Ibq76yQb8l2ubyjtHn3wYM=,iv:0YRfVkim4NNAUmV9MzErQoXZhdVKwa102D+hBT1is/w=,tag:l+9NkxOjXoxD1WalDgQlJA==,type:str] +mas_secrets_config: ENC[AES256_GCM,data:lgfGW/zkJ3sdmXehzEMGiBUjIvcjnSma+BjBshxAKTPKTxQtllk4GN8VI7AII91u9mG0231bcTb+sq7wm+nuVLxOY9wCuCGA4/Tsa0QZmphXqWzRXx0yuHawW6WCC3U3EmyPiG9m0/a+Xt7by7+ep1p4n4QrDKZBCFkdANCera2MA1VuzVUr0o7xCul26khpdN0dZ539wrUGdocKNw831s+KUdqadB6I9iQ7f+/l0EFi7HlWQ+vvF7/KAYuoUh2jS0MGhBTRgSDqr17QZ9TB7PEQRpztQygqgoqYIl+IVYi/AfmiyY10Zf7GFE9yHn3cd7N1gRRGj7jpKlW38QP/GOF/6w4pOJxovdsNzJRT9lAuFSyQqudgXgM3/uJQwQbguBf/aSGS5pWDp1LxQffLiKzQnfC5RJnYJ87f9n2908eZ53jlhSRYDtAqfbbwQNUsVvATOigcUFKmaDMwGyKKdyiDE3+mXH9Twal5K48pl3LgjOtajR9E23fR/3lJ5HfFCqCdL7rn8AYxFzS0B5G9r59ik7yhHSWiB1jPVhIQTBtbPzdeuIQUkWmRjpxi/I1eMgPGMoHlPNRJowg7Rsa0hvfYrV8caO/TVILd927MmtmqQ8BRDeCxHNNRC3fZVkqcVcMe5vFzafH3NlY+spsNPUJiA3yQX3ahKpByJP/NM5zlSR+y2ZgyM+eXVFW9ORJT6gvZnAtq6rWTEyMXk3iIQUgbw9ume1VN7H/TQur2Vwdaz646TqzYSn2KSXCOwoY/mNNlSbufXvK/76XrW9Ckhhl+tdvHGlzbVTzZJJM8j5/PI9XukCEgPbbrvL/DzXv5KlSme1B6JmGJZlqsaJTBrYBItWzAxiGKQg0e/f72Ay9mjoYqVCPVYG0ms8WECfw4S+45Q9gNoPvG1XLrOzlRNDT0UKnuE0am5H1x6vlmketzgnPMKSZVkWqNcgPA/6BlUkxF7Ne/+Q+506d6w7AyXgXfhFwg+cEyAqXjBtB3paFSLkm0U1OHfSBWsgbgMK0Xn8GyA/KLBV8bLINwR+qTp5Gdz+WgBQTfTb1m4OWhyolx1SkxjnUFveLdZRon3CXH/K34S7X4S8B4y/6z3UHGmQcK5g6HOYNQtuCGKlLAbZHBhQgmNJpdGFuwcdC2bdgHfcNl6eEazB9k90COjJTU030N5fzYq5hOGVL3xBUmvj1LaYEsnJldsfXjfas3JA6iAB9lcOfK2su6F1M1v+qr1SJbbGjeUmFt6q7B7LjrPnZ34Q/CO3PDR+UiuQD5dMpHGc+L6yB5VbMYs6hirlWVQlySvFYnOhaHiUbospLMzxwSi8nWKiMRiFGYojg/2YrpFlVv3T684vBGGGdL/MG7docgEdBANsOrf52nsvvT1921A09z/mL1PxHHJN0XkaSV5cUd1vLv2Ba3dHMs046ls/TrCKcMXQbl3FibSBP+yEg75xzk9aWzjSPUfnQcaslOo1T3UIrYLaPGjmzoMtLBhtNB1hOQh4tQpybHL3sMr52zxzj0vwA3dCZTy8+5SS7tD5hmy1qlnk19+aXaAFPgUZXETBk3r8c208Qi2lbjCHI/zgeQD/1J1ihtSu0EeJR5Kz9a99ztUD5AnyrZXpawsPYDcxjhAVFDmqMClV2pjO/Bt+QcFVMt46XKFftzGk0nXhN/9ziVwTpFYxegq7hJoebU0qG37tTHol8KiaZ6RtsVNwDAuFY4lGgDbnS4oLDxzVDoqY2vsk6WldowAtk8Gl4sicsXmC0WtyVF3KYn3h//nUty+KgxwxF30PMzrxaiK2BmJRSmUQecaYfv4xtcq4DcXkreG4HsnsEsExcMMW1xURfAVG5OC75RWW6yKy0mSVkUGUox2TSEvvJWuvX0yyYXaU0VfXqUTfw9ZFQEHKC0IvP/MtLxyCh5fWGuTGoDyin99b9v+Rf12LwZtkaLxqdzGz8ZuR+JVIhfE0cy/1/M0JEw3NexIPUf9b9svppQA/VGzRAQcwCfeZ4/S4LDC1xWPZCZi3+B4nrCYV1L6eZJIKhGQQzrF33abQ4KPmY3+NyGgA65308G3PhIerJzpvpq+SwRBtrLjXIM5wH2t6Azk8AEVYruZ+2SqLAyFXmt+Zn1uuMK+Zfscj+ji7rZ/Qyfr/r0m2Vc5XVZth0FCQHdL1Mal8bIW31q6tF4LVtMmK/7KrjypjRqCH7D1kUiaafQ74O60YYoS+sPF7emz7xTZ4PNdY5w50qBWcdm3WUW/ObBFR1YZyGd/OEEQXqcUzsSYJ5aMS1ohyIDMkWeUUAvu2digiQgHzyY1XrvjWzHGL56nsWe+x2VTS600d6aY9FYZ5/yY+h3B96hcs258vn9xTTJsMZHIV8V8ZoC1f6Gb4zHpulYNiAA9PjXHHORU3N4DXNjI4jpFmIgQvF7ZQAd7CzUHXXbdwHVD9IQeKrDTrcvl3ErmQumuM/fVD77OtegrBKDYQ/VVS1bPQfX7rnaQQ2hD2LEchJAPXTfI5eiEuH4nJ2TK0uSWHG4Yxau72gx8ASPeNsX5sHf8yIDlx9wlNSRnO6A1rs65uYfSSwTtOX9irkWvDvBUQvYJGtenk2mABAJf9+qoupuF2WfpOCYc1dWka9+vWxj3g+sxIN2KV4HUoAk5fkWOffsdiNVKyxKprrKHZX+X7e3+6azxVbEqQoEQo4yqE31dOPfZBjPntRwt1dVmpKGAQClrVcBfCD7J0+8J8R4r45a4Svwe7zAmef5Icvk3RHCUHKm0ZD+yIaDzoABDLXX+68vwrM2AgNNw2J3QcoKakpyyGtCC+oRlutqn8wAodC3NvnNmeBMuCJaZaTvypDoTnOyvNTmgK6rJZPt3RWACpZvq81tBrEgTjdWFLqPwlFzNhXGvKxIf9Md/ivau6pREa7vBxT1fBqV7ZjGOD1nWsXuq2FM0tKJXNL6cU3DzxVzK3Vll60qFa0s/MZjKL+1lKJaDTtQA156en2mQJo23fQ5uJxZt6mDOY6Qrty5/L5BkiY/vRDp/78orTh7UyW0zLK4Bgjk8/lfiUodliFjTgDnV619XyUK7J2PLzg9HAlbOTFczZS2JImEQKzLGSe3Byy7U/I45bD6TUFlzCBmDqmeIAmIbiu5IVGedqdbuLSJHp3JweR0/Hjho4SzQ3evgMMPG4B5wtYzKhASBcqLhny7Vrn4LmXGlIgRYSp5SxbgsufkORfa1IRviUFoePRVQahCTU+O6DyrwqFWIrAIk2W+O7rYuw83OjGDdFJtU8KDh0AQ6SAry1XLFervHwEtj125Tav9+fg622VnClFpkJV+7QxbtejulREc3BjmTqsPuW99D8lbQrne+BkAFSvNdy/DnHMvPNRYGoU9y39qvGWawfiE9bi39UNDDr+7oPJpnQX4AvrDlF9VNHFB9W3O5772Nh6cd3R39Jzb6jnNg3wC/WRgchKs5kS4WR0T/xhNFDMoAk1Hx59MdhsR/BKQKCUHZGW2tuUBH3Mls90xx4cmZwPQrvaR4NbanTc6MhMkXBDD9828lMC2UK3yv+VL66g2Q2uVTLjAlQaXDVIlSzzpgHJyi35o3CupTDOhUhS80sYA68dcNEcvqHpwoZ1apL98kc8XPQvf7I/885NNLhl3K3MHLiasFoLsFlp7xwXUFSuFz0sI7l/xGkotazDvWdhCS7uZJY+zVxV6Yzus2+ql4fh23kFVVNni9OVGcrDbv0zIWUH956KI0u4r0n3+QinCcUinTTFbrlDL+/WX3c7VlzRUcQ==,iv:DdcflAdm5G82WzP9hDBK+Cy2X6ncETdYdxYJmd8LG1U=,tag:3lp3SO4WI8/gRp0OJLYK2g==,type:str] +mas_matrix_config: ENC[AES256_GCM,data:W7tyChbHM+LWYJYuuWSXL1wg8hKFA6UWHjVFOBQMSnFgguwcE7cg5LSnt1Sr/6TaPQP7+2y0sma0fyKlJ+zcUc1k2OPbJLjsrdjNjz7eMSlzmDESRLo3TBSyNjAKjlgWkEftMZRrrwFmA/cR0PdPchTLfBJnvP2vcLpDPEdoitrQFKk=,iv:FvkXV9emW7l1q1KRk2CP2Ec2pIZfBJ6JlpcIx37mVcg=,tag:p/NaElAD08dSPAWOA/Htvg==,type:str] +sops: + age: + - recipient: age19h7xtfmt3py3ydgl8d8fgh8uakxqxjr74flrxev3pgmvvx94kvtq5d932d + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwTHIvZ0ZPRTdrc2VmY3F4 + T1NqMWU3NzdKSEdqQy9OOWwyaUErWG56MEdJCmpFUmphd2lhUEluT2NrSjE3YWJO + OVRHVk1YTWQzdmgyM3dmMWtCeUgrT0kKLS0tIEZSWlZGVWpUWHQ0aUY2VkdWb005 + Um1hd2FCUzliUjlvY3JGVTJtV2NxWkUKYShPlhmFB3f/8fSdJKue61LR7NqSW3bq + JsmPKkofk3bzMbkUGm9fWey273nOLG3SNcx+ANDCxJUhOQ8KutaOVA== + -----END AGE ENCRYPTED FILE----- + - recipient: age1f7ams0n2zy994pzt0u30h8tex6xdcernj59t4d70z4kjsyzrr3wsy87xzk + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwcFdrdlhNYlVmYmhoMU9Y + aWZxVVVmOTRHNkJWSVpGSytQOGNSOWZ2NmwwCkdENlRPdnk3WDFRMFM5Z0xEMFVT + NVBJWXo3L1lRNTc5eko5dHdyMjEwajAKLS0tIHQvZkticURkNFp3MlkvazlzN1N1 + R282OFVBVXZPcGNWQllXRS9HTXhobUkKpyfxx4gEcWFX//ntF/pWc7HNmeRIlF4K + DxjEnRn+PJol8kpBqttXPSYr5EydboA2O2Fv4EmQc7l3VQKdncrlOQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-10-12T02:48:54Z" + mac: ENC[AES256_GCM,data:xmxSQJ75JwsMPzPIGUgmtijRre7HnU3wpCvaPJo+XVXsC3wRnSwhRGc38DWxKIljx9HAKGMXV+n0iT3+bnTkeUNYGaUMROs82cyfqxfCd9pn6Qi9ytUb/Oec+oignDlojg8sMKZJGyUguN9sdSRootgSe3/Z4Di/IxhXhW3cDZ4=,iv:cLtqVhLcFxrlzFim+jgVpFlmJaRzmm4zdPkRCKOd6CE=,tag:MnZrm5lwYH/7YEjG+vCIKA==,type:str] + pgp: + - created_at: "2026-02-17T22:22:00Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAz5uSgHG2iMJARAAsLBqwVkmgFjAHkgg1Js4o1G0wxf4wSmWfBqGGlQYzuZo + Wn/RojGmly81Vx3GYc9qC9+H+1UKdOGOHeAeBftaverwJdpAay/DdAKaZ5FJxI0b + OgiACiQxaaSTVLAPIZYw8xCKkVItoR6i1M4d0GGwr26hFNUgj4fSdVR2348KFNmZ + tKZIDipjS7WMbAW1etMdY0oPRAxQfhxRVp7lW/Z2bJYbmnug8FGaj5EwzRrSqGrI + li907EswOElX7YijnjrJ2I2B3Et3sHkwxq9jSEZX89EBHJbwy+fFWD81oKugDkwv + HP6a6qMhYBmp9D+hGcHAyyHYXmdQa6HXSv7PJvicHTAQ0iLodPEFz+Z9gblHV1Y9 + xq0ciM0N8NbTmGl6JOfeg4dB1CzH9N9TH6q/+Yp+ZZnMJfzjx+dV89VCPvt8KAH2 + +fj5Ru3gwGD6NpvNP0aDIAIygzlJE0Q1b8AtMXzHNKfA8jlGqGalkNM5/Q0+rJAA + IleUVMXJz07o8QvrDZKTq+FYq6qbcPFGjvV7c9mBcW6/I6rT59OLiX/eJHbfvUAE + SrLpGDi7kOOiWlFmALLG7+pj7XNxxNlmeG+UBWa0ZEMW6onc5HufjpS6FkPeSfAQ + dXSHq2wamtt1o6B3TsBmZAliZ7b/DbFKTl8ErE/XnWGLNAMqJD6pCDtJSwvDpC7S + XgE11hisql+hIYGrjXrHe9DeNtgZlKd6sYQKGhaMtA/GeH933XVXjA3NsN3GyXDG + MzJjKPkRAGCfRu2VfLv6hnqjzREgsiBpS+XLitZezW2/MtkEVvYN9BwWbe+MUsA= + =v4J/ + -----END PGP MESSAGE----- + fp: 18DFCE01456DAB52EA38A6584EDC64F35FA1D6A5 + - created_at: "2026-02-17T22:22:00Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAw5vwmoEJHQ1ARAAuY3IZqvQw2evpOBN/A+15eqpxK7uS8YCzxxQC9Bjn4LB + kwO1b7eh/Q3mTYAG4Xl5tix0Q9uOFM5epftk165xCUu9p388V4Hgx/pGvn4ODhwH + AqIRdXiv4rOp3uN22ZLQPQE9hdLIg8AUK2s87R/vUaB79vZttY76N5ucBDRB5KGC + tPQvggsMi6vCXs59o75nlUbMtVTRZMvERwf+0bv809vGLX81QaZUItcGZyOvpM2t + qhRjYZCI4g7ZDLact0nJA79msJqrjSBsMifmvcfUFoaWps7P1S3DuvBzd6tt2dzU + LKwS/e0BLluawwla9FdoPXy8Dd57zPFVnO0FmsDYtC8qZGQl4BiUtQqvmDxrVmV8 + VvcBMdyyLWyYbCvWLqpxpAN40whis2zGkfN3llK5G6SAhIqhX/KnlOLmIj3HN0pm + HuAls9/y5pebxgBFrPdhYRvsxehQRGmffjr3WW2Co5o6y7Mazss4KLO8FiRvfbRa + OIBEkx+V2CokjRnNnCaOFgBbpzinabfW64eP/6F4pTcYerRVp/EEgioa6iYA5kJE + vPjc6QRh15hdjLKpdGXOFS8JLMlk9mrTECmuQZNb0Uo2BJtbxbOqCMSdX0woF6/M + zRNZJfTvRtaiUFCCXOyU3RhMtqMK+Qwbw57DMDklh2qHsAR1UpS6k9RtYN3j3PDS + XgEgaPSPrGE0E68ydgguomvtl/kVS/P5GGSo9DQ0YhXMPyBV/MIkMD3mIpNmbEbn + nDNtvDvOjCdmfEotALsWs5VeRTqO9J/GcpPxC/+b0gTIvAjnWj3ptTsz11Jnf1E= + =Wkdq + -----END PGP MESSAGE----- + fp: 87AB00D45D37C9E9167B5A5A333448678B60E505 + - created_at: "2026-02-17T22:22:00Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DerEtaFuTeewSAQdAWCQaHsUsVRZ81mhzxREzdj0xMReLH38JmXu515OSFSUw + 76iHcTSqMeclrg1Uio4xhGTctSMhAv2t4yic/ocP6EYNsM4yQUsBLtM+xm7Bu2Qu + 0l4BXcl9T+kQ+xICQySM1g6g+sHxrKCgtzNB22vG/jqeQatdh19OOWlibCXhicTl + Bv4qKPSBGBdk9KYwAN9fstUfmbGX21E5DXJlFGhfdnvWIh8biw/0aJ4floOk1st+ + =dh/i + -----END PGP MESSAGE----- + fp: 057870A2C72CD82566A3EC983695F4FCBCAE4912 + - created_at: "2026-02-17T22:22:00Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAxjNhCKPP69fAQ//VnKyJB+ogP2eCVpjvzkXs8ip5xe1aYj06M/cIw8I8Awf + aVVBo3DTYGrX1ke+E0WbTvwbd37T/M2RyYHlFQclIfnZCfa12gSrg+5ggInZGRl2 + D/d3Zxdz8HjML5DpXGQ3dLGi1SbWn048gmdx2V34JLWvxu5XpOMv1RBBLcDIoqVS + HWGa+/tXAbyT9xwZJAOEVErlrTWXKyCYPLsTL89x8E5jqPijJoDTFle2G8+uv70J + /Gn2Cs957jFocPrZEqIDVwkf0jgQllkTELTNq08dm4wqCHbScxLgUxUyCSobeCk8 + yedGAJ6tFrXywUb3fEoKcnGF/5TG+3XatJC1aefsnsBxAkDT8PX0nTlBxhHwu3RO + IEBtlU5icVKenRPM3mFEkmEIR3B3+zONLGJ+8PqbZ6OCZuImxHgVat8FI+vXE509 + 1Dd/l54an5jskXpqreDJEDfeZpeUYkMMxjHdg8x+ilZlxMHoi+NeF9ocEfTrLA2y + U0bUguEmqW7thA+J6bcoJNHlXsd077+97mN1l8paBctsllVwzZYoQp64ICAx7PPY + N9GvWBuupnbrWxMS0nnMpF0oPKnN4tknflrC3ZacPtscRo7BISy0RHhvJG3SZ212 + eRCM/maYnV8omAaIMuFfbuv45yPKkLq1MPE9NID3wGHkJqmIpm2ggwA0A6g/h+fS + XgHmJuXEV6v9lxtaRD4iFsbLL3+hqfVfQ9W2IPbARNbOKIYplgJu0tWw96y6fnIf + R1h+z00a84R27N3NmuV96Vyg4TvWKTAmWZzmZYIM/QfzQtMszwQ9PWOUZeHGVXs= + =TcqO + -----END PGP MESSAGE----- + fp: F38C9D4228FC6F674E322D9C3326D914EB9B8F55 + - created_at: "2026-02-17T22:22:00Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA1Hthzn+T1OoARAAmnSREMlYFwDLJ/9LoUAO2NqrylMZhIPvwU7HQleKe7u2 + cdhGZKXbPCMLlWgCM6Z7wpVFeUT2OPI0vkDIL6NNlJ/l09j6CunNfWY/4qKc9YzS + J4I0tfY/cvnDRQrpPcg7rIgM+ukxpOcxmfc02NGqK8EMyZurFNmrmJLdob8nsoIl + ZlyPHMEw2KuSzDsX688OzO9HozcHAJVlG5Aw1lD4TCq4Fq9HTPRnmq+oem0gteDT + VZ2Np+Q5zc1NYXU36lmkBSHPAc7KDIplkc7eC1g8w56xk8mMrrEwz/qUhgIYNQ1L + wicf9nVHxaIiPdUpjznL0yGJS2BEbFfQPV9p1dkKX+X+3rBJiVXvGWzlIT1v5AhA + ixXNMYjwpQ6hgytw372q2FltXAcwSggBcmIIgq9DNHP9YtCmI0v3jfu2ZY7HVJNJ + MIJlozlrUrzKjmjhNUXjAjct/N8rKkBtjwruKWWaPERFs0OT7oHPjVphTHo1UDd3 + OhYBZ72cjYCDZyNYk1z79OiGey83o9JAFZv3yWx+LDVJ9l94dGkO43ONXOE50aSE + VSvZlDL12IRg47b6gm+a3DtP7+8mFMaHhvCxNiOpkoFZJQVtZdoFXtwdf1ZAOUXa + sx9tdnWLLGEAR6d9MFXEYyJx4ykfp+Ew8+/eo213ZL4ns3ASGw0wGw78SQebUn/S + XgHeLtKQqx5qhIRcFz78GMZZUkMyljFVddUz3rMy4npPRQoGkyJYiY/pQI55rcHV + 8ShFKDpZurafdf1kEk045SqFzwWvubet+k3VpkxPAlFBlLwstpvz1CQpRqhwZCk= + =HQM8 + -----END PGP MESSAGE----- + fp: 5DA93D5C9D7320E1BD3522C79C78172B3551C9FD + - created_at: "2026-02-17T22:22:00Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA46L6MuPqfJqARAAq1tt3Yc0tQ3alerxjWUNSBzpa3Nq5W1bhZ8d+qMDWm8f + SsIBYUMNbPHvWOA6tLIzeMBIoBFneQwWW7fw5vpGzaATURTaMiu+Ws8Q2h7JhYaH + cTO/0QLTNtrwCMJOWkofgauf/3eQCwz+QNBByULSMESyyxYqaY/Sp5Vkfp9ddNUc + dy6YOKWGwxpUU3OrKvSeO08aIXL1dpw2bVaroOW34xf1MPBX/hEV4ix1bfkPUrDj + Oc+kXlCLrJSf5TqQhiYYOijRWCNmy31b6ww03mb5OKOHbs4zGAs6Wa1KFxy3b5C6 + AV/v+JWHMOBvbU4jhhrIsPXUzp3AyZfTmFbOFn8LHQmlB4wS/poEU5qczJbzVsyU + OlZE8OVsdLDn7KvjoUDk4PClxLMk8LjQWDdoB9XxxmCV6jtou1GB8BPecoa2zknT + BSzC9JDGmoKnXk53YiPe59YNTs9Gxk9OeuCovmygaQbKXeKNe4eg+3UH6Kd6Illz + osSutJjTJC6dkq8oV/7YkMgDodNyrVE6QqrY/F/FOMfqzftMfRg5S+B3NFg8r5JA + sgxxzGYTEpWv0PlK2nuWo8M4tWoso06loMBfRR2ViNmOtCvu+TDHJLAFim+yJOk0 + vzGifrUzvCRysvfXLj09gWPCoG8mNWLWD0xV/XiKLzE2cONRXMbuFeqqBdxkDZ7S + XgGdbwGy/jDBXe3422JPimFUhUKxTuFlcinjL5BhBUnaU9nKtvKj58eKoyfjPPfy + NpbR/flIJrQyoHpe+DSbkB1x88mOINYy8STh88MPAdvnEMqiYMH7RBL8hEfN/JE= + =zAn4 + -----END PGP MESSAGE----- + fp: 8996B62CBD159DCADD3B6DC08BB33A8ABCF7BC4A + - created_at: "2026-02-17T22:22:00Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DQrf1tCqiJxoSAQdAE/M7osrxnQX/N0eV4PzXqrzXLtblLY+Gr0znYJSpPiMw + Pw6O4Nw6u8JkVgZCo7/lG+Y86bsI412vnZxiq3pERlxQVHgNea3ArfbM7y0fH/pb + 0l4BQkt6yleg738hV8XY1hbJG2xruiw1p+Ts71v2qaFpSazOyz0RPrIIcWelJjkP + P5IV9g83IZMv3AWEGnUByACe8VpWJlFJ578tYtJIfnhsrDryCBubQ0gPsXGqTPPI + =mE/U + -----END PGP MESSAGE----- + fp: B71138A6A8964A3C3B8899857B4F70C356765BAB + unencrypted_suffix: _unencrypted + version: 3.10.2 diff --git a/config/hosts/matrix/sops.nix b/config/hosts/matrix/sops.nix new file mode 100644 index 0000000..b4548ed --- /dev/null +++ b/config/hosts/matrix/sops.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + sops = { + defaultSopsFile = ./secrets.yaml; + }; +} diff --git a/config/hosts/mqtt/configuration.nix b/config/hosts/mqtt/configuration.nix new file mode 100644 index 0000000..793807d --- /dev/null +++ b/config/hosts/mqtt/configuration.nix @@ -0,0 +1,10 @@ +{ ... }: + +{ + networking = { + hostName = "mqtt"; + domain = "z9.ccchh.net"; + }; + + system.stateVersion = "23.11"; +} diff --git a/config/hosts/mqtt/default.nix b/config/hosts/mqtt/default.nix new file mode 100644 index 0000000..bc91d9f --- /dev/null +++ b/config/hosts/mqtt/default.nix @@ -0,0 +1,9 @@ +{ pkgs, ... }: + +{ + imports = [ + ./configuration.nix + ./networking.nix + ./mosquitto.nix + ]; +} diff --git a/config/hosts/mqtt/mosquitto.nix b/config/hosts/mqtt/mosquitto.nix new file mode 100644 index 0000000..9bc02b0 --- /dev/null +++ b/config/hosts/mqtt/mosquitto.nix @@ -0,0 +1,34 @@ +# Sources for this configuration: +# - https://search.nixos.org/options?sort=relevance&type=packages&query=services.mosquitto +# - https://mosquitto.org/man/mosquitto-conf-5.html +# - https://winkekatze24.de +{ ... }: + +{ + services.mosquitto = { + enable = true; + persistence = true; + + # set config for all listeners + listeners = [{ + settings.allow_anonymous = true; + omitPasswordAuth = true; + acl = [ "topic readwrite #" ]; + }]; + + bridges.winkekatz = { + addresses = [ + { address = "mqtt.winkekatze24.de"; } + ]; + topics = [ + "winkekatze/allcats/eye/set in 2" + "winkekatze/allcats in 2" + "+/command in 2 winkekatze/ \"\"" + "+/status out 2 winkekatze/ \"\"" + "+/connected out 2 winkekatze/ \"\"" + ]; + }; + }; + + networking.firewall.allowedTCPPorts = [ 1883 ]; +} diff --git a/config/hosts/mqtt/networking.nix b/config/hosts/mqtt/networking.nix new file mode 100644 index 0000000..7a34cbb --- /dev/null +++ b/config/hosts/mqtt/networking.nix @@ -0,0 +1,21 @@ +{ ... }: + +{ + networking = { + interfaces.net0 = { + ipv4.addresses = [ + { + address = "10.31.208.14"; + prefixLength = 23; + } + ]; + }; + defaultGateway = "10.31.208.1"; + nameservers = [ "10.31.210.1" ]; + }; + + systemd.network.links."10-net0" = { + matchConfig.MACAddress = "BC:24:11:48:85:73"; + linkConfig.Name = "net0"; + }; +} diff --git a/config/hosts/netbox/configuration.nix b/config/hosts/netbox/configuration.nix deleted file mode 100644 index 50a584e..0000000 --- a/config/hosts/netbox/configuration.nix +++ /dev/null @@ -1,7 +0,0 @@ -{ config, pkgs, ... }: - -{ - networking.hostName = "netbox"; - - system.stateVersion = "23.05"; -} diff --git a/config/hosts/netbox/netbox.nix b/config/hosts/netbox/netbox.nix deleted file mode 100644 index 9c07233..0000000 --- a/config/hosts/netbox/netbox.nix +++ /dev/null @@ -1,30 +0,0 @@ -# Sources for this configuration: -# - https://docs.netbox.dev/en/stable/configuration/ -# - https://colmena.cli.rs/unstable/features/keys.html -# - https://colmena.cli.rs/unstable/reference/deployment.html -# - https://git.grzb.de/yuri/nix-infra/-/blob/33f2d9e324c2e3a8b1b41c20bce239001bcce9fc/hosts/netbox/secrets.nix - -{ config, pkgs, ... }: - -{ - services.netbox = { - enable = true; - package = pkgs.netbox; - secretKeyFile = "/secrets/netbox-secret-key.secret"; - settings = { - ALLOWED_HOSTS = [ "netbox.hamburg.ccc.de" ]; - SESSION_COOKIE_SECURE = true; - }; - }; - - deployment.keys."netbox-secret-key.secret" = { - keyCommand = [ "env" "pass" "noc/vm-secrets/z9/netbox/netbox_secret_key" ]; - - destDir = "/secrets"; - user = "netbox"; - group = "netbox"; - permissions = "0440"; - - uploadAt = "pre-activation"; - }; -} diff --git a/config/hosts/netbox/postgresql.nix b/config/hosts/netbox/postgresql.nix deleted file mode 100644 index 5f49f30..0000000 --- a/config/hosts/netbox/postgresql.nix +++ /dev/null @@ -1,7 +0,0 @@ -{ pkgs, config, ... }: - -{ - services.postgresql = { - package = pkgs.postgresql_15; - }; -} diff --git a/config/hosts/penpot/configuration.nix b/config/hosts/penpot/configuration.nix new file mode 100644 index 0000000..4608e1c --- /dev/null +++ b/config/hosts/penpot/configuration.nix @@ -0,0 +1,7 @@ +{ config, pkgs, ... }: + +{ + networking.hostName = "penpot"; + + system.stateVersion = "24.05"; +} diff --git a/config/hosts/netbox/default.nix b/config/hosts/penpot/default.nix similarity index 73% rename from config/hosts/netbox/default.nix rename to config/hosts/penpot/default.nix index d4a02cf..b6c8d81 100644 --- a/config/hosts/netbox/default.nix +++ b/config/hosts/penpot/default.nix @@ -3,9 +3,9 @@ { imports = [ ./configuration.nix - ./netbox.nix ./networking.nix ./nginx.nix - ./postgresql.nix + ./penpot.nix + ./sops.nix ]; } diff --git a/config/hosts/netbox/networking.nix b/config/hosts/penpot/networking.nix similarity index 50% rename from config/hosts/netbox/networking.nix rename to config/hosts/penpot/networking.nix index dbfe9a6..a96f70b 100644 --- a/config/hosts/netbox/networking.nix +++ b/config/hosts/penpot/networking.nix @@ -1,16 +1,10 @@ -# Networking configuration for the host. -# Sources for this configuration: -# - https://nixos.org/manual/nixos/stable/#sec-networking -# - https://nixos.wiki/wiki/Systemd-networkd -# - https://wiki.archlinux.org/title/Systemd-networkd - -{ config, pkgs, ... }: +{ ... }: { networking.interfaces.net0 = { ipv4.addresses = [ { - address = "172.31.17.149"; + address = "172.31.17.162"; prefixLength = 25; } ]; @@ -20,7 +14,7 @@ networking.search = [ "hamburg.ccc.de" ]; systemd.network.links."10-net0" = { - matchConfig.MACAddress = "62:ED:44:20:7C:C1"; + matchConfig.MACAddress = "BC:24:11:26:1C:8A"; linkConfig.Name = "net0"; }; } diff --git a/config/hosts/penpot/nginx.nix b/config/hosts/penpot/nginx.nix new file mode 100644 index 0000000..dc446f3 --- /dev/null +++ b/config/hosts/penpot/nginx.nix @@ -0,0 +1,63 @@ +{ config, pkgs, ... }: + +let + domain = "design.hamburg.ccc.de"; +in +{ + services.nginx = { + enable = true; + + virtualHosts = { + "acme-${domain}" = { + default = true; + enableACME = true; + serverName = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 31820; + } + ]; + }; + + "${domain}" = { + default = true; + forceSSL = true; + useACMEHost = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + locations."/" = { + proxyPass = "http://127.0.0.1:9001"; + }; + + locations."/ws/notifications" = { + proxyPass = "http://127.0.0.1:9001"; + proxyWebsockets = true; + }; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + }; + }; + + networking.firewall.allowedTCPPorts = [ 8443 31820 ]; + networking.firewall.allowedUDPPorts = [ 8443 ]; +} diff --git a/config/hosts/penpot/penpot.nix b/config/hosts/penpot/penpot.nix new file mode 100644 index 0000000..0629d1f --- /dev/null +++ b/config/hosts/penpot/penpot.nix @@ -0,0 +1,198 @@ +# Sources used for this configuration: +# - https://github.com/penpot/penpot/blob/2.1.0/docker/images/docker-compose.yaml +# - https://raw.githubusercontent.com/penpot/penpot/2.1.0/docker/images/docker-compose.yaml +# - https://help.penpot.app/technical-guide/configuration/ +# - https://medium.com/@social.iodols/managing-docker-containers-in-nixos-fbda0f666dd1 +# - https://madison-technologies.com/take-your-nixos-container-config-and-shove-it/ + +{ config, pkgs, ... }: + +let + # Flags for both frontend and backend. + # https://help.penpot.app/technical-guide/configuration/#common + # https://github.com/penpot/penpot/commit/ea7ad2aaa096f8d190d740f693f22f3ed1f05088 + commonPenpotFlags = "disable-registration enable-oidc-registration disable-login-with-password enable-login-with-oidc"; + penpotVersion = "2.1.3"; +in +{ + virtualisation.docker.enable = true; + virtualisation.oci-containers = { + backend = "docker"; + containers = { + "penpot-frontend" = { + autoStart = true; + image = "docker.io/penpotapp/frontend:${penpotVersion}"; + extraOptions = [ "--network=penpot" ]; + ports = [ "9001:80" ]; + volumes = [ "penpot_assets:/opt/data/assets" ]; + dependsOn = [ + "penpot-backend" + "penpot-exporter" + ]; + environment = { + # https://help.penpot.app/technical-guide/configuration/#frontend + # https://github.com/penpot/penpot/blob/develop/docker/images/docker-compose.yaml#L78 + + PENPOT_FLAGS = "${commonPenpotFlags} disable-onboarding"; + }; + }; + + "penpot-backend" = { + autoStart = true; + image = "docker.io/penpotapp/backend:${penpotVersion}"; + extraOptions = [ "--network=penpot" ]; + volumes = [ "penpot_assets:/opt/data/assets" ]; + dependsOn = [ + "penpot-postgres" + "penpot-redis" + ]; + environment = { + # https://help.penpot.app/technical-guide/configuration/#backend + # https://github.com/penpot/penpot/blob/develop/docker/images/docker-compose.yaml#L112 + + PENPOT_FLAGS = "${commonPenpotFlags} enable-smtp"; + + # PENPOT_SECRET_KEY st via environmentFile. + PENPOT_TELEMETRY_ENABLED = "false"; + + # OpenID Connect configuration. + # https://help.penpot.app/technical-guide/configuration/#openid-connect + PENPOT_OIDC_CLIENT_ID = "penpot"; + PENPOT_OIDC_BASE_URI = "https://id.hamburg.ccc.de/realms/ccchh/"; + # PENPOT_OIDC_CLIENT_SECRET set via environmentFile. + PENPOT_OIDC_ROLES = "user"; + PENPOT_OIDC_ROLES_ATTR = "roles"; + + # Database configuration. + # https://help.penpot.app/technical-guide/configuration/#database + PENPOT_DATABASE_USERNAME = "penpot"; + # PENPOT_DATABASE_PASSWORD set via environmentFile. + PENPOT_DATABASE_URI = "postgresql://penpot-postgres/penpot"; + + # Email configuration. + # https://help.penpot.app/technical-guide/configuration/#email-(smtp) + PENPOT_SMTP_HOST = "cow.hamburg.ccc.de"; + PENPOT_SMTP_PORT = "465"; + PENPOT_SMTP_USERNAME = "no-reply@design.hamburg.ccc.de"; + # PENPOT_SMTP_PASSWORD set via environmentFile. + PENPOT_SMTP_SSL = "true"; + PENPOT_SMTP_DEFAULT_REPLY_TO = "Penpot "; + PENPOT_SMTP_DEFAULT_FROM = "Penpot "; + + # Storage + # https://help.penpot.app/technical-guide/configuration/#storage + PENPOT_ASSETS_STORAGE_BACKEND = "assets-fs"; + PENPOT_STORAGE_ASSETS_FS_DIRECTORY = "/opt/data/assets"; + + # Redis + # https://help.penpot.app/technical-guide/configuration/#redis + PENPOT_REDIS_URI = "redis://penpot-redis/0"; + + PENPOT_PUBLIC_URI = "https://design.hamburg.ccc.de"; + }; + environmentFiles = [ "/run/secrets/penpot_backend_environment_file" ]; + }; + + "penpot-exporter" = { + autoStart = true; + image = "docker.io/penpotapp/exporter:${penpotVersion}"; + extraOptions = [ "--network=penpot" ]; + environment = { + # https://help.penpot.app/technical-guide/configuration/#exporter + # https://github.com/penpot/penpot/blob/develop/docker/images/docker-compose.yaml#L221 + PENPOT_PUBLIC_URI = "http://penpot-frontend"; + PENPOT_REDIS_URI = "redis://penpot-redis/0"; + }; + }; + + "penpot-postgres" = { + autoStart = true; + image = "docker.io/library/postgres:15"; + extraOptions = [ "--stop-signal=SIGINT" "--network=penpot" ]; + volumes = [ "penpot_postgres_v15:/var/lib/postgresql/data" ]; + environment = { + # https://github.com/penpot/penpot/blob/develop/docker/images/docker-compose.yaml#L240 + + POSTGRES_INITDB_ARGS = "--data-checksums"; + POSTGRES_DB = "penpot"; + POSTGRES_USER = "penpot"; + # POSTGRES_PASSWORD set via environmentFile. + }; + environmentFiles = [ "/run/secrets/penpot_postgres_environment_file" ]; + }; + + "penpot-redis" = { + autoStart = true; + image = "docker.io/library/redis:7"; + extraOptions = [ "--network=penpot" ]; + }; + }; + }; + + # Docker networks. + systemd.services."docker-network-penpot" = { + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStop = "${pkgs.docker}/bin/docker network rm -f penpot"; + }; + script = "${pkgs.docker}/bin/docker network inspect penpot || ${pkgs.docker}/bin/docker network create penpot"; + requiredBy = [ + "docker-penpot-frontend.service" + "docker-penpot-backend.service" + "docker-penpot-exporter.service" + "docker-penpot-postgres.service" + "docker-penpot-redis.service" + ]; + before = [ + "docker-penpot-frontend.service" + "docker-penpot-backend.service" + "docker-penpot-exporter.service" + "docker-penpot-postgres.service" + "docker-penpot-redis.service" + ]; + }; + + # Pull docker images prior to starting container services, so that a container + # service isn't considered up, if it actually is still just pulling the + # relevant image. + systemd.services."docker-images-penpot" = { + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + ${pkgs.docker}/bin/docker pull ${config.virtualisation.oci-containers.containers."penpot-frontend".image} + ${pkgs.docker}/bin/docker pull ${config.virtualisation.oci-containers.containers."penpot-backend".image} + ${pkgs.docker}/bin/docker pull ${config.virtualisation.oci-containers.containers."penpot-exporter".image} + ${pkgs.docker}/bin/docker pull ${config.virtualisation.oci-containers.containers."penpot-postgres".image} + ${pkgs.docker}/bin/docker pull ${config.virtualisation.oci-containers.containers."penpot-redis".image} + ''; + requiredBy = [ + "docker-penpot-frontend.service" + "docker-penpot-backend.service" + "docker-penpot-exporter.service" + "docker-penpot-postgres.service" + "docker-penpot-redis.service" + ]; + before = [ + "docker-penpot-frontend.service" + "docker-penpot-backend.service" + "docker-penpot-exporter.service" + "docker-penpot-postgres.service" + "docker-penpot-redis.service" + ]; + }; + + sops.secrets."penpot_backend_environment_file" = { + mode = "0440"; + owner = "root"; + group = "root"; + }; + + sops.secrets."penpot_postgres_environment_file" = { + mode = "0440"; + owner = "root"; + group = "root"; + }; +} diff --git a/config/hosts/penpot/secrets.yaml b/config/hosts/penpot/secrets.yaml new file mode 100644 index 0000000..e3d6894 --- /dev/null +++ b/config/hosts/penpot/secrets.yaml @@ -0,0 +1,149 @@ +penpot_backend_environment_file: ENC[AES256_GCM,data:+MJbbAjzslBIYlQ9xe0VzM8ON2U5dktJGGHmoUu0HW0mvU4pRYrQXlWdW85RXAyYU9yOiL6TNAHOWUQyqOdo23whuer2jL/Qe17DEhapE4b9W9JqBX7H0VZZKHS70AgGZdWmbj/bWAROg/qGPVKjZLhgKxoVTVbvAIJEXUDAbGfvHlY3BP67yUTXvbmtd/Rdhn6i1HafY7YHFNAW8SkikglW6wR5igEZMFAefMOMgq7aYmNXOr1bImjCPEko0DvumJZM4YMjmb3Wc97wL7OMP9G/V0k9fRclhOj9+lNpeeCKL+VL3Bgo8vqgrB+WIi4a0EwerT8srx351txrU+ITxoHciRQtOpeXVHWL1snW9o7xCoOcil0NS93D9GhW+Hd75Is/xHN08UHmahF1r71nbDK4CmSiUzZzFLl1oWkSTU/31zBUnllHOt5nDMKT42xiniAJcQ==,iv:vtIlNGIh9+e9W+OebTac+UUQp9glBIolC6KQwQMzDn4=,tag:kBBTu7LVp+3xJ/MstLyomw==,type:str] +penpot_postgres_environment_file: ENC[AES256_GCM,data:VT36kHkRH8ghnU1oyPpAQZW2LR8GNmG1cQXVjU4f+rGy9hViTivd7qxzMusisy7IcWfVaQuXFvUCT+pCMD/fhSAQZOY/1Rs8LBXJtsuPButOG9Q=,iv:pUjAkvvHjsnzn0xRRmdZXatOgLm9dx8Ggt7lEfiQllQ=,tag:FZRqlcxQWu/FgnJfoukIcA==,type:str] +sops: + age: + - recipient: age19h7xtfmt3py3ydgl8d8fgh8uakxqxjr74flrxev3pgmvvx94kvtq5d932d + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBicGt5U2pkOVoyeEVrWUxP + RG42SVYxMmhjM1lvaXp2a2Zwd3FNL3l2bUZjClpibFhCT1JtNWp6akpIQ1V6YW5L + SzBHd1lPais3eDQ4OEtiYi8yeGVZK1EKLS0tIE5TeTB1MjFmVVh1TUYwZ05YZWor + aUNxU0xKVTNScEl3YXEvZmlVcHh5cjgKTwC4QsYGq/6Z90oxfYakHM0Uiym1KaTP + UcigMqnMlz3z94/cIHZKF+jFFRITq44SiOg8/yAMmR+MPtbTZ5ZnSA== + -----END AGE ENCRYPTED FILE----- + - recipient: age10ku5rphtsf2lcxg78za7f2dad5cx5x9urgkce0d7tyqwq2enva9sqf7g8r + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1bVFvQ0xKMzdKY0MrekRp + NDJ1TGpFb0RJQWJZSys1ZUE1N2JYUDhRUzNJCmw4N3FKRVZ2M3FtdFlBZGZscVBj + NGdWUDlPZHI5ZFErY000VlFsVUtLYjQKLS0tIGo4YmZWRHF5RVpuZzBKQXhrdDN2 + UllmcTIrNXJjcnNSS29BMWlSNkhOL2cKaPzeAO5y8SiU/Oupf3hVbhm5qlz08Z16 + vaGXmMv/NjhSM2Xevk8BYuU9CH9rIVqNDiQXBKeIVD6VhdtoJV2pgA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-08-10T15:40:27Z" + mac: ENC[AES256_GCM,data:hxVxH/BBwYcvbtOH4aOUnI9NnbCfAGnnwE3VQBJBJliOWo9WHm/hx4Eol4vaS+AA2t6AUU7UmzjofX2wSTbqQliDCFCSgbpMofDXP7tmlat+M9Du91fQmfOibzCd84tkqS+TRTFCFX83LmQ7/Bb2mHl77uGVAFYyHX9+IPPEUMw=,iv:w2Rdl2+o7bZRQsOogU6U5DK1UuHn+bL4Ouh3XbByYHA=,tag:6sqJal6+kzk0stP6vK6oOw==,type:str] + pgp: + - created_at: "2026-02-17T22:22:01Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAz5uSgHG2iMJARAAynwvOJFE4hlU6Cr/HwoXK5TqrsdZbJjsK0dBhMJjZCXo + mQiGbeCmq6ut9LpSL399eXSuZ7MGzk39JBQ54PXUeB/3K02E43tIAzPIrJGXVW9n + Z9QvdAk5B772WgjjTMN82GeQ7xGTp/KJ8MjNvob4umpqYVvkX7CN8glvldHoeqbH + oBwviYU2YEnNgqWYCby0OvwT2Ouky8QEXiKwlI0fUfGd3EHtnLCwegouAUUBKCqb + 2SMPLpSFeJuZiGxTsS889CJWMQxXdfqVDS3aedt7SJP8TyqdDlIIJ+fJ5Vt429vN + Af/drBfpViLVHXHh3MQNF5kQXgLt+LSecuj9ubZHXLNm34nw0ldtjf1nqAcsMDRY + gM3FQSuBZUU3vpbisFHzF63tiotwdjQf2BR5r9McnSKyHNHvd0m6DN9l9W5xNlKC + Sdf+cuQOdtsYFxeGrkl7j3uvxsjEyfPJ7lokfRm3vC43GY6MoBBjVqUIe1i4ynUj + nLwtps6AkiTyhkDUXomCqKNiZNAGwW0VI2lMgnva/atWNI15VuD3gOU8TrAfBRcU + vpD82HhBGvyYgcqvn8WWwkd508OQsAHlQlZbp+ZFjbPgzqriSBCv1Z6C74Yhw1Gg + vmfcCCRw70Vmz0zXC4iWJxxFH4SUla7YVOCdwrKhF/6thJSfgQ85bsFkSzUcvV7S + XgHhXgm71Ah6fFzrkOTo58+8RJBwXYGhcOvotq0owzuski4RtdLKWTtC4cT0oMlR + hbziNLYPYo7aogsZ+FxYlkQ4YTleKJUkrUuwBPYqYKZsbCG0un0R5yQrf4/hlfo= + =ekfn + -----END PGP MESSAGE----- + fp: 18DFCE01456DAB52EA38A6584EDC64F35FA1D6A5 + - created_at: "2026-02-17T22:22:01Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAw5vwmoEJHQ1AQ//Rl2w61XcbW6YhwDThbwbcpaKzZegAzKnKa2Q25U2UfNP + jhqwqay/PUbJyt/G/9ukVNZ1ujTu4ffbzlV6wD4TJ6baLn1NL1Xkjz8rqoIlXy9/ + ZqpyEZxyQAsaP0hBgE3x4UZdD6jh/NRUUlrnPRFVqXxHSCL5XHmHdjCaY58OgB6H + /5LFGjYdxFomGEozR5fpgBuA50B4ylh1Crw+xiT6VPB50/mWRw7GSO4f6iwB/2eR + VeGrK7nqHf6dFS/mTDUxw2jrSoyjDMTgAPHwl1qJ+Pug8fmp0cIdLf3ZGBlulsL2 + 9DHCvXNeNGmk72Ag6DWh1vxLBOGYAzar4hXSxu216ppJh9ym+3SZRmEYhP33VBRp + JbufVtrRwK3wU3+o88DXZ0Z58Pt+IlH652qxHqJlC7H2F/gX7B5zjH+Uz+1IeEK8 + YudPIH3Vo+saCSpKg0RLqHiNXE9ia/wvnWNzw4U5GGikle8LNnzy2TMnwq8I92GP + RUVzWH3vFOWMSt+ilrA4nhjeVlzMBMGBvmQiJypAUAj+fm/xEJTkasa0a+GVpZtH + zHMwTFV/A/7rtXFrtcjTjDLBdlVMqSNM3FYHnKKlZLYUQbqhQNaINdxjrx2C/19w + +WLI08wqrPMZSa5iA1q60LLC3WkiTka1K5N+8fT6HxH/OuuiBJJyxMWsoIcSpYTS + XgG3jf+BR/9y8kDxqiGCwwU7fzRGXGvCH5i7CJzwrWtc3FmTNb7ct3k+tMbEcrNc + frd6gvm0u8+I5CFmHsdZFrDy55afTOoT4DErO7vmUGRKh4JfgKxsn8lzzfLcYjc= + =hjjX + -----END PGP MESSAGE----- + fp: 87AB00D45D37C9E9167B5A5A333448678B60E505 + - created_at: "2026-02-17T22:22:01Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DerEtaFuTeewSAQdAhOSneDEqtquUzQxEuKsOmmBWObvr4JDzmoijutbNFS8w + dixZ92+6rfNthVHhzDQghzyU8dYNqQiwfcrXNWpJ4fJRE1g8nTuQApvxTF4lC4Vm + 0l4B/YhYp2JGWdw1dllA9cD/HMAzKJ4zHSL7dCcfP6k0b6CUYm1GuO/VT6Bx7ygC + gfLuQKGFRPomTHNan4S1rhW0q2zvQNGIFMTDo3eR6Uyb2UVDTIdbaICsuaEKssEc + =JN/I + -----END PGP MESSAGE----- + fp: 057870A2C72CD82566A3EC983695F4FCBCAE4912 + - created_at: "2026-02-17T22:22:01Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAxjNhCKPP69fAQ/9GhlagbbuK9o7QroUgY9gcimdxp1PTK4HOsjRgnf56PNm + vTpP3We62o3+ohIX7yGKbpNKbnf3n5Ecx3ItJbBRniUDr3G2AnnxpynJJWmZGsn3 + HOsgQqqYtUeSgf6KIhaeebP9drM2p2qPYmGfa+9DBb+Li6FESOlzOmZeiUoaZUlF + lHys0cTsBE2iYepR34NYwv7qrkt8tkCz1nrKraAmhiNWFoUFWVN617p2NQICpsFD + Wk5m9gJtWlgQHvSHvqEgu6PBArOFclBcY+bb/XC0srWlAVixwr60iDy1IRRuKz6r + 9OukM9Ng1V0bZhkGyjB4ti+RmQKiP9SPAupxmCe5n+ZkweJ7gb/nE9lodNJv8IkK + 3o9h653H1hCbWKeKlaAggCfopAyEn1mU+7l37AWUGh3sh5jz7aFrdXYcAIuum88/ + Zpa0ALYIABoevjJwV6NyFtAsQpt7YQ3/0wJe/BC/6XQ7QI44DlUYraIaA+CLT9gp + C4h2olOPtCXHfNRM4VK4pOJ0gwQVTI40snlCNzq9TfZPjC63MxzinRLs8PUVvM3r + CXYTwxkOI3IFdvoTIefdVjoOxvGR0tUyYTagtJ0nihh4ymKlxPS2F2FNAm/oDQvm + kx1AjAci8YuYZbS+DSFpi5djN2nxoQRfiFhm08ruBRnX0SI1EYLMShO/AO5fJrTS + XgF86MBuDd9XX2E1OLWamMpgobsAHLgUd/kny8Nz1+VFRmME+FKicrOOvm3RVPWW + D5NGxvlHPMfeE/xqPv4Oog1qkvUdDQoNSc1D6h8uh07XW77mJr0kwnmhk/zDsmA= + =Tlzo + -----END PGP MESSAGE----- + fp: F38C9D4228FC6F674E322D9C3326D914EB9B8F55 + - created_at: "2026-02-17T22:22:01Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA1Hthzn+T1OoARAAlUaspaXyF0VUY+9YYAZNTO9FcqybRLNMCNfYqxjOc9EY + CtHqfMOaA2fYO3Jz5cY3u85ilKovHNpUTQN2AL5B/DnMthQy8ooGrvabeZ4qYeuq + EgKDgzsFw5BS2eS1t6A5cl7OS/tSMnN83Mmy5zYT0eBApkW0uwucv5paNvi4v0XS + nxkfpjLx6Bh4lZ1S4elhkkoC3NQp9oi/xQD3xQue6i0hAw1fKjHXHcluN7gBYfQ3 + dgCuPC9NGdNJ3O6k8zn5b01wyLKISt0noYy6XQfZkac/7YKJmfYjaDjwr3G5GPJN + 5qDvb/NER/wcPMPiH2avFFPxy8MetG44OS7F2sqUumwxPAKCgrLuGvX5zNf2FdSO + hYPaOveWxGfoAP4IkoGlnp7+DdcWplWE/zyA8vk49JH/cac74+tUkI0AOflJVU2y + EGJ2egD2ThL64+V3Ezml5QQnVFwgWWM46w1X6fhx1wWD+o9mZovj2RF2WkGa2dp6 + vP5PXDvTioFt40v5sYjN/19sfeuT+QVExdRZ8yBLgPj430CtF2TvCNNP56h1GB4+ + oId9LNlhjSLl23dcA80C3OKLJhFMFC3EhJDXqyrUFXf4rUF/rN/Bd/ig0oq/d2+7 + LE7xJE0TYQw83ReW4Amcy4rkLOub64JiNEpEBqZk246MkZoH2IT6gh8sKJ/DHdPS + XgGcprhx/8L/jM4qS0nGaFvkMnOWqZfv0By/CHCl1KPx9p+6m+a5oyA6NUUbYZsZ + 6BF0Yk2CEdlM8WjUilQWIYBJtpXqGRu+z4KkaosyNmAem0gImPxQQA2bBdVTQwQ= + =PMud + -----END PGP MESSAGE----- + fp: 5DA93D5C9D7320E1BD3522C79C78172B3551C9FD + - created_at: "2026-02-17T22:22:01Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA46L6MuPqfJqAQ/+NWPka8B/F/sZkJ2cVtVLywIPhHNIroBiyA5n/8TOjWjF + Q9zII52FLTjOrNozJb6Vf09iNTBqPGnde5vW/98aa4v6XaGL/rpHG0TS7uR7Y26Q + DQbYlxZIMwdlhkrb6OHgTeocl1q/XDruLqUaEpqxDjRrtwvFqtEPIMkIvJQp5g9U + qBUqL0gZz71hx7M4V/cxCitMY2bmINueF5TIF44THHGu8QbZaoAt7vXzkxvn9/Jj + jkQYCw128bBWWOTgZ8Nen+s5QuV0jRsczZGkwg7KNSkYi+XszxgcamXIPkKeGhcA + kTyKDNotOeKyui5Mh/MVGSQDi/njWua8ZiPUarORef53ndRY5hkd2dQVjZm1kZvY + Hfi7Nxd8Uxl7ru2m4W8+MXGPRCnm7jFFaVtcwKdGyIASyTtJBHG/wbXDVfsfQVSc + /YLuS10B37gd3innwndPTockCHsuOMHIbNeM8RD41OJSV3opEQlf+DCxTQTxQMZg + n+J61eflGMfkMHSU8yj/7b9NX2IFka2w3GO/hicZ2l2GrM7fNUqT+ynaO1lC1xNX + ALReI0DQUdRd2VHn3cBoduT2j/DM6RaVH89nf7Euj+mzHGSR0DFNxHFXyoHAJJmF + 8J08ATp68JkbahHs7swa9Kh3Z4//LILHYcdDiiJNP5NJRG65OlIcTro08NzPg5HS + XgHKbiW3ZXCowpDempWr7UawruY3O1SSvgC3YsHlslrm6RD0uINCKxJL7YjBjIqD + u4M70/rHNiGJefJ2xACNQgdTzPl6s1LpG3c8ANEBLVE4irqFTE6mgfErOMb2Qzo= + =JZf1 + -----END PGP MESSAGE----- + fp: 8996B62CBD159DCADD3B6DC08BB33A8ABCF7BC4A + - created_at: "2026-02-17T22:22:01Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DQrf1tCqiJxoSAQdApX/THvWws8d2Tijx5RrGIh+CYcqDI0T30rttyxT8Mw0w + /7TkFc4D2eSqXQW57YWEACwd47NGyMlW96JEeMDCqwNdGQQLaSseoYrS1hxI9oVB + 0l4B0/igsdF1GICTtToMkS8aWwVHXQLu2AO0wNyKjXAyLtsDposdx+UtLM0y0v6X + HfXqQmyHEK0QNr17oqyTKiHQ6rnuX00W42vwxDCGs9RuLvI2qCWeNzC6C6j62vkI + =8osW + -----END PGP MESSAGE----- + fp: B71138A6A8964A3C3B8899857B4F70C356765BAB + unencrypted_suffix: _unencrypted + version: 3.8.1 diff --git a/config/hosts/penpot/sops.nix b/config/hosts/penpot/sops.nix new file mode 100644 index 0000000..b4548ed --- /dev/null +++ b/config/hosts/penpot/sops.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + sops = { + defaultSopsFile = ./secrets.yaml; + }; +} diff --git a/config/hosts/ptouch-print-server/configuration.nix b/config/hosts/ptouch-print-server/configuration.nix index 1bb1448..33f9681 100644 --- a/config/hosts/ptouch-print-server/configuration.nix +++ b/config/hosts/ptouch-print-server/configuration.nix @@ -1,7 +1,10 @@ { ... }: { - networking.hostName = "ptouch-print-server"; + networking = { + hostName = "ptouch-print-server"; + domain = "z9.ccchh.net"; + }; system.stateVersion = "23.11"; } diff --git a/config/hosts/ptouch-print-server/networking.nix b/config/hosts/ptouch-print-server/networking.nix index 7c7cb62..83031a1 100644 --- a/config/hosts/ptouch-print-server/networking.nix +++ b/config/hosts/ptouch-print-server/networking.nix @@ -11,9 +11,7 @@ ]; }; defaultGateway = "10.31.208.1"; - nameservers = [ - "10.31.208.1" - ]; + nameservers = [ "10.31.208.1" ]; }; systemd.network.links."10-net0" = { diff --git a/config/hosts/ptouch-print-server/printing.nix b/config/hosts/ptouch-print-server/printing.nix index 5964f56..23cacca 100644 --- a/config/hosts/ptouch-print-server/printing.nix +++ b/config/hosts/ptouch-print-server/printing.nix @@ -90,9 +90,7 @@ in # pam_deny.so # deny (order 12400)" for pam.d/sshd, so enable # PasswordAuthentication to have it not do that. services.openssh.settings.PasswordAuthentication = lib.mkForce true; - # The following doesn't need to be set in order for empty passwords to work - # apparently: - # security.pam.services.sshd.allowNullPassword = true; + security.pam.services.sshd.allowNullPassword = true; services.openssh.extraConfig = '' Match User print PubkeyAuthentication no diff --git a/config/hosts/public-reverse-proxy/configuration.nix b/config/hosts/public-reverse-proxy/configuration.nix deleted file mode 100644 index 31aa8e8..0000000 --- a/config/hosts/public-reverse-proxy/configuration.nix +++ /dev/null @@ -1,7 +0,0 @@ -{ config, pkgs, ... }: - -{ - networking.hostName = "public-reverse-proxy"; - - system.stateVersion = "23.05"; -} diff --git a/config/hosts/public-reverse-proxy/nginx.nix b/config/hosts/public-reverse-proxy/nginx.nix deleted file mode 100644 index ff14adb..0000000 --- a/config/hosts/public-reverse-proxy/nginx.nix +++ /dev/null @@ -1,67 +0,0 @@ -# Sources for this configuration: -# - https://nixos.wiki/wiki/Nginx -# - https://nixos.org/manual/nixos/stable/#sec-firewall -# - https://git.grzb.de/yuri/nix-infra/-/tree/3896d34f4f7f3b5dd5cbd270a14b56b102ef3a2a/hosts/web-public-2 - -{ config, pkgs, ... }: - -{ - services.nginx.streamConfig = '' - map $ssl_preread_server_name $address { - status.ccchh.net 10.31.206.15:8443; - } - - # Listen on port 443 as a reverse proxy and use PROXY Protocol for the - # upstreams. - server { - listen 0.0.0.0:443; - proxy_pass $address; - ssl_preread on; - proxy_protocol on; - } - ''; - - services.nginx.appendHttpConfig = '' - map $host $upstream_acme_challenge_host { - club-assistant.ccchh.net 10.31.208.10; - netbox.ccchh.net 10.31.208.29:31820; - light.ccchh.net 10.31.208.23; - light-werkstatt.ccchh.net 10.31.208.23; - thinkcccore0.ccchh.net 10.31.242.3; - thinkcccore1.ccchh.net 10.31.242.4; - thinkcccore2.ccchh.net 10.31.242.5; - thinkcccore3.ccchh.net 10.31.242.6; - zigbee2mqtt.ccchh.net 10.31.208.25:31820; - esphome.ccchh.net 10.31.208.24:31820; - proxmox-backup-server.ccchh.net 10.31.208.28; - status.ccchh.net 10.31.206.15:31820; - default ""; - } - ''; - - services.nginx = { - enable = true; - - virtualHosts."well-known_acme-challenge" = { - default = true; - - listen = [{ - addr = "0.0.0.0"; - port = 80; - }]; - - locations."/.well-known/acme-challenge/" = { - proxyPass = "http://$upstream_acme_challenge_host"; - }; - - # Better safe than sorry. - # Don't do a permanent redirect to avoid acme challenge pain. - locations."/" = { - return = "307 https://$host$request_uri"; - }; - }; - }; - - networking.firewall.allowedTCPPorts = [ 80 443 ]; - networking.firewall.allowedUDPPorts = [ 443 ]; -} diff --git a/config/hosts/public-web-static/default.nix b/config/hosts/public-web-static/default.nix index 60487fe..9ef00e4 100644 --- a/config/hosts/public-web-static/default.nix +++ b/config/hosts/public-web-static/default.nix @@ -6,6 +6,7 @@ ./networking.nix ./nginx.nix ./virtualHosts + ./sops.nix ./spaceapid.nix ]; } diff --git a/config/hosts/public-web-static/networking.nix b/config/hosts/public-web-static/networking.nix index 34b36f3..cb22d40 100644 --- a/config/hosts/public-web-static/networking.nix +++ b/config/hosts/public-web-static/networking.nix @@ -1,17 +1,19 @@ { ... }: { - networking.interfaces.net0 = { - ipv4.addresses = [ - { - address = "172.31.17.151"; - prefixLength = 25; - } - ]; + networking = { + interfaces.net0 = { + ipv4.addresses = [ + { + address = "172.31.17.151"; + prefixLength = 25; + } + ]; + }; + defaultGateway = "172.31.17.129"; + nameservers = [ "212.12.50.158" "192.76.134.90" ]; + search = [ "hamburg.ccc.de" ]; }; - networking.defaultGateway = "172.31.17.129"; - networking.nameservers = [ "212.12.50.158" "192.76.134.90" ]; - networking.search = [ "hamburg.ccc.de" ]; systemd.network.links."10-net0" = { matchConfig.MACAddress = "86:72:08:F6:C0:D6"; diff --git a/config/hosts/public-web-static/nginx.nix b/config/hosts/public-web-static/nginx.nix index 9d0e173..898df39 100644 --- a/config/hosts/public-web-static/nginx.nix +++ b/config/hosts/public-web-static/nginx.nix @@ -1,7 +1,17 @@ { ... }: { - services.nginx.enable = true; + services.nginx = { + enable = true; + appendHttpConfig = '' + access_log off; + + # load the DID redirect map from the webroot + map $request_uri $did_redirect_target { + include /var/www/diday.org/nginx-redirects.conf; + } + ''; + }; networking.firewall.allowedTCPPorts = [ 8443 31820 ]; networking.firewall.allowedUDPPorts = [ 8443 ]; diff --git a/config/hosts/public-web-static/secrets.yaml b/config/hosts/public-web-static/secrets.yaml new file mode 100644 index 0000000..e1f1a5b --- /dev/null +++ b/config/hosts/public-web-static/secrets.yaml @@ -0,0 +1,150 @@ +spaceapid_config_ccchh_credentials: ENC[AES256_GCM,data:5IClrKKMO/AztQuGabrnoRFItYNeEmVWGeafomVO94pL1RKzL1sCxBxnmzvJFPb/8Y+6FXMh+Mim4DP8B2RaJMLpmqCv+76N/5+527SZ6gn9i2Klg6q0kD9RzJv40qHq/NYLCa24tpcZDt7eB0EOgqLsKUmtX2LrQjjnN3NzjAevJGKQ5ypnb7xygjft2KrpvlR1hMnZ0XpSLDTNR1AmImxE24JtDaJKzwXbptr2IZvm1UFkNslxdqHPjN+N8+MSSLhqHy/FdcY2ADvsTX1jtjnjkb+9E30QOeCiFPKSmWtSGiQ9sPcQna1yr717Vk0EiNSAWDQ2fMZyJUgBXG6w3wiZbxfJmxvshLPs5KguF9NHER+Seps1QiE0p16c0IS/0Y24UYrK2GyUIcSReGufjxUFGTJHFSsNANac34H/RTs7BkoZ,iv:8WzTRaXVeH5GKmigMVTLVBnhy6nXZnTZHLAYHcqDs2s=,tag:jTdgz0gmruMWWDBQ3h70vw==,type:str] +staging.diday.org: + lego.env: ENC[AES256_GCM,data:FHCHBrjapNGSAtUnDTMZfeAZJqZV65d8COBJF8lzZmNBiw0jXyrmJ6rnUbYmnPN54T+1e8V0dzkdqmYX708tpFWagOPPQ9Ko+D+lV5yJ4hj/lhunuPSetWC/5dGBfN6CbA==,iv:WZ8CWu40ToF2mbpSUR6pDdUa6jcWPIUsWhVaGGBwx1E=,tag:8CohD3CwcUm2LzAJ8Lfimg==,type:str] +sops: + age: + - recipient: age19h7xtfmt3py3ydgl8d8fgh8uakxqxjr74flrxev3pgmvvx94kvtq5d932d + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOaEZqOHRMMko4S1loUXdm + aTlsS1RDNHdjdkZWSG1aR0d4Vmh4dVVZQWo0CmJUbm9hZzJqaDBOMTVObG9HWFF1 + RDlCcmdvR1RGbzBKQytZK1lSem82SWcKLS0tIEZUdFpldVJpT2RlVThjREVqcUV6 + OUJkei9zWmhyazc5T2FVbElFRG9RaFkKu4lZrg8UWVVk75eY8HBdLIT4BNw2UcyV + +7X2L7ltv2z31T4cKnnZrsyeG6fBGCLvuI5EQBd09OCZEUZ4u7qPOA== + -----END AGE ENCRYPTED FILE----- + - recipient: age19s7r8sf7j6zk24x9vumawgxpd2q8epyv7p9qsjntw7v9s3v045mqhmsfp0 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzMkdGQ0tpSUlWQ25ERTMy + QXhNdUYzdlBPUXR0V0NyOHpZbDY5RVd1ZXg0Cm40TjQvMXVGamM1akMzRUFuc3NO + K3lJYnpVQ1I3QjlRZUJkUm9QK0NuRFEKLS0tIFNuY2NXU002bnlvVHZKRCtoc1NS + ZE9rN3R4aHRXR0dBc2oxcEYrL1lxZncKuVocF84+ge1gyzfNjIxhwNgd8+kJIpxh + yREbS2mrQ2zvSMtw9OoA0KJSpoHZfIiCwn2uYkQDPiGB/721JmA12Q== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-02-27T20:40:06Z" + mac: ENC[AES256_GCM,data:Nsburro0nSV8CLZsxLaFrwsE5EIz8qQOlclNynbRT03XkfaPN2Pup8UWg9QL34KGcGUweqtytxZvLWjwfJYEsIkLqi4ZfrpXpEfBowq5aNbWHzDJDW5QqZKaUPmMQxiPVm1EhXmyvfVdFEueOhfFLbuNUSvNWaFk/7l2utTeLrs=,iv:dSJDVYGdaunvRqj+EkPGy3qxR9suV0s2Mm26silX24M=,tag:hqA+4FpP2PwatRMnZUcUqw==,type:str] + pgp: + - created_at: "2026-02-17T22:22:02Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAz5uSgHG2iMJAQ//QUk96h2C0nYHnswgF7hInFG+w+HC0v6sCTzwacAOCwMG + a4otLktg51S/iBqP0VYNCQSfBc0iX2YhHrrROHTRGrxMecVWi8hw3q6MMkBjw49x + wHpSdao/2fSzwB7j6llJNAkpR1RTZkmOimyaWAkH8Er+MNF6xClPuxN3IrPvU/C8 + Ru1uZCXvG0jh48NzvXk7rK/KRhPWlcYkgPWAEWQdeNMyxW9Ha0lQhSOhC/lNOLMJ + Q2pZ0zQxeQqNApe4nSs7AE9OGd1U/DNXAAriEtmXRHstPodHLqSjSfO749KLZuQA + ruSMz3tf+FFJspyY7DSleIiiJvu5A5SnU4aaFcrqfhDKNAsFfziG6ze2aq0YHf38 + 1KxvKvtQP+qT+8pKMFPe7Wz4oFEcHBjxFLyJZ7DwRDkzdMvdAQLLL/kcP4fKxFPx + tNDfJX45CM91soY9N6zHYk3MZ8WXCdcGjP+/XFit3GGeJCV3qNjy1mTalPZbVUE1 + uqNgqwG7IZaPup+3TEtIuGb3r0YNy4kWlJcaQ2bz5pPtDpbzcf9Fr+jxTod2LIky + X25qzKmAwus6aWheEyPQ5AHZVT5l2Sgdf/uBBJjh7yt/Y1OY/EtbS05fE6VVdiUq + oFq3DQ8L+MGyUTfQqIxpremwdq7pNp+XxdF8v1O6H5t0ByqcQt0UjsDWpv0T+k3S + XgEMQqbP81OTPCSwL2ePrbj92C97zkScyAyur1lrducU0UPGulQ9k51gIm/1nV4C + 04NrhKIlCqNHqx3DY8oHk/rnFrV/Ulrxqq5Hc1FRZCEJIbyV4e+uQQggWSxuqVM= + =uorx + -----END PGP MESSAGE----- + fp: 18DFCE01456DAB52EA38A6584EDC64F35FA1D6A5 + - created_at: "2026-02-17T22:22:02Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAw5vwmoEJHQ1ARAApCd7a+rHgICU4yfYOorWORysVsifvZpAGVTJJGWfeRdR + CQiqubBzEMN2Y9q2WnjYqmk5j909VCxSXO8zWpFjJZwLtA9eaAMftja2/1pLtGQd + AUPUIuTWxKjrP/aoL8tC+I7W2TVsU6Q2GSYqm6OZ0WLDP5kR8YQRSOKzVSDsDkOt + jphtni6zQpE8XLlJRhyPiLX+96Y5geDYj8KD19DBl6vSMFudMhI2WK5imak5PERk + y07w3lJ0/FXGLAdR/I2l8aaynkQ53Ft4IEXNoDtf89nO/8L13AImOZtpoIv1nfVr + QMS1jKys9bfo5lIcJ9bIJQ7hMQwV8AZQziBDDZQjDclZxcxC353zx8sjWjUWzUeY + 229b0bn6yutQ6hu9eIU0gxepyvNz9lAN6EHKb2cgp/UJb4IXnn3/ktmPq/wOlVIz + 5xOH0ue/BaIWmp1xjC3oKLbJeTw8zvRyzk8jGFDhmhDRUwMoLiPvR9XkQ7cpGGYy + wkb/URVBXLGT2u7wWVPZL0zUJ7zO1wCZ27lBwLgSAvVNSE87Ldsj3roxtr9nOQif + /qmCxHkDbhfhWMFl3PbCYY3hkS/ANQPhGyiBaU26x8o/0Vgajq43OLU0KO1+Wxbr + xvfKVN4m58iPHsMXbgvyEipFu+eoiNvEA68+pCRXrS0om2oE913XNEalVJ6F5f/S + XgGxibFQj6MyvJChwsuFx9YmdH8/nnb0eb9hmZuXctFNZCdlVrv3fhEwBoA6FnrA + RoCdOB5Djl0jHSk66Jto1uwfDYdcPZR+1tgRT9xVeK4PtM+c0Q1Y8dv3wjAnqr8= + =lzNQ + -----END PGP MESSAGE----- + fp: 87AB00D45D37C9E9167B5A5A333448678B60E505 + - created_at: "2026-02-17T22:22:02Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DerEtaFuTeewSAQdAMGn63OSW8nVLoTMXbLnQdYJuP0cD0exmbpSakMw9PlAw + MTJF0o46wKf+3F84IOf35LwWwMuMGEyz3pvcRXVa1OfPAFk53PMo1P9TyWRoHrgW + 0l4BNK3KuE4zB7YNpu8sYtJ4a94qKzTOgUTPdBNOQyZR60BOVyGFDRLo3hHk0opV + eP1e3BxevL3rj1b2WoCewT8lNO+y8+x8bu8JY0WMBVrwjSqYlWENbtuG4eFhNGrN + =3yKD + -----END PGP MESSAGE----- + fp: 057870A2C72CD82566A3EC983695F4FCBCAE4912 + - created_at: "2026-02-17T22:22:02Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAxjNhCKPP69fARAAhwsKIIhLW9DXZlOfg7a+6crdjzTv3EH+8dCcSk5JiRGG + QnFQX+14DCLTX9kmEilDXWwawKbIdabqkF/+LbGyRjd7IrcNe5a+ggzkry9cDPb0 + VKts7T3Ti3BFcgNis8ku/W9l17Fm4ngdHA1F47ttByjDcfuAZURtnf1Ta2Lx8XwV + w3Cc09xtsKo98Bfrhel4iI0WZjj9+U3pHE4WeKm7bieLEpwtoxfdmPkGLGaGP8I4 + 4lIKJG78DTbrbsEP8FpWTTy6gp9N3Q7ZAjpZnuolZp7uZp1I4t+Z2SuHPrsLNwS+ + fxjOJnigl8hwPHGm030xq2/tcsxyfNGD13Z8ZG85KBa4+ziN900WZe6AELtMFCsY + HTCEe6b1oe+rBIWsxNNswkakb0w12hZlkZP59/4iahHYaTIPKfmkZTtNKFxeGW8U + 3/81nLtEUVn9EOjIL5uHO1zSeAxBBDZb5P6aajdVpKMa4HFFk18nbE8UnPYOoAHm + IJ+xwBs3FBN6nEfjMoq0P6RaszocK4lcTJ9a/8WqWHouG5s2Zvz3sgxBcWd0VQSJ + Eu2HUVPYn/R+87X5ExZ7n4Pv8z4obz+c9oPtjsJJd2sy8laKK1u1gEF94SLovNcJ + Xe/CaW0lpbJtglF4DwqI02WyjUJ4w1p7fgnVO1gzLRPRIbQc4Q/LtEv/rxMRUsbS + XgH6WzB8yoRztIy+0ZFPlcyvGwU+ZniK18rGPnj9FBMC5IWG/zn7Hqro1K0wxMB2 + HPwiJkwy+ckIgskVYOdT6b3K9qDSZ6sXe4gMmTNLu95enc4HcaINHt4pUvePX54= + =n02T + -----END PGP MESSAGE----- + fp: F38C9D4228FC6F674E322D9C3326D914EB9B8F55 + - created_at: "2026-02-17T22:22:02Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA1Hthzn+T1OoARAAvH00112Z82i6jX1U2jeHDSBkyNT8L2tgCO3pwKpbvP/i + qiq1FWod53sA4l9OlrrshJttmBLjra53fOjhEo/qITb/YQ0gB4/EOHgc/AVkF4Cz + kj0bvUaCwR9vhqla7exG+O10i+OpWXPIeGT0BZUo37XUZ/wPFztR4/GP5qhiC6ZF + q7aZVwCaMKE9YQiAJHGqKPUmsAaEbxQIzZKEkyn9/GMy1YAgMtmfVoZgp8FmiG0k + L6OwMv9BU7gS/4DY82KuF/rtJMGjjio8tLa9Bu/VsHhdREvvXDBjyl78g4wtTUSc + S2JRIdM061scpIoy8sn1VFVbaMP0zgrsU7JvBO9/hLmS6M4Dp5a43OP+hNdWg3X2 + VxtzhGKLlOn6ycO96lMZflz0YA07SM3pw/EFhWszv/GTQCciGUojv1Gi2u94OQQl + YwbePXWF10IUWK4KqMBHUd6H/oyk4wahS3FDBlB5xdUiO61fH1o72ejQvy/d03mB + e4X3ThvpSg6lWJdXvRi3t4Nnk1deGU6NM1CRvZGsASkLulhsVYDsH3vW4NAatUyk + 6g3I5HzJilgLj0CLEyO9dA8m/15Uq8jC2WmBMxqp667QFUuPkKnm1ZUl/vX7Vra+ + yazYNtesU1eAP42IMA78irER+kOpi6AbQL7L8SXTcm+rQvhccNZz2/SO5eDDrHzS + XgErn65EfHWhgyLmkUPt6JPiGSoRgsEyEDn2EF3sxJVkCuwp4eVenSrzhtKTR5To + TIY/KGISC2AXccYlDMOicVE8j2K8NrvM6k/lNYhkaiUfhxqiOrFLK8Ku8YU9oPQ= + =JgVW + -----END PGP MESSAGE----- + fp: 5DA93D5C9D7320E1BD3522C79C78172B3551C9FD + - created_at: "2026-02-17T22:22:02Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA46L6MuPqfJqARAAuPJGCikiP9NTaQJ60FgpC1MHVwBet0RdK86Q3TLHtrfN + ib6ZDZCczv1L/nijEA9sznTHuATnUtd75TrHH1DCKVzFs9fqZx6y7hvnfeJZz85M + iIVybAJwk2Q8xoEf+6IVzFVXwic1RnPCNN1ZYsrfFIWpyRIj6VgP3D9lX10Np/y1 + x4QyxO7+gDG/vcNRkFXgnG+i4bekQwC/4vJ9jX3XEpXbTTPBqhW2OnMPX/T/mMmo + ll9NdBq+dw8OZ9zRCOtht5/HOI0uyP2pa/ooX/nfYiGZHzkIfENl1GID3LD3wHGl + qic1aSx0YkW19fZMQ9cTkoHXzrQDyv3QaSPFljgP3ibSh64k1Tp/lcc5Gn13qIMq + ORh2AeLlBwVSzlvr9FjulLzOJhoo04ZxHbi3OG6Exq9AOk61zGHe6xSa6sA0FoAS + SXAouLls4lqrF1RJhUMOJbX6Iwr+52z3JYgUmYqW1FP2iNnwU8Kfs/lW/3zn7IIH + oYimV6F7+5pqW85r7XMukEZB3LSFVviH7l/4pcxXbGCnfStACENngmd0Rkim6Bog + JYEF17naHgnXHJYsZkVGSnlxDfmaJYjK2YKQA1sFtQw0YenUDaewyPDeoCjAsf+O + QwzfLwJhPCZKRvsCAaP6Xj3DaisofI9fJWGKf8GwfbSFkISBY/RYLh4nTTauwlfS + XgFNQ+YXPmD5bCIO7KD9W+6MOVgyAu8Hyr7eMabydbzkMQ+OfeZCOQ535r6/lpzN + 3s/9QYu0lYN104ZbZTfu9ZrLnp9ULxw75H019o40YyXE5rx1Qhf9K/Ml1LZgdZg= + =Y9gd + -----END PGP MESSAGE----- + fp: 8996B62CBD159DCADD3B6DC08BB33A8ABCF7BC4A + - created_at: "2026-02-17T22:22:02Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DQrf1tCqiJxoSAQdACJe1cOwJNh+yCqthzmRCGIO0eKIAdYjrJHDxsuhVB1ow + 5wFPVzDJ1ERhKaur4wEPRwIe1FLznKHF4bR7F6+yIqgWiUhtMpGsrrezq0vS48C8 + 0l4BwPMgJVgLgfGRH8hZUcM3MYpSQcVKay13eOeTD8kH2rHOY5bq+79l69Z25qXf + 46O7DP5sQ51DLGu6t6UBiifyFWZD+WEbkoa5knvyzziYBoQM5hEeUWj9KSHKBaBD + =zi1G + -----END PGP MESSAGE----- + fp: B71138A6A8964A3C3B8899857B4F70C356765BAB + unencrypted_suffix: _unencrypted + version: 3.11.0 diff --git a/config/hosts/public-web-static/sops.nix b/config/hosts/public-web-static/sops.nix new file mode 100644 index 0000000..b4548ed --- /dev/null +++ b/config/hosts/public-web-static/sops.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + sops = { + defaultSopsFile = ./secrets.yaml; + }; +} diff --git a/config/hosts/public-web-static/spaceapid-config/ccchh-dynamic.json b/config/hosts/public-web-static/spaceapid-config/ccchh-dynamic.json index b2f9f8e..2b1309f 100644 --- a/config/hosts/public-web-static/spaceapid-config/ccchh-dynamic.json +++ b/config/hosts/public-web-static/spaceapid-config/ccchh-dynamic.json @@ -2,26 +2,6 @@ "dynamic": { "sensors": { "temperature": [ - { - "sensor_data": { - "unit": "°C", - "location": "Hauptraum", - "description": "Sensor im Hauptraum" - }, - "allowed_credentials": [ - "club-assistant" - ] - }, - { - "sensor_data": { - "unit": "°C", - "location": "Loetschlauch", - "description": "Sensor im Lötschlauch (Teil der Werkstatt)" - }, - "allowed_credentials": [ - "club-assistant" - ] - }, { "sensor_data": { "unit": "°C", @@ -34,26 +14,6 @@ } ], "humidity": [ - { - "sensor_data": { - "unit": "%", - "location": "Hauptraum", - "description": "Sensor im Hauptraum" - }, - "allowed_credentials": [ - "club-assistant" - ] - }, - { - "sensor_data": { - "unit": "%", - "location": "Loetschlauch", - "description": "Sensor im Lötschlauch (Teil der Werkstatt)" - }, - "allowed_credentials": [ - "club-assistant" - ] - }, { "sensor_data": { "unit": "%", @@ -65,12 +25,13 @@ ] } ], - "CO2": [ + "ext_3d_printer_busy_state": [ { "sensor_data": { - "unit": "ppm", - "location": "Hauptraum", - "description": "Sensor im Hauptraum (Typ: SCD41)" + "unit": "bool", + "location": "Loetschlauch", + "name": "mk4", + "description": "Prusa mk4 busy state" }, "allowed_credentials": [ "club-assistant" @@ -78,9 +39,34 @@ }, { "sensor_data": { - "unit": "ppm", + "unit": "bool", "location": "Loetschlauch", - "description": "Sensor im Lötschlauch (Teil der Werkstatt, Typ: SCD41)" + "name": "mk3.5", + "description": "Prusa mk3.5 busy state" + }, + "allowed_credentials": [ + "club-assistant" + ] + } + ], + "ext_3d_printer_minutes_remaining": [ + { + "sensor_data": { + "unit": "minutes_remaining", + "location": "Loetschlauch", + "name": "mk4", + "description": "Prusa mk4 minutes remaining" + }, + "allowed_credentials": [ + "club-assistant" + ] + }, + { + "sensor_data": { + "unit": "minutes_remaining", + "location": "Loetschlauch", + "name": "mk3.5", + "description": "Prusa mk3.5 minutes remaining" }, "allowed_credentials": [ "club-assistant" diff --git a/config/hosts/public-web-static/spaceapid-config/ccchh-response.json b/config/hosts/public-web-static/spaceapid-config/ccchh-response.json index 3127d20..b49b2da 100644 --- a/config/hosts/public-web-static/spaceapid-config/ccchh-response.json +++ b/config/hosts/public-web-static/spaceapid-config/ccchh-response.json @@ -4,7 +4,7 @@ "14" ], "space": "CCCHH", - "logo": "https://next.hamburg.ccc.de/images/logo.svg", + "logo": "https://hamburg.ccc.de/images/logo.svg", "ext_ccc": "erfa", "url": "https://hamburg.ccc.de/", "location": { @@ -14,7 +14,6 @@ }, "contact": { "phone": "+49 40 23830150", - "irc": "ircs://irc.hackint.org:6697/#ccchh", "mastodon": "@ccchh@chaos.social", "email": "mail@hamburg.ccc.de", "ml": "talk@hamburg.ccc.de", diff --git a/config/hosts/public-web-static/spaceapid.nix b/config/hosts/public-web-static/spaceapid.nix index d2a25b6..3f1f8fe 100644 --- a/config/hosts/public-web-static/spaceapid.nix +++ b/config/hosts/public-web-static/spaceapid.nix @@ -1,19 +1,20 @@ { pkgs, ... }: let - spaceapidSrc = builtins.fetchGit { + version = "v0.1.0"; + spaceapidSrc = pkgs.fetchgit { url = "https://git.hamburg.ccc.de/CCCHH/spaceapid.git"; - ref = "main"; - rev = "bbeb0d0e2b4538faed275b9891fb55149bc3a2f8"; + rev = version; + hash = "sha256-2SDhliltzyydPPZdNn/htDydiK/SHQcYyG/dQ0EyFrY="; }; spaceapid = pkgs.buildGoModule rec { pname = "spaceapid"; - version = "main"; + inherit version; src = spaceapidSrc; ldflags = [ - "-X main.version=${version}-${spaceapidSrc.rev}" + "-X main.version=${version}" ]; # Since spaceapid doesn't have any dependencies, we can set this to null and @@ -38,7 +39,7 @@ in After = [ "network.target" "network-online.target" ]; }; serviceConfig = { - ExecStart = "${spaceapid}/bin/spaceapid -c ${spaceapidConfigResponse},${spaceapidConfigDynamic},/secrets/spaceapid-config-ccchh-credentials.secret"; + ExecStart = "${spaceapid}/bin/spaceapid -c ${spaceapidConfigResponse},${spaceapidConfigDynamic},/run/secrets/spaceapid_config_ccchh_credentials"; User = "spaceapi"; Group = "spaceapi"; Restart = "on-failure"; @@ -47,14 +48,10 @@ in wantedBy = [ "multi-user.target" ]; }; - deployment.keys = { - "spaceapid-config-ccchh-credentials.secret" = { - keyCommand = [ "pass" "noc/vm-secrets/chaosknoten/public-web-static/spaceapid-config-ccchh-credentials" ]; - destDir = "/secrets"; - user = "spaceapi"; - group = "spaceapi"; - permissions = "0640"; - uploadAt = "pre-activation"; - }; + sops.secrets."spaceapid_config_ccchh_credentials" = { + mode = "0440"; + owner = "spaceapi"; + group = "spaceapi"; + restartUnits = [ "spaceapid.service" ]; }; } diff --git a/config/hosts/public-web-static/virtualHosts/c3cat.de.nix b/config/hosts/public-web-static/virtualHosts/c3cat.de.nix index f1ad527..95f9b59 100644 --- a/config/hosts/public-web-static/virtualHosts/c3cat.de.nix +++ b/config/hosts/public-web-static/virtualHosts/c3cat.de.nix @@ -1,10 +1,19 @@ { pkgs, ... }: -{ +let + domain = "c3cat.de"; + dataDir = "/var/www/${domain}"; + deployUser = "c3cat-website-deploy"; +in { + security.acme.certs."${domain}".extraDomainNames = [ "www.${domain}" ]; + services.nginx.virtualHosts = { - "acme-c3cat.de" = { + "acme-${domain}" = { enableACME = true; - serverName = "c3cat.de"; + serverName = "${domain}"; + serverAliases = [ + "www.${domain}" + ]; listen = [ { @@ -14,9 +23,9 @@ ]; }; - "c3cat.de" = { + "www.${domain}" = { forceSSL = true; - useACMEHost = "c3cat.de"; + useACMEHost = "${domain}"; listen = [ { @@ -28,7 +37,42 @@ ]; locations."/" = { - return = "302 https://wiki.hamburg.ccc.de/club:c3cat:start"; + return = "302 https://c3cat.de$request_uri"; + }; + + locations."/manuals/eh22-rgb-ears" = { + return = "307 https://www.c3cat.de/rgb-ears.html"; + }; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + + "${domain}" = { + forceSSL = true; + useACMEHost = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + root = "${dataDir}"; + + locations."/manuals/eh22-rgb-ears" = { + return = "307 https://c3cat.de/rgb-ears.html"; }; extraConfig = '' @@ -43,4 +87,17 @@ ''; }; }; + + systemd.tmpfiles.rules = [ + "d ${dataDir} 0755 ${deployUser} ${deployUser}" + ]; + + users.users."${deployUser}" = { + isNormalUser = true; + group = "${deployUser}"; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIcZJzQO4RYinJm6YDUgCELe8OJA/DYOss+8xp7TtxM0 deploy key for c3cat.de" + ]; + }; + users.groups."${deployUser}" = { }; } diff --git a/config/hosts/public-web-static/virtualHosts/cpu.ccc.de.nix b/config/hosts/public-web-static/virtualHosts/cpu.ccc.de.nix new file mode 100644 index 0000000..d2e779a --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/cpu.ccc.de.nix @@ -0,0 +1,118 @@ +{ ... }: + +let + domain = "cpu.ccc.de"; + dataDir = "/var/www/${domain}"; + deployUser = "cpuccc-website-deploy"; +in +{ + security.acme.certs."cpu.ccc.de".extraDomainNames = [ + "lokal.ccc.de" + "local.ccc.de" + ]; + + services.nginx.virtualHosts = { + "acme-${domain}" = { + enableACME = true; + serverName = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 31820; + } + ]; + }; + + # https://git.hamburg.ccc.de/CCCHH/cpu.ccc.de/src/branch/main/nginx.conf + "${domain}" = { + forceSSL = true; + useACMEHost = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + root = "${dataDir}"; + + extraConfig = '' + index index.html; + default_type text/plain; + + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + + port_in_redirect off; + ''; + + locations."/" = { + tryFiles = "$uri $uri/ =404"; + + extraConfig = '' + location /feed/ { + default_type application/rss+xml; + types { + text/xml application/rss+xml; + } + } + + location /rss { + default_type application/rss+xml; + } + ''; + }; + }; + + "lokal.ccc.de" = { + forceSSL = true; + useACMEHost = "cpu.ccc.de"; + serverAliases = [ + "local.ccc.de" + ]; + + listen = [{ + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + }]; + + locations."/".return = "302 https://cpu.ccc.de"; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + }; + + systemd.tmpfiles.rules = [ + "d ${dataDir} 0755 ${deployUser} ${deployUser}" + ]; + + users.users."${deployUser}" = { + isNormalUser = true; + group = "${deployUser}"; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOnO7g/7mVVKnvkszto8m3nPljO/6qQc/34aEbrhKOvn deploy key for cpu.ccc.de" + ]; + }; + users.groups."${deployUser}" = { }; +} diff --git a/config/hosts/public-web-static/virtualHosts/cryptoparty-hamburg.de.nix b/config/hosts/public-web-static/virtualHosts/cryptoparty-hamburg.de.nix new file mode 100644 index 0000000..37d95b9 --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/cryptoparty-hamburg.de.nix @@ -0,0 +1,97 @@ +{ ... }: + +let + domain = "cryptoparty-hamburg.de"; + dataDir = "/var/www/${domain}"; + deployUser = "cryptoparty-website-deploy"; +in +{ + security.acme.certs."${domain}".extraDomainNames = [ + "cryptoparty.hamburg.ccc.de" + ]; + + services.nginx.virtualHosts = { + "acme-${domain}" = { + enableACME = true; + serverName = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 31820; + } + ]; + }; + + "cryptoparty.hamburg.ccc.de" = { + forceSSL = true; + useACMEHost = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + locations."/".return = "302 https://${domain}$request_uri"; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + + "${domain}" = { + forceSSL = true; + useACMEHost = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + root = "${dataDir}"; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + + error_page 404 /404.html; + + port_in_redirect off; + ''; + }; + }; + + systemd.tmpfiles.rules = [ + "d ${dataDir} 0755 ${deployUser} ${deployUser}" + ]; + + users.users."${deployUser}" = { + isNormalUser = true; + group = "${deployUser}"; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICz+Lxi9scblM/SKJq4nl64UwvVn8SuF2xmzOuyQrzR+ deploy key for cryptoparty-hamburg.de" + ]; + }; + users.groups."${deployUser}" = { }; +} diff --git a/config/hosts/public-web-static/virtualHosts/default.nix b/config/hosts/public-web-static/virtualHosts/default.nix index e22165f..11e9ea1 100644 --- a/config/hosts/public-web-static/virtualHosts/default.nix +++ b/config/hosts/public-web-static/virtualHosts/default.nix @@ -4,10 +4,22 @@ imports = [ ./branding-resources.hamburg.ccc.de.nix ./c3cat.de.nix + ./cpu.ccc.de.nix + ./cryptoparty-hamburg.de.nix + ./element-admin.hamburg.ccc.de.nix ./element.hamburg.ccc.de.nix + ./hacker.tours.nix + ./hackertours.hamburg.ccc.de.nix ./hamburg.ccc.de.nix ./spaceapi.hamburg.ccc.de.nix + ./staging.c3cat.de.nix + ./staging.cryptoparty-hamburg.de.nix + ./staging.hacker.tours.nix + ./staging.hackertours.hamburg.ccc.de.nix ./staging.hamburg.ccc.de.nix ./www.hamburg.ccc.de.nix + ./diday.org.nix + ./staging.diday.org.nix + ./historic-easterhegg ]; } diff --git a/config/hosts/public-web-static/virtualHosts/diday.org.nix b/config/hosts/public-web-static/virtualHosts/diday.org.nix new file mode 100644 index 0000000..547c797 --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/diday.org.nix @@ -0,0 +1,151 @@ +{ ... }: + +let + domain = "diday.org"; + dataDir = "/var/www/${domain}"; + deployUser = "diday-website-deploy"; +in +{ + security.acme.certs."${domain}".extraDomainNames = [ + "did.hamburg.ccc.de" + ]; + + services.nginx.virtualHosts = { + "acme-${domain}" = { + enableACME = true; + serverName = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 31820; + } + ]; + }; + + "did.hamburg.ccc.de" = { + forceSSL = true; + useACMEHost = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + basicAuth = { + "preview" = "liebe"; + }; + + extraConfig = '' + return 301 https://diday.org; + ''; + }; + + "${domain}" = { + forceSSL = true; + useACMEHost = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + basicAuth = { + "preview" = "liebe"; + }; + + root = "${dataDir}"; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + + error_page 404 /404.html; + + port_in_redirect off; + + index index.html; + + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + + # return a redirect based on the map loaded from the webroot + if ($did_redirect_target ~ ^301:(.*)$) { + return 301 $1; + } + if ($did_redirect_target ~ ^302:(.*)$) { + return 302 $1; + } + + # deny access to the redirects config file + location = /nginx-redirects.conf { + deny all; + return 404; + } + + # dynamically redirect the user to the language they prefer + location = / { + set $lang "de"; + if ($http_accept_language ~* "^en") { + set $lang "en"; + } + return 302 /$lang/; + } + + # configure decap-cms content-type and caching rules + location = /admin/cms.js { + expires -1; + add_header Cache-Control "no-store"; + } + location = /admin/config.yml { + expires -1; + add_header Cache-Control "no-store"; + types { } + default_type text/yaml; + } + + # configure asset caching + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # we are using the Astro Image Pipeline, therefore DecapCMS can't access image previews + location /admin/src/ { + log_not_found off; + return 404; + } + + location / { + try_files $uri $uri/ =404; + } + ''; + }; + }; + + systemd.tmpfiles.rules = [ + "d ${dataDir} 0755 ${deployUser} ${deployUser}" + ]; + + users.users."${deployUser}" = { + isNormalUser = true; + group = "${deployUser}"; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBitESG5AvHnHLPo+kdsV5l+wzSTqCltkk0IFAWGqBcl codeberg-actions-runner" + ]; + }; + users.groups."${deployUser}" = { }; +} diff --git a/config/hosts/public-web-static/virtualHosts/element-admin.hamburg.ccc.de.nix b/config/hosts/public-web-static/virtualHosts/element-admin.hamburg.ccc.de.nix new file mode 100644 index 0000000..670b191 --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/element-admin.hamburg.ccc.de.nix @@ -0,0 +1,115 @@ +{ config, pkgs, ... }: + +let + elementAdminVersion = "0.1.10"; + elementAdmin = pkgs.stdenv.mkDerivation (finalAttrs: { + pname = "element-admin"; + version = elementAdminVersion; + + src = pkgs.fetchzip { + url = "https://github.com/element-hq/element-admin/archive/refs/tags/v${elementAdminVersion}.zip"; + sha256 = "sha256-dh7tmzAaTfKB9FuOVhLHpOIsTZK1qMvNq16HeObHOqI="; + }; + + nativeBuildInputs = [ + pkgs.nodejs + pkgs.pnpm.configHook + ]; + + pnpmDeps = pkgs.pnpm.fetchDeps { + inherit (finalAttrs) pname version src; + fetcherVersion = 2; + hash = "sha256-S/MdfUv6q+PaAKWYHxVY80BcpL81dOfpPVhNxEPQVE4="; + }; + + buildPhase = '' + pnpm build + ''; + + installPhase = '' + cp -a dist $out + ''; + }); +in +{ + services.nginx = { + enable = true; + + virtualHosts."acme-element-admin.hamburg.ccc.de" = { + enableACME = true; + serverName = "element-admin.hamburg.ccc.de"; + + listen = [ + { + addr = "0.0.0.0"; + port = 31820; + } + ]; + }; + + virtualHosts."element-admin.hamburg.ccc.de" = { + forceSSL = true; + useACMEHost = "element-admin.hamburg.ccc.de"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + root = elementAdmin; + + locations."/assets" = { + extraConfig = '' + expires 1y; + add_header Cache-Control "public, max-age=31536000, immutable"; + # Security headers. + add_header X-Frame-Options "DENY" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' blob: data:; font-src 'self'; connect-src *; object-src 'none'; media-src 'self'; child-src 'none'; worker-src 'self'; manifest-src 'self';" always; + add_header Permissions-Policy "geolocation=(), camera=(), microphone=(), payment=(), usb=(), magnetometer=(), accelerometer=(), gyroscope=()" always; + ''; + }; + + locations."/" = { + index = "/index.html"; + tryFiles = "$uri $uri/ /"; + extraConfig = '' + # Security headers. + add_header X-Frame-Options "DENY" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' blob: data:; font-src 'self'; connect-src *; object-src 'none'; media-src 'self'; child-src 'none'; worker-src 'self'; manifest-src 'self';" always; + add_header Permissions-Policy "geolocation=(), camera=(), microphone=(), payment=(), usb=(), magnetometer=(), accelerometer=(), gyroscope=()" always; + ''; + }; + + extraConfig = '' + # Security headers. + add_header X-Frame-Options "DENY" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' blob: data:; font-src 'self'; connect-src *; object-src 'none'; media-src 'self'; child-src 'none'; worker-src 'self'; manifest-src 'self';" always; + add_header Permissions-Policy "geolocation=(), camera=(), microphone=(), payment=(), usb=(), magnetometer=(), accelerometer=(), gyroscope=()" always; + + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + }; + + networking.firewall.allowedTCPPorts = [ 8443 31820 ]; +} diff --git a/config/hosts/public-web-static/virtualHosts/element.hamburg.ccc.de.nix b/config/hosts/public-web-static/virtualHosts/element.hamburg.ccc.de.nix index 8a6c629..360fb76 100644 --- a/config/hosts/public-web-static/virtualHosts/element.hamburg.ccc.de.nix +++ b/config/hosts/public-web-static/virtualHosts/element.hamburg.ccc.de.nix @@ -1,10 +1,10 @@ { pkgs, ... }: let - elementWebVersion = "1.11.59"; + elementWebVersion = "1.12.0"; element-web = pkgs.fetchzip { - url = "https://github.com/vector-im/element-web/releases/download/v${elementWebVersion}/element-v${elementWebVersion}.tar.gz"; - sha256 = "sha256-iVTd5zWUJh9wkbKMh+5hq0ucQaLLY29w1xCLxDIdQ18="; + url = "https://github.com/element-hq/element-web/releases/download/v${elementWebVersion}/element-v${elementWebVersion}.tar.gz"; + sha256 = "sha256-2kXQFUhLYyEKuXYw+n94JGlTN2VJHRpjmu78u8gdaro="; }; elementSecurityHeaders = '' # Configuration best practices diff --git a/config/hosts/public-web-static/virtualHosts/hacker.tours.nix b/config/hosts/public-web-static/virtualHosts/hacker.tours.nix new file mode 100644 index 0000000..20bb644 --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/hacker.tours.nix @@ -0,0 +1,68 @@ +{ pkgs, ... }: + +let + domain = "hacker.tours"; + dataDir = "/var/www/${domain}"; + deployUser = "hackertours-website-deploy"; +in +{ + services.nginx.virtualHosts = { + "acme-${domain}" = { + enableACME = true; + serverName = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 31820; + } + ]; + }; + + "${domain}" = { + forceSSL = true; + useACMEHost = "${domain}"; + + locations."/shop" = { + return = "302 https://tickets.hamburg.ccc.de"; + }; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + root = "${dataDir}"; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + + error_page 404 /404.html; + ''; + }; + }; + + systemd.tmpfiles.rules = [ + "d ${dataDir} 0755 ${deployUser} ${deployUser}" + ]; + + users.users."${deployUser}" = { + isNormalUser = true; + group = "${deployUser}"; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOrDTANfPMkcf+V7zkypzaeX2fxkfStPHmZKqC29xyqy deploy key for hacker.tours" + ]; + }; + users.groups."${deployUser}" = { }; +} diff --git a/config/hosts/public-web-static/virtualHosts/hackertours.hamburg.ccc.de.nix b/config/hosts/public-web-static/virtualHosts/hackertours.hamburg.ccc.de.nix new file mode 100644 index 0000000..eeb7778 --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/hackertours.hamburg.ccc.de.nix @@ -0,0 +1,77 @@ +{ pkgs, ... }: + +let + domain = "hackertours.hamburg.ccc.de"; + dataDir = "/var/www/${domain}"; + deployUser = "ht-ccchh-website-deploy"; +in +{ + services.nginx.virtualHosts = { + "acme-${domain}" = { + enableACME = true; + serverName = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 31820; + } + ]; + }; + + "${domain}" = { + forceSSL = true; + useACMEHost = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + locations."/de/posts/faq" = { + return = "302 /de/faq/"; + }; + + locations."/en/posts/faq" = { + return = "302 /en/faq/"; + }; + + root = "${dataDir}"; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + + error_page 404 /404.html; + + port_in_redirect off; + + rewrite ^/(de|en)/tours$ /$1/37c3 redirect; + rewrite ^/(de|en)/tours/(.*)$ /$1/37c3/$2 redirect; + ''; + }; + }; + + systemd.tmpfiles.rules = [ + "d ${dataDir} 0755 ${deployUser} ${deployUser}" + ]; + + users.users."${deployUser}" = { + isNormalUser = true; + group = "${deployUser}"; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILxMnllgRD6W85IQ0WrVJSwr7dKM8PLNK4pmGaJRu0OR deploy key for hackertours.hamburg.ccc.de" + ]; + }; + users.groups."${deployUser}" = { }; +} diff --git a/config/hosts/public-web-static/virtualHosts/hamburg.ccc.de.nix b/config/hosts/public-web-static/virtualHosts/hamburg.ccc.de.nix index 1d8eef1..1c967c9 100644 --- a/config/hosts/public-web-static/virtualHosts/hamburg.ccc.de.nix +++ b/config/hosts/public-web-static/virtualHosts/hamburg.ccc.de.nix @@ -17,6 +17,7 @@ "hamburg.ccc.de" = { forceSSL = true; useACMEHost = "hamburg.ccc.de"; + default = true; listen = [ { @@ -83,6 +84,11 @@ return = "302 https://$host/blog/index.xml"; }; + # Redirect /calendar to the Nextcloud calendar, as this location apparently gets used in several locations. + locations."/calendar" = { + return = "302 https://cloud.hamburg.ccc.de/apps/calendar/embed/QJAdExziSnNJEz5g"; + }; + extraConfig = '' # Make use of the ngx_http_realip_module to set the $remote_addr and # $remote_port to the client address and client port, when using proxy @@ -94,6 +100,8 @@ real_ip_header proxy_protocol; error_page 404 /404.html; + + port_in_redirect off; ''; }; }; diff --git a/config/hosts/public-web-static/virtualHosts/historic-easterhegg/default.nix b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/default.nix new file mode 100644 index 0000000..69d8855 --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/default.nix @@ -0,0 +1,12 @@ +{ ... }: + +{ + imports = [ + ./eh03.nix + ./eh05.nix + ./eh07.nix + ./eh09.nix + ./eh11.nix + ./eh20.nix + ]; +} diff --git a/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh03.nix b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh03.nix new file mode 100644 index 0000000..2c5dd86 --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh03.nix @@ -0,0 +1,101 @@ +{ pkgs, ... }: + +let + eh03 = pkgs.fetchgit { + url = "https://git.hamburg.ccc.de/CCCHH/easterhegg-2003-website.git"; + rev = "74977c56486cd060566bf06678a936e801952f9e"; + hash = "sha256-ded/NO+Jex2Sa4yWAIRpqANsv8i0vKmJSkM5r9KxaVk="; + }; +in +{ + security.acme.certs."eh03.easterhegg.eu".extraDomainNames = [ + "eh2003.hamburg.ccc.de" + "www.eh2003.hamburg.ccc.de" + "easterhegg2003.hamburg.ccc.de" + "www.easterhegg2003.hamburg.ccc.de" + ]; + + services.nginx.virtualHosts = { + "acme-eh03.easterhegg.eu" = { + enableACME = true; + serverName = "eh03.easterhegg.eu"; + serverAliases = [ + "eh2003.hamburg.ccc.de" + "www.eh2003.hamburg.ccc.de" + "easterhegg2003.hamburg.ccc.de" + "www.easterhegg2003.hamburg.ccc.de" + ]; + listen = [{ + addr = "0.0.0.0"; + port = 31820; + }]; + }; + + "easterhegg2003.hamburg.ccc.de" = { + forceSSL = true; + useACMEHost = "eh03.easterhegg.eu"; + serverAliases = [ + "eh2003.hamburg.ccc.de" + "www.eh2003.hamburg.ccc.de" + "www.easterhegg2003.hamburg.ccc.de" + ]; + + listen = [{ + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + }]; + + locations."/".return = "302 https://eh03.easterhegg.eu"; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + + "eh03.easterhegg.eu" = { + forceSSL = true; + useACMEHost = "eh03.easterhegg.eu"; + + listen = [{ + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + }]; + + locations."/" = { + index = "index.html"; + root = eh03; + extraConfig = '' + # Set default_type to html + default_type text/html; + # Enable SSI + ssi on; + ''; + }; + + extraConfig = '' + set $chosen_lang "de"; + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + # Enable SSI + ssi on; + ''; + }; + }; +} diff --git a/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh05.nix b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh05.nix new file mode 100644 index 0000000..37cb893 --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh05.nix @@ -0,0 +1,100 @@ +{ pkgs, ... }: + +let + eh05 = pkgs.fetchgit { + url = "https://git.hamburg.ccc.de/CCCHH/easterhegg-2005-website.git"; + rev = "f1455aee35b6462ab5c46f3d52c47e0b200c1315"; + hash = "sha256-lA4fxO05K39nosSYNfKUtSCrK+dja1yWKILqRklSNy8="; + }; +in +{ + security.acme.certs."eh05.easterhegg.eu".extraDomainNames = [ + "eh2005.hamburg.ccc.de" + "www.eh2005.hamburg.ccc.de" + "easterhegg2005.hamburg.ccc.de" + "www.easterhegg2005.hamburg.ccc.de" + ]; + + services.nginx.virtualHosts = { + "acme-eh05.easterhegg.eu" = { + enableACME = true; + serverName = "eh05.easterhegg.eu"; + serverAliases = [ + "eh2005.hamburg.ccc.de" + "www.eh2005.hamburg.ccc.de" + "easterhegg2005.hamburg.ccc.de" + "www.easterhegg2005.hamburg.ccc.de" + ]; + listen = [{ + addr = "0.0.0.0"; + port = 31820; + }]; + }; + + "easterhegg2005.hamburg.ccc.de" = { + forceSSL = true; + useACMEHost = "eh05.easterhegg.eu"; + serverAliases = [ + "eh2005.hamburg.ccc.de" + "www.eh2005.hamburg.ccc.de" + "www.easterhegg2005.hamburg.ccc.de" + ]; + + listen = [{ + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + }]; + + locations."/".return = "302 https://eh05.easterhegg.eu"; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + + "eh05.easterhegg.eu" = { + forceSSL = true; + useACMEHost = "eh05.easterhegg.eu"; + + listen = [{ + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + }]; + + locations."/" = { + index = "index.shtml"; + root = eh05; + extraConfig = '' + # Set default_type to html + default_type text/html; + # Enable SSI + ssi on; + ''; + }; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + # Enable SSI + ssi on; + ''; + }; + }; +} diff --git a/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh07.nix b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh07.nix new file mode 100644 index 0000000..ebfa712 --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh07.nix @@ -0,0 +1,106 @@ +{ pkgs, ... }: + +let + eh07 = pkgs.fetchgit { + url = "https://git.hamburg.ccc.de/CCCHH/easterhegg-2007-website.git"; + rev = "0bb06fd2654814ddda28469a1bf9e50a9814dd9a"; + hash = "sha256-jMpDxgxbL3ipG3HLJo0ISTdWfYYrd2EfwpmoiWV0qCM="; + }; +in +{ + security.acme.certs."eh07.easterhegg.eu".extraDomainNames = [ + "eh2007.hamburg.ccc.de" + "www.eh2007.hamburg.ccc.de" + "eh07.hamburg.ccc.de" + "www.eh07.hamburg.ccc.de" + "easterhegg2007.hamburg.ccc.de" + "www.easterhegg2007.hamburg.ccc.de" + ]; + + services.nginx.virtualHosts = { + "acme-eh07.easterhegg.eu" = { + enableACME = true; + serverName = "eh07.easterhegg.eu"; + serverAliases = [ + "eh2007.hamburg.ccc.de" + "www.eh2007.hamburg.ccc.de" + "eh07.hamburg.ccc.de" + "www.eh07.hamburg.ccc.de" + "easterhegg2007.hamburg.ccc.de" + "www.easterhegg2007.hamburg.ccc.de" + ]; + listen = [{ + addr = "0.0.0.0"; + port = 31820; + }]; + }; + + "easterhegg2007.hamburg.ccc.de" = { + forceSSL = true; + useACMEHost = "eh07.easterhegg.eu"; + serverAliases = [ + "eh2007.hamburg.ccc.de" + "www.eh2007.hamburg.ccc.de" + "eh07.hamburg.ccc.de" + "www.eh07.hamburg.ccc.de" + "www.easterhegg2007.hamburg.ccc.de" + ]; + + listen = [{ + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + }]; + + locations."/".return = "302 https://eh07.easterhegg.eu"; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + + "eh07.easterhegg.eu" = { + forceSSL = true; + useACMEHost = "eh07.easterhegg.eu"; + + listen = [{ + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + }]; + + locations."/" = { + index = "index.shtml"; + root = eh07; + extraConfig = '' + # Set default_type to html + default_type text/html; + # Enable SSI + ssi on; + ''; + }; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + # Enable SSI + ssi on; + ''; + }; + }; +} diff --git a/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh09.nix b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh09.nix new file mode 100644 index 0000000..ea274af --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh09.nix @@ -0,0 +1,105 @@ +{ pkgs, ... }: + +let + eh09 = pkgs.fetchgit { + url = "https://git.hamburg.ccc.de/CCCHH/easterhegg-2009-website.git"; + rev = "6d4a50c5ab23870072f0b33dd0171b0c56d6cab5"; + hash = "sha256-kPJOrKseJD/scRxhYFa249DT1cYmeCjnK50Bt0IJZK8="; + }; +in +{ + security.acme.certs."eh09.easterhegg.eu".extraDomainNames = [ + "eh2009.hamburg.ccc.de" + "www.eh2009.hamburg.ccc.de" + "eh09.hamburg.ccc.de" + "www.eh09.hamburg.ccc.de" + "easterhegg2009.hamburg.ccc.de" + "www.easterhegg2009.hamburg.ccc.de" + ]; + + services.nginx.virtualHosts = { + "acme-eh09.easterhegg.eu" = { + enableACME = true; + serverName = "eh09.easterhegg.eu"; + serverAliases = [ + "eh2009.hamburg.ccc.de" + "www.eh2009.hamburg.ccc.de" + "eh09.hamburg.ccc.de" + "www.eh09.hamburg.ccc.de" + "easterhegg2009.hamburg.ccc.de" + "www.easterhegg2009.hamburg.ccc.de" + ]; + listen = [{ + addr = "0.0.0.0"; + port = 31820; + }]; + }; + + "easterhegg2009.hamburg.ccc.de" = { + forceSSL = true; + useACMEHost = "eh09.easterhegg.eu"; + serverAliases = [ + "eh2009.hamburg.ccc.de" + "www.eh2009.hamburg.ccc.de" + "eh09.hamburg.ccc.de" + "www.eh09.hamburg.ccc.de" + "www.easterhegg2009.hamburg.ccc.de" + ]; + + listen = [{ + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + }]; + + locations."/".return = "302 https://eh09.easterhegg.eu"; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + + "eh09.easterhegg.eu" = { + forceSSL = true; + useACMEHost = "eh09.easterhegg.eu"; + + listen = [{ + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + }]; + + locations."/" = { + index = "index.shtml"; + root = eh09; + extraConfig = '' + # Set default_type to html + default_type text/html; + # Enable SSI + ssi on; + ''; + }; + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + # Enable SSI + ssi on; + ''; + }; + }; +} diff --git a/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh11.nix b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh11.nix new file mode 100644 index 0000000..39d7fad --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh11.nix @@ -0,0 +1,106 @@ +{ pkgs, ... }: + +let + eh11 = pkgs.fetchgit { + url = "https://git.hamburg.ccc.de/CCCHH/easterhegg-2011-website.git"; + rev = "c20540af71d4a0bd1fa12f49962b92d04293415b"; + hash = "sha256-9hhtfU8fp2HOThcyQ4R7kuGQBjZktqMtiiYQhOas2QA="; + }; +in +{ + security.acme.certs."eh11.easterhegg.eu".extraDomainNames = [ + "eh2011.hamburg.ccc.de" + "www.eh2011.hamburg.ccc.de" + "eh11.hamburg.ccc.de" + "www.eh11.hamburg.ccc.de" + "easterhegg2011.hamburg.ccc.de" + "www.easterhegg2011.hamburg.ccc.de" + ]; + + services.nginx.virtualHosts = { + "acme-eh11.easterhegg.eu" = { + enableACME = true; + serverName = "eh11.easterhegg.eu"; + serverAliases = [ + "eh2011.hamburg.ccc.de" + "www.eh2011.hamburg.ccc.de" + "eh11.hamburg.ccc.de" + "www.eh11.hamburg.ccc.de" + "easterhegg2011.hamburg.ccc.de" + "www.easterhegg2011.hamburg.ccc.de" + ]; + listen = [{ + addr = "0.0.0.0"; + port = 31820; + }]; + }; + + "easterhegg2011.hamburg.ccc.de" = { + forceSSL = true; + useACMEHost = "eh11.easterhegg.eu"; + serverAliases = [ + "eh2011.hamburg.ccc.de" + "www.eh2011.hamburg.ccc.de" + "eh11.hamburg.ccc.de" + "www.eh11.hamburg.ccc.de" + "www.easterhegg2011.hamburg.ccc.de" + ]; + + listen = [{ + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + }]; + + locations."/".return = "302 https://eh11.easterhegg.eu"; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + + "eh11.easterhegg.eu" = { + forceSSL = true; + useACMEHost = "eh11.easterhegg.eu"; + + listen = [{ + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + }]; + + locations."/" = { + index = "index.shtml"; + root = eh11; + extraConfig = '' + # Set default_type to html + default_type text/html; + # Enable SSI + ssi on; + ''; + }; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + # Enable SSI + ssi on; + ''; + }; + }; +} diff --git a/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh20.nix b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh20.nix new file mode 100644 index 0000000..afc93c1 --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh20.nix @@ -0,0 +1,91 @@ +{ pkgs, ... }: + +let + eh20 = pkgs.fetchgit { + url = "https://git.hamburg.ccc.de/CCCHH/easterhegg-eh20-website.git"; + rev = "026932ef2f1fb85c99269e0fb547589a25d3687c"; + hash = "sha256-YYxHhPYIioJgyHXNieoX6ibasHcNw/AFk+qCNSOxke4="; + }; +in +{ + security.acme.certs."eh20.easterhegg.eu".extraDomainNames = [ + "www.eh20.easterhegg.eu" + "eh20.hamburg.ccc.de" + ]; + + services.nginx.virtualHosts = { + "acme-eh20.easterhegg.eu" = { + enableACME = true; + serverName = "eh20.easterhegg.eu"; + serverAliases = [ + "www.eh20.easterhegg.eu" + "eh20.hamburg.ccc.de" + ]; + listen = [{ + addr = "0.0.0.0"; + port = 31820; + }]; + }; + + "www.eh20.easterhegg.eu" = { + forceSSL = true; + useACMEHost = "eh20.easterhegg.eu"; + serverAliases = [ + "eh20.hamburg.ccc.de" + ]; + + listen = [{ + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + }]; + + locations."/".return = "302 https://eh20.easterhegg.eu"; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + + "eh20.easterhegg.eu" = { + forceSSL = true; + useACMEHost = "eh20.easterhegg.eu"; + + listen = [{ + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + }]; + + locations."/" = { + index = "start.html"; + root = "${eh20}/wiki_siteexport"; + }; + + # redirect doku.php?id=$pagename to /$pagename.html + locations."/doku.php" = { + return = "301 $scheme://$host/$arg_id.html"; + }; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + }; +} diff --git a/config/hosts/public-web-static/virtualHosts/staging.c3cat.de.nix b/config/hosts/public-web-static/virtualHosts/staging.c3cat.de.nix new file mode 100644 index 0000000..c91d283 --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/staging.c3cat.de.nix @@ -0,0 +1,60 @@ +{ pkgs, ... }: + +let + domain = "staging.c3cat.de"; + dataDir = "/var/www/${domain}"; + deployUser = "c3cat-website-deploy"; +in { + services.nginx.virtualHosts = { + "acme-${domain}" = { + enableACME = true; + serverName = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 31820; + } + ]; + }; + + "${domain}" = { + forceSSL = true; + useACMEHost = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + root = "${dataDir}"; + + # Disallow *, since this is staging and doesn't need to be in any search + # results. + locations."/robots.txt" = { + return = "200 \"User-agent: *\\nDisallow: *\\n\""; + }; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + }; + + systemd.tmpfiles.rules = [ + "d ${dataDir} 0755 ${deployUser} ${deployUser}" + ]; + + # c3cat deploy user already defined in c3cat.de.nix. +} diff --git a/config/hosts/public-web-static/virtualHosts/staging.cryptoparty-hamburg.de.nix b/config/hosts/public-web-static/virtualHosts/staging.cryptoparty-hamburg.de.nix new file mode 100644 index 0000000..6733dad --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/staging.cryptoparty-hamburg.de.nix @@ -0,0 +1,94 @@ +{ ... }: + +let + domain = "staging.cryptoparty-hamburg.de"; + dataDir = "/var/www/${domain}"; + deployUser = "cryptoparty-website-deploy"; +in +{ + security.acme.certs."${domain}".extraDomainNames = [ + "staging.cryptoparty.hamburg.ccc.de" + ]; + + services.nginx.virtualHosts = { + "acme-${domain}" = { + enableACME = true; + serverName = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 31820; + } + ]; + }; + + "staging.cryptoparty.hamburg.ccc.de" = { + forceSSL = true; + useACMEHost = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + locations."/".return = "302 https://${domain}$request_uri"; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + + "${domain}" = { + forceSSL = true; + useACMEHost = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + root = "${dataDir}"; + + # Disallow *, since this is staging and doesn't need to be in any search + # results. + locations."/robots.txt" = { + return = "200 \"User-agent: *\\nDisallow: *\\n\""; + }; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + + port_in_redirect off; + ''; + }; + }; + + systemd.tmpfiles.rules = [ + "d ${dataDir} 0755 ${deployUser} ${deployUser}" + ]; + + # Cryptoparty website deploy user already defined in cryptoparty-hamburg.de.nix. +} diff --git a/config/hosts/public-web-static/virtualHosts/staging.diday.org.nix b/config/hosts/public-web-static/virtualHosts/staging.diday.org.nix new file mode 100644 index 0000000..b165348 --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/staging.diday.org.nix @@ -0,0 +1,81 @@ +{ config, ... }: + +let + domain = "staging.diday.org"; + dataDir = "/var/www/${domain}"; + deployUser = "diday-website-deploy"; +in +{ + security.acme.certs."${domain}" = { + domain = "staging.diday.org"; + extraDomainNames = [ "*.staging.diday.org" ]; + group = "nginx"; + dnsResolver = "45.54.76.1:53"; + dnsProvider = "desec"; + environmentFile = config.sops.secrets."staging.diday.org/lego.env".path; + }; + + services.nginx.virtualHosts = { + "*.${domain}" = { + useACMEHost = "${domain}"; + forceSSL = true; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + basicAuth = { + "preview" = "liebe"; + }; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + port_in_redirect off; + + error_page 404 /404.html; + + location / { + if ($host ~* "^(pr\d+)\.staging\.diday\.org$") { + root /var/www/staging.diday.org/$1/; + } + + index index.html; + try_files $uri $uri/ =404; + + # deny access to the redirects config file + location = /nginx-redirects.conf { + deny all; + return 404; + } + + # dynamically redirect the user to the language they prefer + location = / { + set $lang "de"; + if ($http_accept_language ~* "^en") { + set $lang "en"; + } + return 302 /$lang/; + } + } + ''; + }; + }; + + systemd.tmpfiles.rules = [ + "d ${dataDir} 0755 ${deployUser} ${deployUser}" + ]; + + sops.secrets."staging.diday.org/lego.env" = {}; +} diff --git a/config/hosts/public-web-static/virtualHosts/staging.hacker.tours.nix b/config/hosts/public-web-static/virtualHosts/staging.hacker.tours.nix new file mode 100644 index 0000000..14ede9b --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/staging.hacker.tours.nix @@ -0,0 +1,61 @@ +{ pkgs, ... }: + +let + domain = "staging.hacker.tours"; + dataDir = "/var/www/${domain}"; + deployUser = "hackertours-website-deploy"; +in +{ + services.nginx.virtualHosts = { + "acme-${domain}" = { + enableACME = true; + serverName = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 31820; + } + ]; + }; + + "${domain}" = { + forceSSL = true; + useACMEHost = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + root = "${dataDir}"; + + # Disallow *, since this is staging and doesn't need to be in any search + # results. + locations."/robots.txt" = { + return = "200 \"User-agent: *\\nDisallow: *\\n\""; + }; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + ''; + }; + }; + + systemd.tmpfiles.rules = [ + "d ${dataDir} 0755 ${deployUser} ${deployUser}" + ]; + + # Hackertours deploy user already defined in hacker.tours.nix. +} diff --git a/config/hosts/public-web-static/virtualHosts/staging.hackertours.hamburg.ccc.de.nix b/config/hosts/public-web-static/virtualHosts/staging.hackertours.hamburg.ccc.de.nix new file mode 100644 index 0000000..79ca38c --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/staging.hackertours.hamburg.ccc.de.nix @@ -0,0 +1,63 @@ +{ pkgs, ... }: + +let + domain = "staging.hackertours.hamburg.ccc.de"; + dataDir = "/var/www/${domain}"; + deployUser = "ht-ccchh-website-deploy"; +in +{ + services.nginx.virtualHosts = { + "acme-${domain}" = { + enableACME = true; + serverName = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 31820; + } + ]; + }; + + "${domain}" = { + forceSSL = true; + useACMEHost = "${domain}"; + + listen = [ + { + addr = "0.0.0.0"; + port = 8443; + ssl = true; + proxyProtocol = true; + } + ]; + + root = "${dataDir}"; + + # Disallow *, since this is staging and doesn't need to be in any search + # results. + locations."/robots.txt" = { + return = "200 \"User-agent: *\\nDisallow: *\\n\""; + }; + + extraConfig = '' + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + + error_page 404 /404.html; + ''; + }; + }; + + systemd.tmpfiles.rules = [ + "d ${dataDir} 0755 ${deployUser} ${deployUser}" + ]; + + # Hackertours CCCHH deploy user already defined in hackertours.hamburg.ccc.de.nix. +} diff --git a/config/hosts/public-web-static/virtualHosts/staging.hamburg.ccc.de.nix b/config/hosts/public-web-static/virtualHosts/staging.hamburg.ccc.de.nix index a36a099..f7e0752 100644 --- a/config/hosts/public-web-static/virtualHosts/staging.hamburg.ccc.de.nix +++ b/config/hosts/public-web-static/virtualHosts/staging.hamburg.ccc.de.nix @@ -44,6 +44,8 @@ # Then tell the realip_module to get the addreses from the proxy protocol # header. real_ip_header proxy_protocol; + + port_in_redirect off; ''; }; }; diff --git a/config/hosts/woodpecker/configuration.nix b/config/hosts/woodpecker/configuration.nix new file mode 100644 index 0000000..45e228e --- /dev/null +++ b/config/hosts/woodpecker/configuration.nix @@ -0,0 +1,7 @@ +{ config, pkgs, ... }: + +{ + networking.hostName = "woodpecker"; + + system.stateVersion = "24.05"; +} diff --git a/config/hosts/woodpecker/default.nix b/config/hosts/woodpecker/default.nix new file mode 100644 index 0000000..1db0c8c --- /dev/null +++ b/config/hosts/woodpecker/default.nix @@ -0,0 +1,11 @@ +{ config, pkgs, ... }: + +{ + imports = [ + ./woodpecker-agent + ./woodpecker-server + ./configuration.nix + ./networking.nix + ./sops.nix + ]; +} diff --git a/config/hosts/woodpecker/networking.nix b/config/hosts/woodpecker/networking.nix new file mode 100644 index 0000000..3301812 --- /dev/null +++ b/config/hosts/woodpecker/networking.nix @@ -0,0 +1,22 @@ +{ ... }: + +{ + networking = { + interfaces.net0 = { + ipv4.addresses = [ + { + address = "172.31.17.160"; + prefixLength = 25; + } + ]; + }; + defaultGateway = "172.31.17.129"; + nameservers = [ "212.12.50.158" "192.76.134.90" ]; + search = [ "hamburg.ccc.de" ]; + }; + + systemd.network.links."10-net0" = { + matchConfig.MACAddress = "BC:24:11:5F:A9:B7"; + linkConfig.Name = "net0"; + }; +} diff --git a/config/hosts/woodpecker/secrets.yaml b/config/hosts/woodpecker/secrets.yaml new file mode 100644 index 0000000..5fae897 --- /dev/null +++ b/config/hosts/woodpecker/secrets.yaml @@ -0,0 +1,149 @@ +woodpecker_server_environment_file: ENC[AES256_GCM,data:68Wu0UOHBAGZHSJ0x4wbeDLm626jpumv9w6A65FNKsmzYp6P4/c4g1MF1agQd7l9nKMTRrgyJyfoEZYFQRX6lYSmcsQLfn++uh1JpFoClT5p/5hBkiDq4owUFU+NGUiyl6yjYlEiaxLwC4ZdyISHeEYpbrvGyIXLsFgdrQ0rVX3cCRwIMxFcyCG6d3MZVoqAw1A=,iv:y/+X02aRPBOoR57P9s7y/SijvXVLuiBBfFYqeJLvQEU=,tag:DNwK+M6s3moglkMkrWccyA==,type:str] +woodpecker_agent_environment_file: ENC[AES256_GCM,data:rwp6TYYFJ/IZH+3pGhPxjdZMLoyPMr/W1RXm4IkUGn+SmIjHZcdFZ8nEhvOfnkfrXNPc2MR+X6NXUmVOcBjSCbcBjh9sC653UpKimt9I3/Ec,iv:X9JH7dmTayw8BaEsXYil3PrykCdd+/ANGHVfEyRvc7A=,tag:/ErkX1WnruanNgTTBUT6LA==,type:str] +sops: + age: + - recipient: age19h7xtfmt3py3ydgl8d8fgh8uakxqxjr74flrxev3pgmvvx94kvtq5d932d + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWdUhjQUJIS2QvWk1Yc3pR + M1daYlRubnlsQk9tcytBNWdYMUU4bG1DVHhZCnVKK00ySDdBZFhzRXlaQ2xVaTBh + bVVVNzRraUpHSFFuRStzWFprUGRoMGcKLS0tIEVBUWh4STBIaGdTelFKcnB0TkNR + SEd1VTZQZWlkYXVKcVRPbVA1U3VWbFUKnuaPGc29kKE86nh+xEto0Jb6BQ0uH3pr + Q1QPgfiOCYGkuUewy3LlGnLTuMxHBBWAjg4zgaYPHU2F/HCS5DB5nw== + -----END AGE ENCRYPTED FILE----- + - recipient: age1klxtcr23hers0lh4f5zdd53tyrtg0jud35rhydstyjq9fjymf9hsn2a8ch + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArdVJNK1ljNWwrTy9qc1p1 + N1MweERxdkNXZVZITWRRdGFQRHRQeTNFTTI4CjFkSVJQMFBKY2tRWE1DeXdMOUZY + Qm5oYTU1azFzVEpYZUptcTVhRCsxL28KLS0tIEI0czljekgvQlc1SlVGSUpGb1N3 + NytOaE5nQ3E4bFhCQ1ZDU3MyM3p5cmcK3LGva0vDjitqOBqBo6jHqRBaH8T8cOim + IF8ygc0i/dbaec59ZcCMhS0n8yv0lVHO2WiUwPaKTh5hkti9LhKlaA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-06-22T15:55:25Z" + mac: ENC[AES256_GCM,data:UmDbmxSRj8YfCkKEelQNMJ8mzbu5aQdB9yOr9JfUh5TB9r5Z5ttZ1wgJDJqHNtsII3JGXUvbgHbsmbPikkrj4Ege1rrgr4UttN1rtgeaAKlZIlqb9pOnV4//GJL8jbxCgFp2h2O80G05nAXG54DaY//4Y5hfTyPzgyDlGQ6jlhg=,iv:5e8lpFfGAJh8lTFcY4MlZG7PgnzM0UycsU0tB2KN+zQ=,tag:4xUEHg04wjDbhc9MOItzuQ==,type:str] + pgp: + - created_at: "2026-02-17T22:22:03Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAz5uSgHG2iMJAQ/+NzRul1VZa2BLnjCsdUP7YErHvLsJqc/KwEFgGX8yN1Bg + VOHgm0MBYC14KtMu0Zb+Cm6ypqyaa4j+MXNVWLDTOLt1aLibashBmyPbwHNr0XwO + 6tr9qYAPixaoWFeiCtATKLUzWzQ68eDv9JHNNQvKGNjet9E1yOIxWHj6RxyV/EeZ + 50nf+7AO7cFkqRGFxrGKAYchzetajNPLtbS2htFCc3Vt9m38jusafvYdjeG+HQHe + 6INzdNqvM7vhfWJlIiTPCXGKvx0NhLg6sVvcXpq5mKbMAhja80KyUdl772L8Kr6P + ZYvmj+Ey8+GM+opGGxcaSBmgw3ZLRIZ1tks3LlRf/UiAZD5MqJoRL1DEJMtHzYnp + IqxOEiuMLAL1/TxG4KhJfT5Gs9Kf3Cnr6djhhsYg3GYXSQdhiyaBDaLpu68nEIRN + JSdA/7pCjxhvlgFl9XvPaMzQD5GZNlVapJPn1c9Ambi9cs4kB8nds+Xx4KgIN3li + 85flJnEtQWRI2DL8qJgoYJ1cXevkPVzKLFnQEHfLuozIzfPl1Wq1Sb3EQk9YZer9 + yfVHRngBBhmfNMtFy9gq8FLod0Odas3KQDAa7ndPMMx6oL5DoNeI3DpuYW4eQIZK + EbT5iHLMrTXHb2XKTHfXdjl6ttED+12GAby69jdGXjt6UVAM6b0UorWfSLLoqabS + XgG1w128eegSl4tqdYO/KDL30c9J1K8LqaJmg+9eFAi9Da/zmPAck+DlS7XUkeiX + OqZiOXLul0N2Qe/tWkpJD8F3HV+K6Xt0MSx8VsmeliicG4Rpme1Xysau+7kht3U= + =KUjN + -----END PGP MESSAGE----- + fp: 18DFCE01456DAB52EA38A6584EDC64F35FA1D6A5 + - created_at: "2026-02-17T22:22:03Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAw5vwmoEJHQ1ARAAxH+TtzvFlUZfD3U7BNRr9SyWVxnkR3U2zvvDG5A3I28K + fI1U1am6Z+gSvYdId38hiMPxDmDIMl2wCYCXd17q+PSycsJ1Bbzy1zaht6KcpSJb + s9jmNmf+5mazSRZ/COBy4mMq+2mam4/vu+xS85IsgxyxK9ygnCurmzMqn3lxatm0 + ICxvoLMAamA+tAfxtw+a5lEMok7pHdKndZmrKvxO7nLXM0292sJ3VHp5Uy9k487W + PznpjM1st/f/0gTu1mgb8rnUkSszw1odBeQ+xw2JvcDHE6Ow7PpCk83oTWXil6c4 + bEsrtvaFLWXN9/gssnayoMWHb/TCHKVe4AGrMevFkRdEFDRV5FRZGqzuGDP++X10 + KYyMN0/Wo/XU7Rn3+7HmKvz0qeaAI/IRTrhdXUDtQQ13/waxGrJEquwS5Xuwea6l + LlA6hwnAERSVrVkMQ60ITOD6n7lvAPA7jD/HhI3P2Xy4mDFW9ZnfnWi0xI9pRCsk + w+ZnQ1Ckacv0gJUirvsVSdUYHwvEvpFEVSsZsv5QbNsaWi5jn5XDH0eqlXQE80aO + o3vPFTNCHNixspiaIO4V8etyv6nSh7BxwDvIH4nZVxr8HmxILs0Occw9anvA81md + roF3pyb+ZFRIwcBh72VSdAm1D/n4h14lnmMj+19HEA3zvbPnZQejtGFMY1Oe2VTS + XgHMI0aRJANXczMA7LSg9vxDYvWXE2KR526oBsC1E7otCNGkxj3hhmng25K3tmIU + E2AAaAIk/RukMnydb93XGciPquCZsWlmpwlTGXCqoqiNBilvIE1lXH6rhym78ko= + =nRW4 + -----END PGP MESSAGE----- + fp: 87AB00D45D37C9E9167B5A5A333448678B60E505 + - created_at: "2026-02-17T22:22:03Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DerEtaFuTeewSAQdAPWizx2khKtlshnLwE5PRszAdTvTlsEEiWVV5xJx3PnAw + 9Gj2lZZX4F0AXoKInElg2N02FXpIo24ZZUPXGqpswfSv93NFNNK+FWwqUCRZhuCM + 0l4Blkyy4PthGwIAtXqZ8GGxjoDGBLIAE/zrY9tdNB5XAnkiy7J82kora0dphpkq + Llb1Jgh0+ZK8RQzaf5wcgWf867MhJLhv0N+qLsFVutGpqFy1W/1vaLQ5au5Ty2Tw + =460I + -----END PGP MESSAGE----- + fp: 057870A2C72CD82566A3EC983695F4FCBCAE4912 + - created_at: "2026-02-17T22:22:03Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAxjNhCKPP69fAQ//Rzcsq0Yay/3g/MzqHI1izkSWsdycz3LE6qM4qhX4f7wZ + 4Ymzu2jbSq43IavCjGPOLIKVJ4nlnPd7rcprYNV5DOcGAkXG5x7PbnVta3SPI300 + CXnSGQB1KHUCCYZN1BkL9ZSQyTx0ex19mnsSEtZh8NB97cCZx9zMowdHKd5ySu/O + +CMFkQ6Uoh2FxBtqM1y1YbDiuDJnAlAQSKlDIVdCdMssutWRs9Nf6eiLtcmb4U5l + sNyKQnPrr3vjkaTbVdBKQjjMSa8Z/1Tf95GxNhzrUGm2APLKVYdHkMVlQwcr/ZfH + jGiZqxgBmrtNe3EypdKCDnlPvlxs8mnO5whxzDZW2NFV3piMmOmvLI/Po1ASi/t1 + PW9h05Foh2764Jfp74BkRTvhBfi465wKkON0VOckwWBkl/n7w7POfHCXdK1/AnGj + 9ywj6P4zg50vKiTMkZStq6YKXAEkVcN6YzhVVDFwDwAE1VKFCMKlmwuYT1FuKXBp + 7maF578qVyb0lXP9jaX10Y9dhC4vU2rJB3vtRhxjqeMEe/WOyhEyalrC9phPfBKS + wVKzdd3vvaNGfQSAwseFAn1upvELFwccPw1aRIqqLhzWTY2m48yyW2aEN6+7SqkR + dOBJpZDE4NxOhbQl0rllZdeLUznIgeOKM2iNg/3kM7cWcsLZRm3+l1ZuiCEy5XPS + XgHbwfJlyZYoQyKCntbdA/5VRS/5s0oPJIjuofoBZb35fIqtYPIpUeNccpklXYsO + atiSRwJeiluCFUag0uV3nq0zltOlqdS6piEVqU6xiGLAZe04jkaMBxL6VQQHYU0= + =811X + -----END PGP MESSAGE----- + fp: F38C9D4228FC6F674E322D9C3326D914EB9B8F55 + - created_at: "2026-02-17T22:22:03Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA1Hthzn+T1OoAQ/9EvULxQSjfO/V600iqRhsQsuuHWY5IfVN+XBCmzmeUX2a + 8qFN8L5gk3pYEoIu4khSCSeIpVyOdX1XeWMMNB15C/pAvgi7emH0y8UxAvCLfW5L + CzP3qLQsbpKUGntPlHaye/G16M/+m4QPc6Y7qwEtUThOei9haPhIU06Tb61IpfLk + AKticUro4ap3Xt/fjDH0NHZsGG33V6LprTt+8LaEcpcwZK/yOWdG4wTV4j6X8LbA + ueCmKunAr1skJrd+hVuwP2e8UkasYgo33pcupsS5jcyXJT9Kf3p/nqOJ3QGlwOtP + lf0DUifdd/QrEXWcMBu+zc9HgtUzpyU3KAoVrxo4JQLaoRlq3kwk3mOOFA0Fzd16 + neuJL2wp/RPuL47StHwA9HxQP+3znXkNxmt9yXGzeyeOBpK4O9qoQ9y7Rbd/FR2u + wEl5uAjhhH2xmAUnIKp5Y1UAFSLqZEaiJjjCHMHycaTpCucjEcChpaBGDAXYS1h+ + x/r6R46UgIzMvjpd2vy+C1aQg0p1Z6P65ifOkdAYIghpSkp+F6SUHHkL3w/kRRjE + dBF8YWFm/yl9P9qenakC5NsAA+bR4ZpNWpv32sYuVjIuoV20GdS7UIVQnvos8bBK + NfqoFmz4n8Eo1jLRcCJ376ow7bSEhRIJlJxdq7bFjZ/3Wtk9vt9dG6XV7wLdJwXS + XgGRxjv94TYLFowYA8/uu9fWxvf2i2lLqctjrvbZkW0Rdn2Ym5GXjg6St3Diug6r + y87PJPSN7CYE4jzCDPaSnGcBvwDHrQsLHLAmenfrAi2Jnweg/THpm9UAftoC7AY= + =Fxot + -----END PGP MESSAGE----- + fp: 5DA93D5C9D7320E1BD3522C79C78172B3551C9FD + - created_at: "2026-02-17T22:22:03Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA46L6MuPqfJqARAAnZq75P7GPcuBCBLUOVPK8w1IBxd4XzoEWW3+T80bFTZE + ZjPAvfiGcOqIfc8CPzpS1drviWiRkuEV4EKCuDmX9GReI0SUlvaoiddUA9V62f4b + akBrzqR0nNnWWvjph4/5PRAQO+xO4wQy2r9thCw4oej3QgvKtLRRRY35TkGqlS0t + ej4d80KaqGGsfIPQ5L9f+lqarrKvYx3DMK6CujN13Kot44Uom4L5TeIdPSAW14jS + 13fa/I1Irq56ME9kNctsuAkRkhrW+KchFJqkYXSS82SbXUDDNcVA7knXSzxVR+iU + NJXb8bQO4Ymi8sWPWKHW/GXUkReiTLl8MkLi+mCwL7qo5fMQcBg/KWo0hReQYCj3 + G9DZPs3xWYFcwcmrSV86LSqjMt5g8ZKjPm6ODQcZVA/ZsGlmdTkjsWNn6WRZI55m + 8kkg7BoRMq7p6b15tW4e/w2rr/bTmGQ9dV03KIpmBG6+OUzwgfB2/w2dGmB7Vor6 + JMzvt+1I/PSHsCC/7GurTurAP63x8NO/9HYX2Qg0qzsOusnTKrCoo4lX/tA5YfIt + OKr6zqy8s5Dv/lGUhofkJrhHr/QTRHFVrFtPNn4yfSzo+8uhomHGsmxBGOOiY83L + 3zwYm+9BlzO/ve7PIvs54hIHQaKsP9Ktsgq/+dM7PVlIb5qfwGNvgoS2QXFqCF/S + XgHWy41J0zTGoyEpooGkheVKvgEPvv6YIlm9oTucYP03AkKWxBr9MTNq/+JcLRvw + Zey10uVJnYPUuH2b9f8N8lNBZlkQCBq/AEu0MsygsK8bcVfQL1Qs58xh1uA7gL8= + =wduB + -----END PGP MESSAGE----- + fp: 8996B62CBD159DCADD3B6DC08BB33A8ABCF7BC4A + - created_at: "2026-02-17T22:22:03Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DQrf1tCqiJxoSAQdA4Y8j9A4ECAds0oJlP50Td1HpYIhywjXKi+pT7CTPXQ8w + 95+hUucTE8WQO/9u4HV2Y2nuyQPwmaYK0iGbNV3YxgI3Zdtf1T680hQxT4y55E1/ + 0l4B+70h9ojiHZkpVKVmFFZdY+tS/jQIFIRxqTW1AAfDf+chO3sUxbRe2qZhOXoY + b/QKU11wFpmOZmzznurOoxkqdNgGNcFm9+Ntb4ZSLSYzx7wrjzmWsaTdFd+coO1j + =V+rP + -----END PGP MESSAGE----- + fp: B71138A6A8964A3C3B8899857B4F70C356765BAB + unencrypted_suffix: _unencrypted + version: 3.8.1 diff --git a/config/hosts/woodpecker/sops.nix b/config/hosts/woodpecker/sops.nix new file mode 100644 index 0000000..b4548ed --- /dev/null +++ b/config/hosts/woodpecker/sops.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + sops = { + defaultSopsFile = ./secrets.yaml; + }; +} diff --git a/config/hosts/woodpecker/woodpecker-agent/default.nix b/config/hosts/woodpecker/woodpecker-agent/default.nix new file mode 100644 index 0000000..279d2bb --- /dev/null +++ b/config/hosts/woodpecker/woodpecker-agent/default.nix @@ -0,0 +1,8 @@ +{ config, pkgs, ... }: + +{ + imports = [ + ./docker.nix + ./woodpecker-agent.nix + ]; +} diff --git a/config/hosts/woodpecker/woodpecker-agent/docker.nix b/config/hosts/woodpecker/woodpecker-agent/docker.nix new file mode 100644 index 0000000..af13f4c --- /dev/null +++ b/config/hosts/woodpecker/woodpecker-agent/docker.nix @@ -0,0 +1,12 @@ +# Sources for this configuration: +# - https://woodpecker-ci.org/docs/administration/deployment/nixos +# - https://woodpecker-ci.org/docs/administration/backends/docker +# - https://nixos.wiki/wiki/Docker + +{ config, pkgs, ... }: + +{ + virtualisation.docker = { + enable = true; + }; +} diff --git a/config/hosts/woodpecker/woodpecker-agent/woodpecker-agent.nix b/config/hosts/woodpecker/woodpecker-agent/woodpecker-agent.nix new file mode 100644 index 0000000..8c6847b --- /dev/null +++ b/config/hosts/woodpecker/woodpecker-agent/woodpecker-agent.nix @@ -0,0 +1,29 @@ +# Sources for this configuration: +# - https://woodpecker-ci.org/docs/administration/deployment/nixos +# - https://woodpecker-ci.org/docs/administration/agent-config +# - https://woodpecker-ci.org/docs/administration/backends/docker + +{ config, pkgs, ... }: + +{ + services.woodpecker-agents.agents."docker" = { + enable = true; + package = pkgs.woodpecker-agent; + extraGroups = [ "docker" ]; + environment = { + WOODPECKER_SERVER = "localhost${config.services.woodpecker-server.environment.WOODPECKER_GRPC_ADDR}"; + WOODPECKER_MAX_WORKFLOWS = "4"; + WOODPECKER_BACKEND = "docker"; + # Set via enviornmentFile: + # WOODPECKER_AGENT_SECRET + }; + environmentFile = [ "/run/secrets/woodpecker_agent_environment_file" ]; + }; + + sops.secrets."woodpecker_agent_environment_file" = { + mode = "0440"; + owner = "root"; + group = "root"; + restartUnits = [ "woodpecker-agent-docker.service" ]; + }; +} diff --git a/config/hosts/public-reverse-proxy/default.nix b/config/hosts/woodpecker/woodpecker-server/default.nix similarity index 56% rename from config/hosts/public-reverse-proxy/default.nix rename to config/hosts/woodpecker/woodpecker-server/default.nix index 20dd895..a713746 100644 --- a/config/hosts/public-reverse-proxy/default.nix +++ b/config/hosts/woodpecker/woodpecker-server/default.nix @@ -2,7 +2,8 @@ { imports = [ - ./configuration.nix ./nginx.nix + ./postgresql.nix + ./woodpecker-server.nix ]; } diff --git a/config/hosts/netbox/nginx.nix b/config/hosts/woodpecker/woodpecker-server/nginx.nix similarity index 55% rename from config/hosts/netbox/nginx.nix rename to config/hosts/woodpecker/woodpecker-server/nginx.nix index 2673cdc..962183c 100644 --- a/config/hosts/netbox/nginx.nix +++ b/config/hosts/woodpecker/woodpecker-server/nginx.nix @@ -1,21 +1,17 @@ # Sources for this configuration: -# - https://nixos.org/manual/nixos/stable/#module-security-acme -# - https://git.grzb.de/yuri/nix-infra/-/blob/33f2d9e324c2e3a8b1b41c20bce239001bcce9fc/hosts/netbox/nginx.nix -# - https://docs.netbox.dev/en/stable/installation/5-http-server/ -# - https://github.com/netbox-community/netbox/blob/v3.5.9/contrib/nginx.conf +# - https://woodpecker-ci.org/docs/administration/deployment/nixos +# - https://woodpecker-ci.org/docs/administration/proxy { config, pkgs, ... }: { services.nginx = { enable = true; - # So nginx can access the Netbox static files. - user = "netbox"; - virtualHosts."acme-netbox.hamburg.ccc.de" = { + virtualHosts."acme-woodpecker.hamburg.ccc.de" = { default = true; enableACME = true; - serverName = "netbox.hamburg.ccc.de"; + serverName = "woodpecker.hamburg.ccc.de"; listen = [ { @@ -25,10 +21,10 @@ ]; }; - virtualHosts."netbox.hamburg.ccc.de" = { + virtualHosts."woodpecker.hamburg.ccc.de" = { default = true; forceSSL = true; - useACMEHost = "netbox.hamburg.ccc.de"; + useACMEHost = "woodpecker.hamburg.ccc.de"; listen = [ { @@ -39,12 +35,8 @@ } ]; - locations."/static/" = { - alias = "${config.services.netbox.dataDir}/static/"; - }; - locations."/" = { - proxyPass = "http://${config.services.netbox.listenAddress}:${builtins.toString config.services.netbox.port}"; + proxyPass = "http://localhost${config.services.woodpecker-server.environment.WOODPECKER_SERVER_ADDR}"; }; extraConfig = '' @@ -56,8 +48,6 @@ # Then tell the realip_module to get the addreses from the proxy protocol # header. real_ip_header proxy_protocol; - - client_max_body_size 25m; ''; }; }; diff --git a/config/hosts/woodpecker/woodpecker-server/postgresql.nix b/config/hosts/woodpecker/woodpecker-server/postgresql.nix new file mode 100644 index 0000000..e715650 --- /dev/null +++ b/config/hosts/woodpecker/woodpecker-server/postgresql.nix @@ -0,0 +1,18 @@ +# Sources for this configuration: +# - https://github.com/NixOS/nixpkgs/blob/dce84c46d780b20c064d5dfb10d0686e0584a198/nixos/modules/services/web-apps/nextcloud.nix#L1069 + +{ config, pkgs, ... }: + +{ + services.postgresql = { + enable = true; + package = pkgs.postgresql_15; + ensureDatabases = [ "woodpecker-server" ]; + ensureUsers = [ + { + name = "woodpecker-server"; + ensureDBOwnership = true; + } + ]; + }; +} diff --git a/config/hosts/woodpecker/woodpecker-server/woodpecker-server.nix b/config/hosts/woodpecker/woodpecker-server/woodpecker-server.nix new file mode 100644 index 0000000..1836b73 --- /dev/null +++ b/config/hosts/woodpecker/woodpecker-server/woodpecker-server.nix @@ -0,0 +1,44 @@ +# Sources for this configuration: +# - https://woodpecker-ci.org/docs/administration/deployment/nixos +# - https://woodpecker-ci.org/docs/administration/server-config +# - https://woodpecker-ci.org/docs/administration/database +# - https://woodpecker-ci.org/docs/administration/forges/forgejo +# - https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING + +{ config, pkgs, ... }: + +{ + services.woodpecker-server = { + enable = true; + package = pkgs.woodpecker-server; + environment = { + WOODPECKER_HOST = "https://woodpecker.hamburg.ccc.de"; + WOODPECKER_SERVER_ADDR = ":8001"; + WOODPECKER_GRPC_ADDR = ":9000"; + WOODPECKER_ADMIN = "june"; + WOODPECKER_OPEN = "true"; + WOODPECKER_ORGS = "CCCHH"; + WOODPECKER_DATABASE_DRIVER = "postgres"; + WOODPECKER_DATABASE_DATASOURCE = "postgresql://woodpecker-server@/woodpecker-server?host=/run/postgresql"; + WOODPECKER_FORGEJO = "true"; + WOODPECKER_FORGEJO_URL = "https://git.hamburg.ccc.de"; + WOODPECKER_LIMIT_MEM = "6442450944"; # 6GB + # Set via enviornmentFile: + # WOODPECKER_FORGEJO_CLIENT + # WOODPECKER_FORGEJO_SECRET + }; + environmentFile = [ "/run/secrets/woodpecker_server_environment_file" ]; + }; + + systemd.services.woodpecker-server.serviceConfig = { + User = "woodpecker-server"; + Group = "woodpecker-server"; + }; + + sops.secrets."woodpecker_server_environment_file" = { + mode = "0440"; + owner = "root"; + group = "root"; + restartUnits = [ "woodpecker-server.service" ]; + }; +} diff --git a/config/hosts/yate/configuration.nix b/config/hosts/yate/configuration.nix new file mode 100644 index 0000000..6b1fa99 --- /dev/null +++ b/config/hosts/yate/configuration.nix @@ -0,0 +1,10 @@ +{ ... }: + +{ + networking = { + hostName = "yate"; + domain = "z9.ccchh.net"; + }; + + system.stateVersion = "23.11"; +} diff --git a/config/hosts/yate/default.nix b/config/hosts/yate/default.nix new file mode 100644 index 0000000..66738e8 --- /dev/null +++ b/config/hosts/yate/default.nix @@ -0,0 +1,10 @@ +{ ... }: + +{ + imports = [ + ./configuration.nix + ./networking.nix + ./yate.nix + ./sops.nix + ]; +} diff --git a/config/hosts/yate/networking.nix b/config/hosts/yate/networking.nix new file mode 100644 index 0000000..a06a019 --- /dev/null +++ b/config/hosts/yate/networking.nix @@ -0,0 +1,23 @@ +{ ... }: + +{ + networking = { + interfaces.net0 = { + ipv4.addresses = [ + { + address = "10.31.208.12"; + prefixLength = 23; + } + ]; + }; + defaultGateway = "10.31.208.1"; + nameservers = [ + "10.31.210.1" + ]; + }; + + systemd.network.links."10-net0" = { + matchConfig.MACAddress = "BC:24:11:73:3E:F7"; + linkConfig.Name = "net0"; + }; +} diff --git a/config/hosts/yate/secrets.yaml b/config/hosts/yate/secrets.yaml new file mode 100644 index 0000000..d3cb216 --- /dev/null +++ b/config/hosts/yate/secrets.yaml @@ -0,0 +1,148 @@ +git_clone_key: ENC[AES256_GCM,data:Wss8NtyYXOmQ8fYbqKfbGQ+5l+ifNznis9OJ4p2HRPsExOFvgHH60t+D/gsOPTiwL0fEQKQn008Zo7VpIEhKIQM0fW3cd3ED3Tk8QX4hDRxyLl/lql5MlhTm4UMY58rNMBXgA88oR1lozgAa39KMH0MRUoSzrhvecwnAHO+RjZGXBN5zYIorqBVEk5h+1wUGSlV1TroZX9u0cWt11eH59AgKY/oP5mOrgA++E623Oc/DnTxlLbR//lFHW1JPiBSUFMP1ck6fg4PwnADYITgr1B1zdJz1J6jNC+n6S9bKDPnH5bvqmpvJIRmimxR4/R182RkIC+TBhD850cD1y9KSZa0Lh3DZ3LPrqGtZ6MHvpCgY/wPiTUANv6CJPcOAoskaaW57EiFl0ev3Jc3A+XFM6yqQOmmvNXx0hYz6ltlvtsltOcmz5TWooijwTaPS5UEwltYalrT9RNmC/ODkBRkSvuLEBWYwnu8aeo2f/+IxciG0PldDJED2ud6HSkDEXHcPCwodScpnk032Jrc+0qtI,iv:tCo4f5u/y/ZrAfT1N+eUNLy5pKAg/U0xa3cNQmzUgFs=,tag:03HK65hWjYnVzz+7C+HmsA==,type:str] +sops: + age: + - recipient: age19h7xtfmt3py3ydgl8d8fgh8uakxqxjr74flrxev3pgmvvx94kvtq5d932d + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTeklHTk8wRXZUWDE2bHdV + LzJSVkJMMStpMmlud1VZWjVLUVdLejNXWDFNClM2UjhMaWl5cmxjRHdpakowV2hZ + aVVxMUtoSmdJU2p0MzZORC9XV2U4QTgKLS0tIEM0RUhRTTFBcjNsOVR2Q1A3bEFE + cWNJR1kyQkVMbElBdTkvQlkwWk8yTDgKK8XqGA2Gy7b7dIS4Zas/t8aK8d2qCx5p + cDHyRqqAfMIn9fRmiRGL0VRXCTZcPZ8FcaDx5/CuOgxe4hvNXp9U3Q== + -----END AGE ENCRYPTED FILE----- + - recipient: age1kxzl00cfa5v926cvtcp0l3fncwh6fgmk8jvpf4swkl4vh3hv9e5qyqsrnt + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtd1ZQNytmcTQ0bC8xMlAz + QXlibmhQZGNQQnV3QktoVGtxOHA1eEtnaHdzCnRiMVl0Nll1V2ZibWdkTnBoYnFq + ZXNqUHI3eXMwYkZvZkVEVm1Ld3RFdkkKLS0tIEx5RVc5WGEvdlhUcHVQMXdXcUhS + Y2t3K3Vhckp4VnBwOHQwVjVpYjkxU1kKuvtNN9eHFvBBjZmh/L5yxeU6rRtz7KMy + q/5pLyRVAg/LjXKnFH9SZLbvWyffpfG7U8CUQdBmVIzYhrj/WEKwcQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-09-08T18:35:07Z" + mac: ENC[AES256_GCM,data:tyrfhBaTKnp1lqSPfkErk1UFoI7v/1az+zl9g3XoZ5Apo3CRixdLUldM9sYXqQT5WNrgO2NyZHqvyQOnFZiJuNhlYFSQbgwFFm3gz45BV8Do7QAhAG7+Q6q/Gz9VAqePQJlmzbfeL5iqJC2jhrcGIutO2cI22QULLkBzVVDg1/w=,iv:ayLonGC1F3vp6bh4pcAps6BvMzrG/yT2rPGAcUQ1Geg=,tag:1fIaRIFrzDTSP+oIUHABgQ==,type:str] + pgp: + - created_at: "2026-02-17T22:22:04Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAz5uSgHG2iMJARAAg1t+aqAh+rbcjhyNZha1ovJbcM6FoNr55nmdFZQnqwi5 + sCIct2zE/lQzz770bbkplJaEAM2mQnPEGYJ6hQApF4M8x4HKVWaA68qM/dP2ZQQs + oXysCouuUvypfU+EeZhN6Lke8PapFls+iLidcb8fFh+FHAEe3qOKHfwFamjkxz0T + N7/hCInKHFNeOOq9QpH+2dtpo3+wL0ImwSO/hfnhLc8f9eCgXYQZEArT9mhm4eFp + AWkkN34dZJcRa/n0NcZhMWhEDgepXO86h3vuXSfGRzuj3QEChSgm1paVOv5IWtCP + e9H66PcpBC0v8lnf6sk3uwTORH09rAuSDgEFcFHzdfZAL6c2O0oleMTVXDEQ23Ci + 8/X6N/qZjIJNBQogcRSCQijaYgSeUuMStvizzOK6hRKS/DSMK6Zbw2eM5SHXen0h + GVf8XvenfZF0U4MvzTDYzYnDh/1HA7NvfhRcvHo4TjkCyzuekGaE8WC1JtWA3DQD + IQf2q/7p6Qka+duMeirJcM+c71c7so6EDrlbFPI6A15F/vqtD4VyfmwLJm2YZZ4S + DfKKJHIQDzXh0bqiyNtAQyyo1H9UhJehXOod70Nz6EZkYz3F67Xo2fO/5mCrkRJH + tJEbSz43IHaT1AkB80mEy59+WCrT02mpuwsdsoLvhLokiCNFPHUR/YaWqjwJ5Y7S + XAGF4ku196vpnW9Ce+9rYE1UZ/Uh9xHBqPdc3tnufhKIwAE0UyF+fqFY89iwcMrb + WLcN+Pt7KhWIe2lJ3R8jKbzceTLIpxoHUtXGLutu8XM7tWN/obE61a9iWSTK + =s5xj + -----END PGP MESSAGE----- + fp: 18DFCE01456DAB52EA38A6584EDC64F35FA1D6A5 + - created_at: "2026-02-17T22:22:04Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAw5vwmoEJHQ1ARAApGc0RVQyE+NzUrw0yVctMi53dHT0fSC48WhVFuX77r97 + oLcw2/gzVhOGXHfuyPgkis16QBcMaHX4BNfrTonk6sXC/WOPBsRCAZ/h2YazK3Nt + fv/Ve8oNC2kDmCOIn4RwmXVS+QXPp9pgZA2b9wuAlU0SLbYq+t0lgCTZZb3lfL8m + DM5Y1xbXrwGNEqjkxEdU1Secd0oUgTWVwZlmjhnH+1e5tZe5sDLkUP28XBQB0b1j + BgV6dEERl0lxgTPYlcC0LHI+gD7gG3rmzMudJJBZzVomQK/VfKWqV7UuaT4x+ejQ + tVbkGZcjOAmb8A4xXQwkRgCBBS8CmiRGhx/BwJlabEMHW1QBOJB9+PYWD78rgiyY + CdjX4xFE80Wpdh8PDZXAe93m/4DlGKntLR5GVtZrk9VHuDL1CAc40tJkCuvl3Nig + bwapAGdGQnRRLMg0mPLI/isc7PmmBs2M+3m38mhdqjttbFpBrvD6wFPmhWmOw0YR + fiI7QOMOcihoX937S6jVTrUGVLFtR9Esl5LadYQp93le3GjZw6uiANepIwkeaX81 + ZanuDJGJXhvtgLfBByxWiuJxKRkZ1jyOVcbq9BEv/FjgFbxPEKq8vevuEAcSoM0K + PyRrav59UciQ6BUGy8jM7caIu9hZhon9BZA3bWFekXAjWWyfL/2SkIkjyo+B0hvS + XAGvaOrp3aF7mF6XyyxxNC7IjVifnlElFzv594o2fPQdRKGfcLIETADMUaMskrD5 + RSEe4ldP8KQOlmKn2yG/fhQw04D+RdhatWIfszGjQwo84g4SIBOzI8Ut8fsd + =W/jm + -----END PGP MESSAGE----- + fp: 87AB00D45D37C9E9167B5A5A333448678B60E505 + - created_at: "2026-02-17T22:22:04Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DerEtaFuTeewSAQdAUr63BpqUMMezyhp+cq1nWfUixaQPB2XZm2ZM6/OfHi4w + 583JukURVqiCDGyMmuMvx1c+7txy3BImR+ZcX54CyLi41pAJYM+t0GCYUX+N1iUh + 0lwBGLwkDC83Go28mRIVf2VJex6MaW9F6scWat/FDn8QLzsL/MpWpTTbOvCM9eF3 + p1MMmqV2s4NkdGaXKhMWoc84CQZgEfvNyzmObPSj558ZIcvdmuu+gxBbm2jJUg== + =pwG7 + -----END PGP MESSAGE----- + fp: 057870A2C72CD82566A3EC983695F4FCBCAE4912 + - created_at: "2026-02-17T22:22:04Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAxjNhCKPP69fAQ//UrQNdx+LIIf+GLfmG5wCjpa2CSBPRta1AT6JUFSaImwm + d0qDFyTSf96SqnyPFh2GlHuR/s2OZjF92a6EJidq8FDGJWCwlhJIDOD5B5veCPsF + kGB8CqXod7ZD1z19p1h5WiWdSLxYoseDEsnb2SDeONaZjOklNgpWT3dhTjVD2ca0 + 92pp3xHfMHNOMyTzC9f2cLPdfUr7/2sHk5h84wH+4IOoXyACQmbCDQjrDg0FoxUh + KR3Tc4oxrAEhSkipuFjqZceihLx9tb2peZmBUMzLh/N71hAQ6aNav3EIBEKcyy3k + W7M9BS3yX6pBD1FWDdp0l7YlJTNXPDRF/c9Q5CgR7S7Td6/zL/Mm0k6Va6kvjBN8 + slRTiqsjT/W6h6scnihFEcPTKUdmZKx2f/Hj5EE+cM6WfULeIAawJxoWBOoSi6cq + RdlJzpkCqridarADKMy226Isj9QH1qmspL5HIJQ/lBHO7lRx17MvB2JkojYsHxix + LiEEQUdAkmVmV0APLNV4Uh9fkyi9FfDgtzhKBmF/4Hue2ZUCQcsuTzzy2TyF2YZi + pYLJ8dlsSUFIr1ZmzDzf/x/v87GLJuuHjOGVPiA26ipIeR8w3u0yFjf2EFQd7KXm + 3viDYhGBdVfntgfJL5o5VVGeIv95x0ZXlyi2/6r1NL+KZJhiZ4drE5DfrQ9Z6BrS + XAEhAjt4mAGphYPQnygGYxrcGDW18akLE2BXjqnQZlxyt5I3cqubSciz85mlcvXJ + KLaxFI/A8jl+eDlNqhrNvR5E8vPOBi1253IDHLMzsYtAgZ51A3UPN6BBCmSL + =+sro + -----END PGP MESSAGE----- + fp: F38C9D4228FC6F674E322D9C3326D914EB9B8F55 + - created_at: "2026-02-17T22:22:04Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA1Hthzn+T1OoAQ//V5CtyaEMACLYe8t4AWFkPOfKnZ6nLDSzYc+AgDdzk0Nn + 8EK6KOT+m0d65Sbqg1D2U+n1/8dyqFB0cnUmSUZzL5iYfQF/Zry2sqncmX5dO4ne + k8ZSc+s1QL7ed5fq0MykOPhopxwF8UWHRMTggPXm1JZ1+QrNXrGveaZq4IS0hjbj + k2TgvFd1svf/xqlWN31wdIuNVtpMaI01gTW0XX4ECVOc7gJz9xTJtzB6imBb3yHN + cRB60rhtbeIx24wJ9yro9HWEaOLaqXyMWFCrH0J4pXFvtKa3iPxZCJpE3YNUnX48 + pGE6ZUleHhAagsDZMabwqsfLZdmJCc+C8fJEIhC+uBS9vtmALGUeKxnkvWbfPAVP + sj6QbVmiyVnK/X4wNguMK+AdTGElvu5yB2ejypD/kCKI1RbVPXqTYS/gY0Vm+OKL + kYKuz7gC72O72pC577usHYeUkptqjYIKD66+N0OkqymkLmdTFsISqmVodmp4WD1I + r1gDGFt2BkHziG2FbnUbYv187q87yvHf61f+P0NWcPV3XnGvd2eHURPhhrhQtOzl + DaPwoTZ4EY042mIC4PoScxs39eSBSFYeO5lXyh+5Vvtcb0lt6aLmXWNkVbq+JEft + tLt9WnBGcdF/gbMWMG+OnFPnzt9YH9ydOXFoP//TbmubNV6rUCd99aKLcPdg7LrS + XAHR9cSMAaq74ZebTw/gt3oBD4Yewwpnna0X8i9xy6VGJz2ja/hWI+gYdlsvyNT4 + bwbmdFbgJtV9NtMP7c5CxlOBbwjmqpy9/syjgieNfMVI7BMbkVm4Tp9P/X87 + =+JD1 + -----END PGP MESSAGE----- + fp: 5DA93D5C9D7320E1BD3522C79C78172B3551C9FD + - created_at: "2026-02-17T22:22:04Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA46L6MuPqfJqAQ//Y35T5AgDswhpSVOMPoAToapHzH9rZan5nzqDhfJrVe/A + xxCHoJY1YTRKjG9cAtmYm22oJqWZqmoXUS43KW0jzwNcfKBE06u+3VjVgnkkn+Q9 + ceDUycbqbYsiwBdiYC/2mKjgg4xvbz55ZmOLvjLljlcNXQOHb9XO0ggqX2t50GEh + 4RaieL7d8/MwgC9RLz2i+K6Bqf+W4kjGtBiQF7D4cI+mZbguCZ5AptMKXCFBHQrV + Lu+WKzPTVFmpRnnK0nIrlHa9WV7h5gYnu+qK4O7Jgs8HYiNOtLQJMhuUnos+psDG + y9GzHU7VoGAqYth9Nn8IQE2bdQOde+bTTaPxvLA3coCqTNjw12FyPQ7cppWwn+iK + NuTxdDPj2GIRd32nBONbpFpjdFv0FINOXKJB2HnbjiHz1vBT2sL530TuTuDl4G6n + 3vz0rRb1lOZHiSPNsinz/hkSEQMfwV6AhC/AW/Y6Zsoh89WJMCBSlyc6VmHBHq+y + r0ZWfbGjBciPXbDA2SXgrGN01txTkps4NP6rxaLIgJZpPtmYNhe1JCMvMJcLvVNe + wtChGFj2Hyn6eDkh/JKkvw0RZ9ktWUY448+DYuOpO+KtkO9kQZw0853opVivcmHT + CF/GWzcoSP18HIaCvYmdNyvsQDPgs5g9m5nXp+3AK6oUwmPAbUp4lR81CpxWFh/S + XAErwhIXCJFhsS2C47V4kjy/5wGi6LrcquNGTtYxbVIRzZv+LyCSXNeRHbxlbniD + fUD0Rjr6EDxEe9Apsz01Ko92GRxs3ihRtUBwyNHqJxX6nqX2icpDsEsY8U5o + =t63I + -----END PGP MESSAGE----- + fp: 8996B62CBD159DCADD3B6DC08BB33A8ABCF7BC4A + - created_at: "2026-02-17T22:22:04Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DQrf1tCqiJxoSAQdAU9KcQp4hcBjhmB52+zjDjkNyrzF+vj4B+yWYAwj6dnIw + xp2nTCQJHck8AJgvQbnm79kMvDjWmZ+BKga5Djudq9y0h8pedsWA7F3SC/Pd2bsA + 0lwBmJgvzUo9+lkCVVByyfPOPYgvd3SYFFTvLrYLiuHsoYLsLBKMtURqeDwSGCRJ + eqbE5Ebio0ag+tKKKLtfnvfTZKuyB7kDOu0hdbhQ6+bNHL+Q76c++z1zZl5MTA== + =5Gin + -----END PGP MESSAGE----- + fp: B71138A6A8964A3C3B8899857B4F70C356765BAB + unencrypted_suffix: _unencrypted + version: 3.9.0 diff --git a/config/hosts/yate/sops.nix b/config/hosts/yate/sops.nix new file mode 100644 index 0000000..38b06f9 --- /dev/null +++ b/config/hosts/yate/sops.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + sops = { + defaultSopsFile = ./secrets.yaml; + }; +} \ No newline at end of file diff --git a/config/hosts/yate/yate.nix b/config/hosts/yate/yate.nix new file mode 100644 index 0000000..236e1f0 --- /dev/null +++ b/config/hosts/yate/yate.nix @@ -0,0 +1,78 @@ +{ pkgs, ... }: + +{ + environment.systemPackages = [ + pkgs.yate + pkgs.git + pkgs.tcpdump + pkgs.tmux + ]; + + # Just disable it for now. + networking.firewall.enable = false; + + users = { + users.yate = { + description = "yate service user"; + group = "yate-config"; + isNormalUser = true; + }; + + groups.yate-config = { + members = [ "colmema-deploy" "chaos" "root" "yate"]; + }; + }; + + environment.etc.yate = { + user = "yate"; + group = "yate-config"; + mode = "symlink"; + source = "/var/lib/yate"; + }; + + sops.secrets."git_clone_key" = { + mode = "0600"; + owner = "yate"; + group = "yate-config"; + restartUnits = [ "yate.service" ]; + }; + + systemd.services.yate = { + enable = true; + description = "Yate telehony engine"; + unitConfig = { + After= "network-online.target"; + }; + serviceConfig = { + ExecStart = "${pkgs.yate}/bin/yate -c /etc/yate -e /etc/yate/share"; + Type="simple"; + Restart="always"; + User="yate"; + Group="yate-config"; + StateDirectory = "yate"; + StateDirectoryMode = "0775"; + }; + wantedBy = [ "default.target" ]; + requires = [ "network-online.target" ]; + preStart = '' + echo "\n" >> /run/secrets/git_clone_key + sleep 5 + id + echo "$(stat -c '%U' /var/lib/yate/.git) owns /var/lib/yate/.git" + SSH_SUCCESS=1 + ${pkgs.openssh}/bin/ssh -q -i /run/secrets/git_clone_key forgejo@git.hamburg.ccc.de 2> /var/lib/yate/SSH_CHECK_LOG || SSH_SUCCESS=0 + if [[ $SSH_SUCCESS = 1 && $(stat -c '%U' /var/lib/yate/.git) == *yate* ]]; then + rm -rf /var/lib/yate/* + rm -rf /var/lib/yate/.* + env GIT_SSH_COMMAND="${pkgs.openssh}/bin/ssh -i /run/secrets/git_clone_key" ${pkgs.git}/bin/git clone forgejo@git.hamburg.ccc.de:CCCHH/yate-config.git /var/lib/yate + ${pkgs.git}/bin/git -C /var/lib/yate config --add safe.directory "/var/lib/yate" + fi + ''; + reload= '' + id + ${pkgs.git}/bin/git config --global --add safe.directory /var/lib/yate + /usr/bin/env GIT_SSH_COMMAND="${pkgs.openssh}/bin/ssh -i /run/secrets/git_clone_key" ${pkgs.git}/bin/git -C /var/lib/yate fetch --all + /usr/bin/env GIT_SSH_COMMAND="${pkgs.openssh}/bin/ssh -i /run/secrets/git_clone_key" ${pkgs.git}/bin/git -C /var/lib/yate reset --hard origin/master + ''; + }; +} diff --git a/deployment_configuration.json b/deployment_configuration.json new file mode 100644 index 0000000..3ae44cc --- /dev/null +++ b/deployment_configuration.json @@ -0,0 +1,25 @@ +{ + "default": { + "targetUser": "colmena-deploy" + }, + "hosts": { + "matrix": { + "targetHostname": "matrix-intern.hamburg.ccc.de" + }, + "public-web-static": { + "targetHostname": "public-web-static-intern.hamburg.ccc.de" + }, + "git": { + "targetHostname": "git.hamburg.ccc.de" + }, + "forgejo-actions-runner": { + "targetHostname": "forgejo-actions-runner-intern.hamburg.ccc.de" + }, + "woodpecker": { + "targetHostname": "woodpecker-intern.hamburg.ccc.de" + }, + "penpot": { + "targetHostname": "penpot-intern.hamburg.ccc.de" + } + } +} diff --git a/flake.lock b/flake.lock index 50f72f6..3230d75 100644 --- a/flake.lock +++ b/flake.lock @@ -1,78 +1,80 @@ { "nodes": { - "nixlib": { + "authorizedKeysRepo": { + "flake": false, "locked": { - "lastModified": 1709426687, - "narHash": "sha256-jLBZmwXf0WYHzLkmEMq33bqhX55YtT5edvluFr0RcSA=", - "owner": "nix-community", - "repo": "nixpkgs.lib", - "rev": "7873d84a89ae6e4841528ff7f5697ddcb5bdfe6c", - "type": "github" + "lastModified": 1761076425, + "narHash": "sha256-EMUF17MVENJoX8bmxvWLB0TUPhFqlq0szXT0M7mkwWU=", + "ref": "trunk", + "rev": "7d9c3a683a50d109ed8fd3f75d090d5403967f7f", + "revCount": 20, + "type": "git", + "url": "https://git.hamburg.ccc.de/CCCHH/infrastructure-authorized-keys" }, "original": { - "owner": "nix-community", - "repo": "nixpkgs.lib", - "type": "github" - } - }, - "nixos-generators": { - "inputs": { - "nixlib": "nixlib", - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709887845, - "narHash": "sha256-803UIoB8+vGkm/VK/g55aBAAOf/ncTGvxXyjTF4ydm0=", - "owner": "nix-community", - "repo": "nixos-generators", - "rev": "bef32a05496d9480b02be586fa7827748b9e597b", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nixos-generators", - "type": "github" + "ref": "trunk", + "type": "git", + "url": "https://git.hamburg.ccc.de/CCCHH/infrastructure-authorized-keys" } }, "nixpkgs": { "locked": { - "lastModified": 1709953752, - "narHash": "sha256-LW84B4vM1cn7E6cDNQn2LndT9iJXI1dRE5fwbNFbQa8=", + "lastModified": 1768621446, + "narHash": "sha256-6YwHV1cjv6arXdF/PQc365h1j+Qje3Pydk501Rm4Q+4=", "owner": "nixos", "repo": "nixpkgs", - "rev": "fcaa81ed3c273237217330cf342ef1873b77c80a", + "rev": "72ac591e737060deab2b86d6952babd1f896d7c5", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-23.11-small", + "ref": "nixos-25.11", "repo": "nixpkgs", "type": "github" } }, "nixpkgs-unstable": { "locked": { - "lastModified": 1709987164, - "narHash": "sha256-W3KoCToX0gnwpZARkRteYd8Ns0Kie3C4u057YepUP5I=", + "lastModified": 1768661221, + "narHash": "sha256-MJwOjrIISfOpdI9x4C+5WFQXvHtOuj5mqLZ4TMEtk1M=", "owner": "nixos", "repo": "nixpkgs", - "rev": "e389a1133d14925b942e0ad76ce75f32637db20d", + "rev": "3327b113f2ef698d380df83fbccefad7e83d7769", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-unstable-small", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, "root": { "inputs": { - "nixos-generators": "nixos-generators", + "authorizedKeysRepo": "authorizedKeysRepo", "nixpkgs": "nixpkgs", - "nixpkgs-unstable": "nixpkgs-unstable" + "nixpkgs-unstable": "nixpkgs-unstable", + "sops-nix": "sops-nix" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1768709255, + "narHash": "sha256-aigyBfxI20FRtqajVMYXHtj5gHXENY2gLAXEhfJ8/WM=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "5e8fae80726b66e9fec023d21cd3b3e638597aa9", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" } } }, diff --git a/flake.nix b/flake.nix index 5360d1f..fe0cbdc 100644 --- a/flake.nix +++ b/flake.nix @@ -5,237 +5,218 @@ # Use the NixOS small channels for nixpkgs. # https://nixos.org/manual/nixos/stable/#sec-upgrading # https://github.com/NixOS/nixpkgs - nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11-small"; - nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable-small"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11"; + nixpkgs-unstable.url = "github:nixos/nixpkgs/nixpkgs-unstable"; - # Add nixos-generators as an input. - # See here: https://github.com/nix-community/nixos-generators#using-in-a-flake - nixos-generators = { - url = "github:nix-community/nixos-generators"; + # # Add nixos-generators as an input. + # # See here: https://github.com/nix-community/nixos-generators#using-in-a-flake + # nixos-generators = { + # url = "github:nix-community/nixos-generators"; + # #inputs.nixpkgs.follows = "nixpkgs"; + # }; + + # Add sops-nix as an input for secret management. + # See here: https://github.com/Mic92/sops-nix?tab=readme-ov-file#flakes-current-recommendation + sops-nix = { + url = "github:Mic92/sops-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; + + authorizedKeysRepo = { + url = "git+https://git.hamburg.ccc.de/CCCHH/infrastructure-authorized-keys?ref=trunk"; + flake = false; + }; }; - outputs = { nixpkgs, nixpkgs-unstable, nixos-generators, ... }: + outputs = { self, nixpkgs, nixpkgs-unstable, sops-nix, authorizedKeysRepo, ... }: let - # Shairport Sync 4.3.1 (with nqptp 1.2.4) with metadata, MQTT and AirPlay 2 support. - shairportSync431ExtendedNixpkgsUnstableOverlay = final: prev: { - shairport-sync = (prev.shairport-sync.override { enableMetadata = true; enableAirplay2 = true; }).overrideAttrs (finalAttr: previousAttr: { - # See: https://github.com/mikebrady/shairport-sync/blob/e78a88b64adfe7b5f88fd6faedf55c57445bb240/CONFIGURATION%20FLAGS.md - configureFlags = previousAttr.configureFlags ++ [ "--with-mqtt-client" ]; - buildInputs = previousAttr.buildInputs ++ [ final.mosquitto ]; - # Use specific Shairport Sync and nqptp versions, since with those the - # following error doesn't happen: - # fatal error: The nqptp service on this system, which is required for - # Shairport Sync to operate, does not seem to be initialised. - # - # Also use a more recent dev version to fix Pipewire stuttering issue. - # See: - # https://github.com/mikebrady/shairport-sync/issues/1736 - # https://github.com/mikebrady/shairport-sync/blob/a65ec2d7f1f380bbae196d7f8f1cd6a88ef5777b/RELEASENOTES-DEVELOPMENT.md#version-432-dev-51-g98679bbb - src = final.fetchFromGitHub { - owner = "mikebrady"; - repo = finalAttr.pname; - rev = "98679bbb54f5aaeda859e34aa28425647b8d179e"; - hash = "sha256-k0kcgtWk2xlG34lP0ryEaqdskYMNM68YnIRLwFR3jaY="; - }; - }); - nqptp = prev.nqptp.overrideAttrs (finalAttr: previousAttr: { - # See Shairport Sync version note. - src = final.fetchFromGitHub { - owner = "mikebrady"; - repo = finalAttr.pname; - rev = "1.2.4"; - hash = "sha256-roTNcr3v2kzE6vQ5plAVtlw1+2yJplltOYsGGibtoZo="; - }; - # Custom install phase to avoid setcap. - # See: - # https://github.com/mikebrady/nqptp/blob/1.2.4/Makefile.am#L23 - installPhase = '' - mkdir -p $out/bin - cp nqptp $out/bin/ - ''; - }); + specialArgs = { + inherit authorizedKeysRepo; }; - pkgs-unstable = nixpkgs-unstable.legacyPackages."x86_64-linux"; + system = "x86_64-linux"; + pkgs-unstable = nixpkgs-unstable.legacyPackages."${system}"; in { - colmena = { - meta = { - nixpkgs = nixpkgs.legacyPackages."x86_64-linux"; - nodeNixpkgs = { - audio-hauptraum-kueche = nixpkgs-unstable.legacyPackages."x86_64-linux".extend shairportSync431ExtendedNixpkgsUnstableOverlay; - audio-hauptraum-tafel = nixpkgs-unstable.legacyPackages."x86_64-linux".extend shairportSync431ExtendedNixpkgsUnstableOverlay; - }; - nodeSpecialArgs = { - git = { inherit pkgs-unstable; }; - }; + nixosModules = { + common = ./config/common; + proxmox-vm = ./config/proxmox-vm; + prometheus-exporter = ./config/extra/prometheus-exporter.nix; + }; + overlays = { + librespotFixOverlay = final: prev: { + librespot = (prev.librespot.override { withAvahi = true; }).overrideAttrs (finalAttrs: prevAttr: rec { + # Build dev branch. + name = "${prevAttr.pname}-${version}"; + version = "dev"; + src = prev.fetchFromGitHub { + owner = "librespot-org"; + repo = "librespot"; + rev = "dev"; + sha256 = "sha256-s9JpIbqXiVXMlhEuIuKio+rD1rM3kc7bAT0+8+5s35w="; + }; + cargoDeps = final.rustPlatform.fetchCargoVendor { + inherit src; + hash = "sha256-Lujz2revTAok9B0hzdl8NVQ5XMRY9ACJzoQHIkIgKMg="; + }; + # Fix librespot failing with "Unable to load audio item: Error { kind: Unavailable, error: StatusCode(500) }". + patches = (prevAttr.patches or []) ++ [ + ./patches/librespot_PR1528_conflicts_resolved.patch + ]; + }); }; - - audio-hauptraum-kueche = { - deployment = { - targetHost = "audio-hauptraum-kueche.z9.ccchh.net"; - targetPort = 22; - targetUser = "colmena-deploy"; - tags = [ "thinkcccluster" ]; - }; - imports = [ - ./config/common - ./config/proxmox-vm + }; + nixosConfigurations = { + audio-hauptraum-kueche = nixpkgs.lib.nixosSystem { + inherit system specialArgs; + modules = [ + self.nixosModules.common + self.nixosModules.proxmox-vm ./config/hosts/audio-hauptraum-kueche ]; }; - audio-hauptraum-tafel = { - deployment = { - targetHost = "audio-hauptraum-tafel.z9.ccchh.net"; - targetPort = 22; - targetUser = "colmena-deploy"; - tags = [ "thinkcccluster" ]; - }; - imports = [ - ./config/common - ./config/proxmox-vm + audio-hauptraum-tafel = nixpkgs.lib.nixosSystem { + inherit system specialArgs; + modules = [ + self.nixosModules.common + self.nixosModules.proxmox-vm ./config/hosts/audio-hauptraum-tafel + { nixpkgs.overlays = [ self.overlays.librespotFixOverlay ]; } ]; }; - esphome = { - deployment = { - targetHost = "esphome.z9.ccchh.net"; - targetPort = 22; - targetUser = "colmena-deploy"; - tags = [ "thinkcccluster" ]; - }; - imports = [ - ./config/common - ./config/proxmox-vm + esphome = nixpkgs.lib.nixosSystem { + inherit system specialArgs; + modules = [ + self.nixosModules.common + self.nixosModules.proxmox-vm ./config/hosts/esphome ]; }; - public-reverse-proxy = { - deployment = { - targetHost = "public-reverse-proxy.z9.ccchh.net"; - targetPort = 22; - targetUser = "colmena-deploy"; - tags = [ "thinkcccluster" ]; - }; - imports = [ - ./config/common - ./config/proxmox-vm - ./config/hosts/public-reverse-proxy - ]; - }; - - netbox = { - deployment = { - targetHost = "netbox-intern.hamburg.ccc.de"; - targetPort = 22; - targetUser = "colmena-deploy"; - tags = [ "chaosknoten" ]; - }; - imports = [ - ./config/common - ./config/proxmox-vm - ./config/hosts/netbox - ]; - }; - - matrix = { - deployment = { - targetHost = "matrix-intern.hamburg.ccc.de"; - targetPort = 22; - targetUser = "colmena-deploy"; - tags = [ "chaosknoten" ]; - }; - imports = [ - ./config/common - ./config/proxmox-vm + matrix = nixpkgs.lib.nixosSystem { + inherit system specialArgs; + modules = [ + self.nixosModules.common + self.nixosModules.proxmox-vm + sops-nix.nixosModules.sops + self.nixosModules.prometheus-exporter ./config/hosts/matrix ]; }; - public-web-static = { - deployment = { - targetHost = "public-web-static-intern.hamburg.ccc.de"; - targetPort = 22; - targetUser = "colmena-deploy"; - tags = [ "chaosknoten" ]; - }; - imports = [ - ./config/common - ./config/proxmox-vm + public-web-static = nixpkgs.lib.nixosSystem { + inherit system specialArgs; + modules = [ + self.nixosModules.common + self.nixosModules.proxmox-vm + sops-nix.nixosModules.sops + self.nixosModules.prometheus-exporter ./config/hosts/public-web-static ]; }; - git = { - deployment = { - targetHost = "git.hamburg.ccc.de"; - targetPort = 22; - targetUser = "colmena-deploy"; - tags = [ "chaosknoten" ]; - }; - imports = [ - ./config/common - ./config/proxmox-vm + git = nixpkgs.lib.nixosSystem { + inherit system specialArgs; + modules = [ + self.nixosModules.common + self.nixosModules.proxmox-vm + sops-nix.nixosModules.sops + self.nixosModules.prometheus-exporter ./config/hosts/git ]; }; - forgejo-actions-runner = { - deployment = { - targetHost = "forgejo-actions-runner-intern.hamburg.ccc.de"; - targetPort = 22; - targetUser = "colmena-deploy"; - tags = [ "chaosknoten" ]; - }; - imports = [ - ./config/common - ./config/proxmox-vm + forgejo-actions-runner = nixpkgs.lib.nixosSystem { + inherit system; + modules = [ + self.nixosModules.common + self.nixosModules.proxmox-vm + sops-nix.nixosModules.sops + self.nixosModules.prometheus-exporter ./config/hosts/forgejo-actions-runner ]; + specialArgs = { + inherit authorizedKeysRepo; + }; }; - ptouch-print-server = { - deployment = { - targetHost = "ptouch-print-server.z9.ccchh.net"; - targetPort = 22; - targetUser = "colmena-deploy"; - tags = [ "thinkcccluster" ]; - }; - imports = [ - ./config/common - ./config/proxmox-vm + ptouch-print-server = nixpkgs.lib.nixosSystem { + inherit system specialArgs; + modules = [ + self.nixosModules.common + self.nixosModules.proxmox-vm ./config/hosts/ptouch-print-server ]; }; - }; - packages.x86_64-linux = { - proxmox-nixos-template = nixos-generators.nixosGenerate { - system = "x86_64-linux"; + yate = nixpkgs.lib.nixosSystem { + inherit system specialArgs; modules = [ - ./config/nixos-generators/proxmox.nix - ./config/common - ./config/proxmox-vm + self.nixosModules.common + self.nixosModules.proxmox-vm + sops-nix.nixosModules.sops + ./config/hosts/yate ]; - format = "proxmox"; }; - proxmox-chaosknoten-nixos-template = nixos-generators.nixosGenerate { - system = "x86_64-linux"; + mqtt = nixpkgs.lib.nixosSystem { + inherit system specialArgs; modules = [ - ./config/nixos-generators/proxmox-chaosknoten.nix - ./config/proxmox-chaosknoten-additional-initial-config.nix - ./config/common - ./config/proxmox-vm + self.nixosModules.common + self.nixosModules.proxmox-vm + ./config/hosts/mqtt + ]; + }; + + woodpecker = nixpkgs.lib.nixosSystem { + inherit system specialArgs; + modules = [ + self.nixosModules.common + self.nixosModules.proxmox-vm + sops-nix.nixosModules.sops + self.nixosModules.prometheus-exporter + ./config/hosts/woodpecker + ]; + }; + + penpot = nixpkgs.lib.nixosSystem { + inherit system specialArgs; + modules = [ + self.nixosModules.common + self.nixosModules.proxmox-vm + sops-nix.nixosModules.sops + self.nixosModules.prometheus-exporter + ./config/hosts/penpot ]; - format = "proxmox"; }; }; + # packages.x86_64-linux = { + # proxmox-nixos-template = nixos-generators.nixosGenerate { + # inherit specialArgs; + # system = "x86_64-linux"; + # modules = [ + # ./config/nixos-generators/proxmox.nix + # self.nixosModules.common + # self.nixosModules.proxmox-vm + # ]; + # format = "proxmox"; + # }; + + # proxmox-chaosknoten-nixos-template = nixos-generators.nixosGenerate { + # inherit specialArgs; + # system = "x86_64-linux"; + # modules = [ + # ./config/nixos-generators/proxmox-chaosknoten.nix + # ./config/proxmox-chaosknoten-additional-initial-config.nix + # self.nixosModules.common + # self.nixosModules.proxmox-vm + # ]; + # format = "proxmox"; + # }; + # }; + formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixpkgs-fmt; }; } diff --git a/modules/services/audio/default.nix b/modules/services/audio/default.nix index 6e8a43b..f9aa6b3 100644 --- a/modules/services/audio/default.nix +++ b/modules/services/audio/default.nix @@ -11,7 +11,7 @@ in { imports = [ ./librespot.nix - ./networking.nix + ./mpd.nix ./pipewire.nix ./shairport-sync.nix ]; diff --git a/modules/services/audio/librespot.nix b/modules/services/audio/librespot.nix index fa4e9ed..3be5c86 100644 --- a/modules/services/audio/librespot.nix +++ b/modules/services/audio/librespot.nix @@ -19,11 +19,11 @@ in enable = true; description = "Spotify Connect Receiver Using librespot"; unitConfig = { - Requires = [ "network-online.target" "pipewire.service" ]; - After = [ "network-online.target" "pipewire.service" ]; + Requires = [ "network-online.target" "pipewire.service" "avahi-daemon.service" ]; + After = [ "network-online.target" "pipewire.service" "avahi-daemon.service" ]; }; serviceConfig = { - ExecStart = "${pkgs.librespot}/bin/librespot --name '${config.ccchh.services.audio.name}' --device-type speaker --bitrate 320 --enable-volume-normalisation --disable-audio-cache --disable-credential-cache --quiet"; + ExecStart = "${pkgs.librespot}/bin/librespot --name '${config.ccchh.services.audio.name}' --device-type speaker --bitrate 320 --enable-volume-normalisation --disable-audio-cache --disable-credential-cache --zeroconf-backend avahi"; User = "librespot"; Group = "librespot"; }; @@ -34,7 +34,7 @@ in users.librespot = { isSystemUser = true; group = "librespot"; - extraGroups = [ "pipewire" ]; + extraGroups = [ "pipewire" "audio" ]; }; groups.librespot = { }; }; diff --git a/modules/services/audio/mpd.nix b/modules/services/audio/mpd.nix new file mode 100644 index 0000000..048e979 --- /dev/null +++ b/modules/services/audio/mpd.nix @@ -0,0 +1,35 @@ +# Links & Resources: +# - https://mpd.readthedocs.io/en/stable/user.html + +{ config, pkgs, lib, ... }: + +with lib; + +let + + cfg = config.ccchh.services.audio; + +in + +{ + config = mkIf cfg.enable { + services.mpd = { + enable = true; + network.listenAddress = "any"; + extraConfig = '' + audio_output { + type "pipewire" + name "Pipewire" + mixer_type "software" + } + restore_paused "yes" + ''; + }; + + users.users.mpd.extraGroups = [ "pipewire" ]; + + networking.firewall = { + allowedTCPPorts = [ 6600 ]; + }; + }; +} diff --git a/modules/services/audio/networking.nix b/modules/services/audio/networking.nix deleted file mode 100644 index b0fbf22..0000000 --- a/modules/services/audio/networking.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ config, pkgs, lib, ... }: - -with lib; - -let - - cfg = config.ccchh.services.audio; - -in - -{ - config = mkIf cfg.enable { - # Disable IPv6, since Shairport-Sync doesn't work with IPv6. Unclear why. - networking.enableIPv6 = false; - }; -} diff --git a/modules/services/audio/shairport-sync.nix b/modules/services/audio/shairport-sync.nix index adf5911..43d1285 100644 --- a/modules/services/audio/shairport-sync.nix +++ b/modules/services/audio/shairport-sync.nix @@ -17,10 +17,11 @@ in config = mkIf cfg.enable { services.shairport-sync = { enable = true; - arguments = "-o pw"; + package = pkgs.shairport-sync-airplay2; + arguments = "-o pw -v"; }; - users.users.shairport.extraGroups = [ "pipewire" ]; + users.users.shairport.extraGroups = [ "pipewire" "audio" ]; environment.etc.shairport-sync-config = { enable = true; diff --git a/patches/librespot_PR1528_conflicts_resolved.patch b/patches/librespot_PR1528_conflicts_resolved.patch new file mode 100644 index 0000000..f97a38a --- /dev/null +++ b/patches/librespot_PR1528_conflicts_resolved.patch @@ -0,0 +1,223 @@ +From c4c968e594edcfce231682db5563f7186da7c6f0 Mon Sep 17 00:00:00 2001 +From: Timon de Groot +Date: Thu, 7 Aug 2025 12:22:56 +0200 +Subject: [PATCH 1/5] spclient: Specify base url for metadata requests + +This fixes #1527 +--- + core/src/spclient.rs | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/core/src/spclient.rs b/core/src/spclient.rs +index 87a6098..56c4287 100644 +--- a/core/src/spclient.rs ++++ b/core/src/spclient.rs +@@ -55,6 +55,7 @@ const CONNECTION_ID: HeaderName = HeaderName::from_static("x-spotify-connection- + const NO_METRICS_AND_SALT: RequestOptions = RequestOptions { + metrics: false, + salt: false, ++ base_url: None, + }; + + #[derive(Debug, Error)] +@@ -86,6 +87,7 @@ impl Default for RequestStrategy { + pub struct RequestOptions { + metrics: bool, + salt: bool, ++ base_url: Option, + } + + impl Default for RequestOptions { +@@ -93,6 +95,7 @@ impl Default for RequestOptions { + Self { + metrics: true, + salt: true, ++ base_url: None, + } + } + } +@@ -449,7 +452,10 @@ impl SpClient { + + // Reconnection logic: retrieve the endpoint every iteration, so we can try + // another access point when we are experiencing network issues (see below). +- let mut url = self.base_url().await?; ++ let mut url = match &options.base_url { ++ Some(base_url) => base_url.clone(), ++ None => self.base_url().await?, ++ }; + url.push_str(endpoint); + + // Add metrics. There is also an optional `partner` key with a value like +@@ -566,7 +572,12 @@ impl SpClient { + + pub async fn get_metadata(&self, scope: &str, id: &SpotifyId) -> SpClientResult { + let endpoint = format!("/metadata/4/{}/{}", scope, id.to_base16()?); +- self.request(&Method::GET, &endpoint, None, None).await ++ let options = RequestOptions { ++ base_url: Some(String::from("https://spclient.wg.spotify.com")), ++ ..Default::default() ++ }; ++ self.request_with_options(&Method::GET, &endpoint, None, None, &options) ++ .await + } + + pub async fn get_track_metadata(&self, track_id: &SpotifyId) -> SpClientResult { +-- +2.49.0 + + +From 2b72f3fbdf6519321feeaaecc1ea6e1bb042074e Mon Sep 17 00:00:00 2001 +From: Timon de Groot +Date: Thu, 7 Aug 2025 13:51:55 +0200 +Subject: [PATCH 2/5] spclient: Change RequestOptions to &str + +This will allocate less strings and makes it possible to have const +request option values. + +Also document why the metadata base url workaround is needed. +--- + core/src/spclient.rs | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/core/src/spclient.rs b/core/src/spclient.rs +index 56c4287..11bcef4 100644 +--- a/core/src/spclient.rs ++++ b/core/src/spclient.rs +@@ -87,7 +87,7 @@ impl Default for RequestStrategy { + pub struct RequestOptions { + metrics: bool, + salt: bool, +- base_url: Option, ++ base_url: Option<&'static str>, + } + + impl Default for RequestOptions { +@@ -453,7 +453,7 @@ impl SpClient { + // Reconnection logic: retrieve the endpoint every iteration, so we can try + // another access point when we are experiencing network issues (see below). + let mut url = match &options.base_url { +- Some(base_url) => base_url.clone(), ++ Some(base_url) => base_url.to_owned().to_string(), + None => self.base_url().await?, + }; + url.push_str(endpoint); +@@ -572,8 +572,11 @@ impl SpClient { + + pub async fn get_metadata(&self, scope: &str, id: &SpotifyId) -> SpClientResult { + let endpoint = format!("/metadata/4/{}/{}", scope, id.to_base16()?); ++ // For unknown reasons, metadata requests must now be sent through spclient.wg.spotify.com. ++ // Otherwise, the API will respond with 500 Internal Server Error responses. ++ // Context: https://github.com/librespot-org/librespot/issues/1527 + let options = RequestOptions { +- base_url: Some(String::from("https://spclient.wg.spotify.com")), ++ base_url: Some("https://spclient.wg.spotify.com"), + ..Default::default() + }; + self.request_with_options(&Method::GET, &endpoint, None, None, &options) +-- +2.49.0 + + +From 73ed5c50849bb660834cd0d7aaa7110c01397055 Mon Sep 17 00:00:00 2001 +From: Timon de Groot +Date: Sat, 9 Aug 2025 09:28:51 +0200 +Subject: [PATCH 3/5] spclient: Make const request options for get_metadata + +--- + core/src/spclient.rs | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/core/src/spclient.rs b/core/src/spclient.rs +index 11bcef4..cbcf092 100644 +--- a/core/src/spclient.rs ++++ b/core/src/spclient.rs +@@ -58,6 +58,12 @@ const NO_METRICS_AND_SALT: RequestOptions = RequestOptions { + base_url: None, + }; + ++const SPCLIENT_FALLBACK_ENDPOINT: RequestOptions = RequestOptions { ++ metrics: true, ++ salt: true, ++ base_url: Some("https://spclient.wg.spotify.com"), ++}; ++ + #[derive(Debug, Error)] + pub enum SpClientError { + #[error("missing attribute {0}")] +@@ -575,12 +581,14 @@ impl SpClient { + // For unknown reasons, metadata requests must now be sent through spclient.wg.spotify.com. + // Otherwise, the API will respond with 500 Internal Server Error responses. + // Context: https://github.com/librespot-org/librespot/issues/1527 +- let options = RequestOptions { +- base_url: Some("https://spclient.wg.spotify.com"), +- ..Default::default() +- }; +- self.request_with_options(&Method::GET, &endpoint, None, None, &options) +- .await ++ self.request_with_options( ++ &Method::GET, ++ &endpoint, ++ None, ++ None, ++ &SPCLIENT_FALLBACK_ENDPOINT, ++ ) ++ .await + } + + pub async fn get_track_metadata(&self, track_id: &SpotifyId) -> SpClientResult { +-- +2.49.0 + + +From 6adca21fdf64bd8026a2d6df04c42dd2b1239358 Mon Sep 17 00:00:00 2001 +From: Timon de Groot +Date: Sat, 9 Aug 2025 09:40:20 +0200 +Subject: [PATCH 4/5] spclient: Simplify base url init + +--- + core/src/spclient.rs | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/core/src/spclient.rs b/core/src/spclient.rs +index cbcf092..272975d 100644 +--- a/core/src/spclient.rs ++++ b/core/src/spclient.rs +@@ -458,8 +458,8 @@ impl SpClient { + + // Reconnection logic: retrieve the endpoint every iteration, so we can try + // another access point when we are experiencing network issues (see below). +- let mut url = match &options.base_url { +- Some(base_url) => base_url.to_owned().to_string(), ++ let mut url = match options.base_url { ++ Some(base_url) => base_url.to_string(), + None => self.base_url().await?, + }; + url.push_str(endpoint); +-- +2.49.0 + + +From 0b5b1eb6c73a9291057b3856939f416113fdd8bb Mon Sep 17 00:00:00 2001 +From: Timon de Groot +Date: Sat, 9 Aug 2025 10:14:02 +0200 +Subject: [PATCH 5/5] Update CHANGELOG.md + +--- + CHANGELOG.md | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/CHANGELOG.md b/CHANGELOG.md +index 560de2b..b62e9f8 100644 +--- a/CHANGELOG.md ++++ b/CHANGELOG.md +@@ -51,6 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 + - [connect] Correctly apply playing/paused state when transferring playback + - [player] Saturate invalid seek positions to track duration + - [audio] Fall back to other URLs in case of a failure when downloading from CDN ++- [core] Metadata requests failing with 500 Internal Server Error + + ### Deprecated + +-- +2.49.0 +