From be8581c2d0c806900316380db72ed14df418b0fc Mon Sep 17 00:00:00 2001
From: lilly
Date: Tue, 17 Feb 2026 22:56:53 +0100
Subject: [PATCH 1/3] configure diday website dpeloyment
---
.../forgejo-actions-runner.nix | 29 ++++++++
.../forgejo-actions-runner/networking.nix | 11 ++-
.../hosts/forgejo-actions-runner/secrets.yaml | 7 +-
.../virtualHosts/default.nix | 2 +
.../virtualHosts/did.hamburg.ccc.de.nix | 68 +++++++++++++++++++
.../staging.did.hamburg.ccc.de.nix | 59 ++++++++++++++++
6 files changed, 170 insertions(+), 6 deletions(-)
create mode 100644 config/hosts/public-web-static/virtualHosts/did.hamburg.ccc.de.nix
create mode 100644 config/hosts/public-web-static/virtualHosts/staging.did.hamburg.ccc.de.nix
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-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..923053e
--- /dev/null
+++ b/config/hosts/public-web-static/virtualHosts/did.hamburg.ccc.de.nix
@@ -0,0 +1,68 @@
+{ ... }:
+
+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;
+ '';
+ };
+ };
+
+ 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}"
+ ];
+}
From 9e5bad593e07542c55114d52935d2089464fcf1a Mon Sep 17 00:00:00 2001
From: lilly
Date: Wed, 18 Feb 2026 12:12:18 +0100
Subject: [PATCH 2/3] remove public-reverse-proxy (it is now on ansible-infra)
---
.../public-reverse-proxy/configuration.nix | 10 ----
config/hosts/public-reverse-proxy/default.nix | 8 ---
config/hosts/public-reverse-proxy/nginx.nix | 51 -------------------
flake.nix | 9 ----
4 files changed, 78 deletions(-)
delete mode 100644 config/hosts/public-reverse-proxy/configuration.nix
delete mode 100644 config/hosts/public-reverse-proxy/default.nix
delete mode 100644 config/hosts/public-reverse-proxy/nginx.nix
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/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 = [
From a8229bfd0dff789ead94036c49f3338683e74f2e Mon Sep 17 00:00:00 2001
From: lilly
Date: Wed, 18 Feb 2026 14:11:30 +0100
Subject: [PATCH 3/3] configure specific diday website requirements
---
config/hosts/public-web-static/nginx.nix | 5 ++
.../virtualHosts/did.hamburg.ccc.de.nix | 55 +++++++++++++++++++
2 files changed, 60 insertions(+)
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/did.hamburg.ccc.de.nix b/config/hosts/public-web-static/virtualHosts/did.hamburg.ccc.de.nix
index 923053e..6a89a22 100644
--- a/config/hosts/public-web-static/virtualHosts/did.hamburg.ccc.de.nix
+++ b/config/hosts/public-web-static/virtualHosts/did.hamburg.ccc.de.nix
@@ -49,6 +49,61 @@ in
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;
+ }
'';
};
};