diff --git a/README.md b/README.md
index b55e1f2..b9de769 100644
--- a/README.md
+++ b/README.md
@@ -62,3 +62,14 @@ This is exactly what we're doing to set the default deployment user to `colmena-
    };
    ```
    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
+```
diff --git a/config/common/users.nix b/config/common/users.nix
index ab29904..59682c4 100644
--- a/config/common/users.nix
+++ b/config/common/users.nix
@@ -9,10 +9,10 @@
 { config, pkgs, lib, ... }:
 
 let
-  authorizedKeysRepo = builtins.fetchGit {
-    url = "forgejo@git.hamburg.ccc.de:CCCHH/infrastructure-authorized-keys.git";
-    ref = "trunk";
-    rev = "da9d3ead9d97ce0fef7538638326264957e2f1b4";
+  authorizedKeysRepo = pkgs.fetchgit {
+    url = "https://git.hamburg.ccc.de/CCCHH/infrastructure-authorized-keys";
+    rev = "b6a29dc7af0a45a8c0b4904290c7cb0c5bc51413";
+    hash = "sha256-c0aH0wQeJtfXJG5wAbS6aO8yILLI1NNkFAHAeOm8RXA=";
   };
   authorizedKeys = builtins.filter (item: item != "") (lib.strings.splitString "\n" (builtins.readFile "${authorizedKeysRepo}/authorized_keys"));
 in
diff --git a/config/hosts/hydra/configuration.nix b/config/hosts/hydra/configuration.nix
new file mode 100644
index 0000000..a4c612e
--- /dev/null
+++ b/config/hosts/hydra/configuration.nix
@@ -0,0 +1,9 @@
+{ ... }:
+
+{
+  networking = {
+    hostName = "hydra";
+  };
+
+  system.stateVersion = "24.05";
+}
diff --git a/config/hosts/hydra/default.nix b/config/hosts/hydra/default.nix
new file mode 100644
index 0000000..f621711
--- /dev/null
+++ b/config/hosts/hydra/default.nix
@@ -0,0 +1,11 @@
+{ ... }:
+
+{
+  imports = [
+    ./configuration.nix
+    ./hydra.nix
+    ./networking.nix
+    ./nginx.nix
+    ./nix.nix
+  ];
+}
diff --git a/config/hosts/hydra/hydra.nix b/config/hosts/hydra/hydra.nix
new file mode 100644
index 0000000..f315710
--- /dev/null
+++ b/config/hosts/hydra/hydra.nix
@@ -0,0 +1,15 @@
+{ ... }:
+
+{
+  services.hydra = {
+    enable = true;
+    listenHost = "localhost";
+    port = 3000;
+    hydraURL = "https://hydra.hamburg.ccc.de/";
+    # E-Mail configuration requires some work/investigation still.
+    notificationSender = "no-reply@hydra.hamburg.ccc.de";
+    useSubstitutes = true;
+    minimumDiskFree = 8;
+    minimumDiskFreeEvaluator = 2;
+  };
+}
diff --git a/config/hosts/hydra/networking.nix b/config/hosts/hydra/networking.nix
new file mode 100644
index 0000000..82cec55
--- /dev/null
+++ b/config/hosts/hydra/networking.nix
@@ -0,0 +1,22 @@
+{ ... }:
+
+{
+  networking = {
+    interfaces.net0 = {
+      ipv4.addresses = [
+        {
+          address = "172.31.17.163";
+          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:45:7C:D6";
+    linkConfig.Name = "net0";
+  };
+}
diff --git a/config/hosts/hydra/nginx.nix b/config/hosts/hydra/nginx.nix
new file mode 100644
index 0000000..49ca2e1
--- /dev/null
+++ b/config/hosts/hydra/nginx.nix
@@ -0,0 +1,58 @@
+{ config, pkgs, ... }:
+
+let
+  domain = "hydra.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://${config.services.hydra.listenHost}:${builtins.toString config.services.hydra.port}";
+        };
+
+        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/hydra/nix.nix b/config/hosts/hydra/nix.nix
new file mode 100644
index 0000000..b95e469
--- /dev/null
+++ b/config/hosts/hydra/nix.nix
@@ -0,0 +1,10 @@
+{ ... }:
+
+{
+  # Allow Hydra to fetch flake inputs.
+  nix.settings.allowed-uris = [
+    "github:"
+    "https://github.com/"
+    "https://git.hamburg.ccc.de/"
+  ];
+}
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 6f951f9..2b1309f 100644
--- a/config/hosts/public-web-static/spaceapid-config/ccchh-dynamic.json
+++ b/config/hosts/public-web-static/spaceapid-config/ccchh-dynamic.json
@@ -25,13 +25,13 @@
           ]
         }
       ],
-      "3d_printer_state": [
+      "ext_3d_printer_busy_state": [
         {
           "sensor_data": {
             "unit": "bool",
             "location": "Loetschlauch",
             "name": "mk4",
-            "description": "Prusa mk4 state"
+            "description": "Prusa mk4 busy state"
           },
           "allowed_credentials": [
             "club-assistant"
@@ -42,7 +42,31 @@
             "unit": "bool",
             "location": "Loetschlauch",
             "name": "mk3.5",
-            "description": "Prusa mk3.5 state"
+            "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/virtualHosts/default.nix b/config/hosts/public-web-static/virtualHosts/default.nix
index c78cf8b..dac4fa4 100644
--- a/config/hosts/public-web-static/virtualHosts/default.nix
+++ b/config/hosts/public-web-static/virtualHosts/default.nix
@@ -6,9 +6,11 @@
     ./c3cat.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.hacker.tours.nix
+    ./staging.hackertours.hamburg.ccc.de.nix
     ./staging.hamburg.ccc.de.nix
     ./www.hamburg.ccc.de.nix
     ./historic-easterhegg
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..2077ca7
--- /dev/null
+++ b/config/hosts/public-web-static/virtualHosts/hackertours.hamburg.ccc.de.nix
@@ -0,0 +1,68 @@
+{ 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;
+        }
+      ];
+
+      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..b70f74a 100644
--- a/config/hosts/public-web-static/virtualHosts/hamburg.ccc.de.nix
+++ b/config/hosts/public-web-static/virtualHosts/hamburg.ccc.de.nix
@@ -94,6 +94,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/eh20.nix b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh20.nix
index 947791d..afc93c1 100644
--- a/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh20.nix
+++ b/config/hosts/public-web-static/virtualHosts/historic-easterhegg/eh20.nix
@@ -71,6 +71,11 @@ in
         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
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..4b71d53
--- /dev/null
+++ b/config/hosts/public-web-static/virtualHosts/staging.hackertours.hamburg.ccc.de.nix
@@ -0,0 +1,62 @@
+{ 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/deployment_configuration.json b/deployment_configuration.json
index dd0f43d..20b9f00 100644
--- a/deployment_configuration.json
+++ b/deployment_configuration.json
@@ -32,6 +32,9 @@
     },
     "penpot": {
       "targetHostname": "penpot-intern.hamburg.ccc.de"
+    },
+    "hydra": {
+      "targetHostname": "hydra-intern.hamburg.ccc.de"
     }
   }
 }
diff --git a/flake.nix b/flake.nix
index 106daa5..a6d9a0a 100644
--- a/flake.nix
+++ b/flake.nix
@@ -23,7 +23,7 @@
     };
   };
 
-  outputs = { nixpkgs, nixpkgs-unstable, nixos-generators, sops-nix, ... }:
+  outputs = { self, nixpkgs, nixpkgs-unstable, nixos-generators, sops-nix, ... }:
     let
       system = "x86_64-linux";
       # Shairport Sync 4.3.1 (with nqptp 1.2.4) with metadata, MQTT and AirPlay 2 support.
@@ -254,6 +254,16 @@
             ./config/hosts/penpot
           ];
         };
+
+        hydra = nixpkgs.lib.nixosSystem {
+          inherit system;
+          modules = [
+            ./config/common
+            ./config/proxmox-vm
+            ./config/extra/prometheus-exporter.nix
+            ./config/hosts/hydra
+          ];
+        };
       };
 
       packages.x86_64-linux = {
@@ -280,5 +290,10 @@
       };
 
       formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixpkgs-fmt;
+
+      hydraJobs = {
+        inherit (self) packages;
+        nixosConfigurations = builtins.mapAttrs (name: value: value.config.system.build.toplevel) self.nixosConfigurations;
+      };
     };
 }