diff --git a/config/hosts/forgejo-actions-runner/forgejo-actions-runner.nix b/config/hosts/forgejo-actions-runner/forgejo-actions-runner.nix index 376fde6..d5a93c1 100644 --- a/config/hosts/forgejo-actions-runner/forgejo-actions-runner.nix +++ b/config/hosts/forgejo-actions-runner/forgejo-actions-runner.nix @@ -15,6 +15,29 @@ 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; }; @@ -28,4 +51,10 @@ 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 8990224..71aa47a 100644 --- a/config/hosts/forgejo-actions-runner/networking.nix +++ b/config/hosts/forgejo-actions-runner/networking.nix @@ -1,6 +1,8 @@ -{ ... }: - -{ +{ 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 = [ @@ -19,4 +21,7 @@ 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 index 5debd4d..79df4d5 100644 --- a/config/hosts/forgejo-actions-runner/secrets.yaml +++ b/config/hosts/forgejo-actions-runner/secrets.yaml @@ -1,4 +1,5 @@ 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 @@ -19,8 +20,8 @@ sops: TklLZWM0cDBKaGJJM2tQQWRLZXhFYU0Ko7cyvzMvwlGCCP3UAX1+5uTI4srhZ5l9 DPaHySiC+rLy+8R9UqEuTKbP4/Aw4NZ/UcfjNnVkqqqNJIODmLoOhg== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-05-26T00:29:52Z" - mac: ENC[AES256_GCM,data:c0261ungapxYViyviTpNsSJZs6OMQ8fyHNqBpvTBp9jEEbbvJBSbqJtwJvVDg8Kv3xrZjC0jZSQOWkvYJlb2PFuW2/GXy5YpLCo7k3ZhXhUbotsDFPe30bvfVxZWhMpaS2rEXlxCqHeVmqoslL34jpLuFx04FmoBh91yjDMoiTw=,iv:njo4Bu4FzAbU6t7CSbqw7hcJ960oqsIKuV/qUGF8c1I=,tag:dzFxW8vyZsDFkd/ARkt5jw==,type:str] + 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: |- @@ -145,4 +146,4 @@ sops: -----END PGP MESSAGE----- fp: B71138A6A8964A3C3B8899857B4F70C356765BAB unencrypted_suffix: _unencrypted - version: 3.8.1 + version: 3.11.0 diff --git a/config/hosts/public-reverse-proxy/configuration.nix b/config/hosts/public-reverse-proxy/configuration.nix deleted file mode 100644 index a80f516..0000000 --- a/config/hosts/public-reverse-proxy/configuration.nix +++ /dev/null @@ -1,10 +0,0 @@ -{ config, pkgs, ... }: - -{ - networking = { - hostName = "public-reverse-proxy"; - domain = "z9.ccchh.net"; - }; - - system.stateVersion = "23.05"; -} diff --git a/config/hosts/public-reverse-proxy/default.nix b/config/hosts/public-reverse-proxy/default.nix deleted file mode 100644 index 20dd895..0000000 --- a/config/hosts/public-reverse-proxy/default.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ config, pkgs, ... }: - -{ - imports = [ - ./configuration.nix - ./nginx.nix - ]; -} diff --git a/config/hosts/public-reverse-proxy/nginx.nix b/config/hosts/public-reverse-proxy/nginx.nix deleted file mode 100644 index 68c30c2..0000000 --- a/config/hosts/public-reverse-proxy/nginx.nix +++ /dev/null @@ -1,51 +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.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; - 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/nginx.nix b/config/hosts/public-web-static/nginx.nix index b69e60b..7568ce4 100644 --- a/config/hosts/public-web-static/nginx.nix +++ b/config/hosts/public-web-static/nginx.nix @@ -5,6 +5,11 @@ enable = true; appendHttpConfig = '' access_log off; + + # load the DI-Day redirect map from the webroot + map $request_uri $did_redirect_target { + include /var/www/did.hamburg.ccc.de/nginx-redirects.conf; + } ''; }; diff --git a/config/hosts/public-web-static/virtualHosts/default.nix b/config/hosts/public-web-static/virtualHosts/default.nix index 3532c25..35da7f5 100644 --- a/config/hosts/public-web-static/virtualHosts/default.nix +++ b/config/hosts/public-web-static/virtualHosts/default.nix @@ -18,6 +18,8 @@ ./staging.hackertours.hamburg.ccc.de.nix ./staging.hamburg.ccc.de.nix ./www.hamburg.ccc.de.nix + ./staging.did.hamburg.ccc.de.nix + ./did.hamburg.ccc.de.nix ./historic-easterhegg ]; } diff --git a/config/hosts/public-web-static/virtualHosts/did.hamburg.ccc.de.nix b/config/hosts/public-web-static/virtualHosts/did.hamburg.ccc.de.nix new file mode 100644 index 0000000..6a89a22 --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/did.hamburg.ccc.de.nix @@ -0,0 +1,123 @@ +{ ... }: + +let + domain = "did.hamburg.ccc.de"; + dataDir = "/var/www/${domain}"; + deployUser = "diday-website-deploy"; +in +{ + # security.acme.certs."${domain}".extraDomainNames = []; + + 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}"; + + 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/staging.did.hamburg.ccc.de.nix b/config/hosts/public-web-static/virtualHosts/staging.did.hamburg.ccc.de.nix new file mode 100644 index 0000000..ad2b246 --- /dev/null +++ b/config/hosts/public-web-static/virtualHosts/staging.did.hamburg.ccc.de.nix @@ -0,0 +1,59 @@ +{ ... }: + +let + domain = "staging.did.hamburg.ccc.de"; + dataDir = "/var/www/${domain}"; + deployUser = "diday-website-deploy"; +in +{ + # security.acme.certs."${domain}".extraDomainNames = []; + + 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}"; + + 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}" + ]; +} diff --git a/flake.nix b/flake.nix index ecc9db5..fe0cbdc 100644 --- a/flake.nix +++ b/flake.nix @@ -94,15 +94,6 @@ ]; }; - public-reverse-proxy = nixpkgs.lib.nixosSystem { - inherit system specialArgs; - modules = [ - self.nixosModules.common - self.nixosModules.proxmox-vm - ./config/hosts/public-reverse-proxy - ]; - }; - matrix = nixpkgs.lib.nixosSystem { inherit system specialArgs; modules = [