Compare commits

..
Author SHA1 Message Date
fd240b0bc9
WIP: ptouch-print-server 2024-03-29 14:47:39 +01:00
113 changed files with 821 additions and 4934 deletions

View file

@ -1,23 +0,0 @@
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

View file

@ -1,66 +0,0 @@
keys:
admins: &admin_keys
pgp: &admin_pgp_keys
- &admin_pgp_djerun EF643F59E008414882232C78FFA8331EEB7D6B70
- &admin_pgp_stb 21C9579E6503CA815A68ABD8541F9408A813C8B7
- &admin_pgp_fi 9633412309CCB83BFA39BA5F2FEF746201D7FCFE
- &admin_pgp_june 057870A2C72CD82566A3EC983695F4FCBCAE4912
- &admin_pgp_haegar F38C9D4228FC6F674E322D9C3326D914EB9B8F55
# - &admin_pgp_dario 5DA93D5C9D7320E1BD3522C79C78172B3551C9FD # expired
- &admin_pgp_echtnurich 8996B62CBD159DCADD3B6DC08BB33A8ABCF7BC4A
- &admin_pgp_c6ristian B71138A6A8964A3C3B8899857B4F70C356765BAB
- &admin_pgp_lilly D2E9C0807BF681F5E164DAFC5EE1B61CD90954CD
- &admin_pgp_langoor 878FEA3CB6A6F6E7CD80ECBE28506E3585F9F533
- &admin_pgp_bitwhisker 41FFAF3D519CF5C039FBD8414BCC213729AF0E49
age: &admin_age_keys
- &admin_age_jtbx ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBQgnQAq6FUSDK8bxtYPjx3oRCAKG+xy9J3Gas2ztJk
- &admin_age_lilly age19h7xtfmt3py3ydgl8d8fgh8uakxqxjr74flrxev3pgmvvx94kvtq5d932d
hosts:
- &host_age_git age18zaq9xg9nhqyl8g7mvrqhsx4qstay5l9cekq2g80vx4920pswdfqpeafd7
- &host_age_forgejo_actions_runner age10xz2l7ghul7023awcydf4q3wurmszy2tafnadlarj0tvm7kl033sjw5f8t
- &host_age_matrix age1f7ams0n2zy994pzt0u30h8tex6xdcernj59t4d70z4kjsyzrr3wsy87xzk
- &host_age_public_web_static age19s7r8sf7j6zk24x9vumawgxpd2q8epyv7p9qsjntw7v9s3v045mqhmsfp0
- &host_age_woodpecker age1klxtcr23hers0lh4f5zdd53tyrtg0jud35rhydstyjq9fjymf9hsn2a8ch
- &host_age_penpot age10ku5rphtsf2lcxg78za7f2dad5cx5x9urgkce0d7tyqwq2enva9sqf7g8r
creation_rules:
- path_regex: config/hosts/git/.*
key_groups:
- age:
- *host_age_git
merge:
- *admin_keys
- path_regex: config/hosts/forgejo-actions-runner/.*
key_groups:
- age:
- *host_age_forgejo_actions_runner
merge:
- *admin_keys
- path_regex: config/hosts/matrix/.*
key_groups:
- age:
- *host_age_matrix
merge:
- *admin_keys
- path_regex: config/hosts/public-web-static/.*
key_groups:
- age:
- *host_age_public_web_static
merge:
- *admin_keys
- path_regex: config/hosts/woodpecker/.*
key_groups:
- age:
- *host_age_woodpecker
merge:
- *admin_keys
- path_regex: config/hosts/penpot/.*
key_groups:
- age:
- *host_age_penpot
merge:
- *admin_keys
- key_groups:
- *admin_keys
stores:
yaml:
indent: 2

21
LICENSE
View file

@ -1,21 +0,0 @@
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.

View file

@ -1,80 +0,0 @@
# 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).

View file

@ -1,22 +0,0 @@
{ 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
];
}

View file

@ -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 "24.05";
system.stateVersion = lib.mkDefault "23.05";
}

View file

@ -3,7 +3,6 @@
{
imports = [
./acme.nix
./admin-environment.nix
./default-host-platform.nix
./default-state-version.nix
./localization.nix

View file

@ -20,7 +20,6 @@
"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.

View file

@ -6,9 +6,14 @@
# - 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, authorizedKeysRepo, ... }:
{ config, pkgs, lib, ... }:
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
{

View file

@ -0,0 +1,13 @@
{ pkgs, ... }:
{
imports = [
../../../modules/services/audio
];
ccchh.services.audio = {
enable = true;
name = "Audio Hauptraum Küche";
};
users.users.chaos.extraGroups = [ "pipewire" ];
}

View file

@ -0,0 +1,8 @@
{ pkgs, ... }:
{
networking = {
hostName = "audio-hauptraum-kueche";
};
system.stateVersion = "23.05";
}

View file

@ -1,9 +1,8 @@
{ pkgs, ... }:
{ ... }:
{
imports = [
./audio.nix
./configuration.nix
./networking.nix
./mosquitto.nix
];
}

View file

@ -1,21 +1,22 @@
{ ... }:
{ config, pkgs, ... }:
{
networking = {
interfaces.net0 = {
ipv4.addresses = [
{
address = "10.31.208.14";
address = "10.31.210.10";
prefixLength = 23;
}
];
};
defaultGateway = "10.31.208.1";
nameservers = [ "10.31.210.1" ];
defaultGateway = "10.31.210.1";
nameservers = [
"10.31.210.1"
];
};
systemd.network.links."10-net0" = {
matchConfig.MACAddress = "BC:24:11:48:85:73";
matchConfig.MACAddress = "1E:EF:2D:92:81:DA";
linkConfig.Name = "net0";
};
}

View file

@ -0,0 +1,13 @@
{ pkgs, ... }:
{
imports = [
../../../modules/services/audio
];
ccchh.services.audio = {
enable = true;
name = "Audio Hauptraum Tafel";
};
users.users.chaos.extraGroups = [ "pipewire" ];
}

View file

@ -0,0 +1,8 @@
{ pkgs, ... }:
{
networking = {
hostName = "audio-hauptraum-tafel";
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,8 @@
{ ... }:
{
imports = [
./audio.nix
./configuration.nix
./networking.nix
];
}

View file

@ -0,0 +1,22 @@
{ config, pkgs, ... }:
{
networking = {
interfaces.net0 = {
ipv4.addresses = [
{
address = "10.31.210.13";
prefixLength = 23;
}
];
};
defaultGateway = "10.31.210.1";
nameservers = [
"10.31.210.1"
];
};
systemd.network.links."10-net0" = {
matchConfig.MACAddress = "D2:10:33:B1:72:C3";
linkConfig.Name = "net0";
};
}

View file

@ -0,0 +1,8 @@
{ ... }:
{
networking = {
hostName = "esphome";
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,8 @@
{ ... }:
{
imports = [
./configuration.nix
./esphome.nix
./nginx.nix
];
}

View file

@ -1,7 +1,6 @@
{ ... }:
{
services.prometheus.exporters.node = {
services.esphome = {
enable = true;
openFirewall = true;
};

View file

@ -0,0 +1,45 @@
{ 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";
listen = [
{
addr = "0.0.0.0";
port = 80;
}
{
addr = "0.0.0.0";
port = 443;
ssl = true;
}
];
locations."/" = {
proxyPass = "http://${config.services.esphome.address}:${builtins.toString config.services.esphome.port}";
proxyWebsockets = true;
};
};
};
};
networking.firewall.allowedTCPPorts = [ 80 443 31820 ];
}

View file

@ -0,0 +1,7 @@
{ config, pkgs, ... }:
{
networking.hostName = "forgejo-actions-runner";
system.stateVersion = "23.11";
}

View file

@ -0,0 +1,10 @@
{ ... }:
{
imports = [
./configuration.nix
./docker.nix
./forgejo-actions-runner.nix
./networking.nix
];
}

View file

@ -0,0 +1,13 @@
# Sources for this configuration:
# - https://nixos.wiki/wiki/Docker
{ config, pkgs, ... }:
{
virtualisation.docker = {
enable = true;
autoPrune = {
enable = true;
dates = "weekly";
};
};
}

View file

@ -0,0 +1,30 @@
# Sources for this configuration:
# - https://forgejo.org/docs/latest/admin/actions/
# - https://forgejo.org/docs/latest/user/actions/
# - https://docs.gitea.com/next/usage/actions/act-runner
{ config, pkgs, ... }:
{
services.gitea-actions-runner = {
package = pkgs.forgejo-actions-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";
labels = [ "docker:docker://node:current-bookworm" ];
};
};
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";
};
};
}

View file

@ -1,10 +1,10 @@
{ ... }:
{ config, pkgs, ... }:
{
networking.interfaces.net0 = {
ipv4.addresses = [
{
address = "172.31.17.162";
address = "172.31.17.155";
prefixLength = 25;
}
];
@ -14,7 +14,7 @@
networking.search = [ "hamburg.ccc.de" ];
systemd.network.links."10-net0" = {
matchConfig.MACAddress = "BC:24:11:26:1C:8A";
matchConfig.MACAddress = "1E:E0:4E:D0:DA:BE";
linkConfig.Name = "net0";
};
}

View file

@ -8,6 +8,5 @@
./nginx.nix
./opensearch.nix
./redis.nix
./sops.nix
];
}

View file

@ -7,20 +7,14 @@
# - 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, ... }:
{ pkgs-unstable, ... }:
{
services.forgejo = {
enable = true;
package = pkgs.forgejo;
package = pkgs-unstable.forgejo;
database.type = "postgres";
lfs.enable = true;
secrets = {
mailer = {
PASSWD = "/run/secrets/forgejo_git_smtp_password";
};
};
mailerPasswordFile = "/secrets/forgejo-git-smtp-password.secret";
settings = {
DEFAULT = {
@ -49,20 +43,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";
};
repository = {
DISABLE_DOWNLOAD_SOURCE_ARCHIVES = true;
};
actions = {
ENABLED = true;
ARTIFACT_RETENTION_DAYS = 30;
@ -87,19 +74,17 @@
REPO_INDEXER_TYPE = "elasticsearch";
REPO_INDEXER_CONN_STR = "http://127.0.0.1:9200";
};
"cron.archive_cleanup" = {
ENABLED = true;
RUN_AT_START = true;
SCHEDULE = "@every 1h";
OLDER_THAN = "2h";
};
};
};
sops.secrets."forgejo_git_smtp_password" = {
mode = "0440";
owner = "forgejo";
group = "forgejo";
restartUnits = [ "forgejo.service" ];
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";
};
};
}

View file

@ -4,30 +4,27 @@
{ ... }:
{
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.interfaces.net0 = {
ipv4.addresses = [
{
address = "212.12.51.136";
prefixLength = 28;
}
];
};
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";

View file

@ -34,10 +34,6 @@
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 ];

View file

@ -1,189 +0,0 @@
forgejo_git_smtp_password: ENC[AES256_GCM,data:ZRj5GpQKRlTxdu5CfbJirRGAKPCLAIG1F0V5USz5m5D49V3lu5uLomxHapmEwb0yYoE7e7ZLYK4VQUoQgpUnSw==,iv:K7+9E2gi8cdYu0lX/HgWitLxnxARywIwh5glEL0uOsM=,tag:s9UC8e+E5E3vM6cTKW7Vqw==,type:str]
sops:
age:
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IHFyYkk3dyBjVGcy
OUFGWFFKR3FsS0xKaFhFS2x0MnRqVGkvMnBBZlpYcFlJTDJROEZRCjlXWjNPcWJn
WGdMV0xGdHl3NWp0R0t6aVhGMDRCSXgzTzZQazRaUERUWkUKLS0tIDE5Y0JTRHVP
MlVZZ2VlMUplOFZnZWVqUFdQVDRwazUrVjh5MzZVdlJVbVkKsBYGKnzC9Z8GlaOC
VB74f99y6HOPrkzAkKd110LjprWqxKsburuoDCYpgzMndB7PMm1hBVruevq07nWh
SzvLTA==
-----END AGE ENCRYPTED FILE-----
recipient: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBQgnQAq6FUSDK8bxtYPjx3oRCAKG+xy9J3Gas2ztJk
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCSWNLaS9DVldhVkRzajI0
T2hMK2Jra3RFb0pPSG1IRGRQWmdoZW1sWDNvCnF4Wkw1VnZ2T3V4M0k2NGFackN0
VTFNTHNod1FMaWhTa09YMGp6Ti91ajQKLS0tIDljRlMxeEFWeG05OXE3WWhxRTM2
RUR2OERWRUdCMFFLUXBVZSsxT0hSbjAKGjlEHm+ChKOMkQwgIwO6MgRoUT9UXnC6
59sQVAchvSwe8WmlCWRBgdkYz4k99yQQPYD0BboLTdYrNmtDHrSk3A==
-----END AGE ENCRYPTED FILE-----
recipient: age19h7xtfmt3py3ydgl8d8fgh8uakxqxjr74flrxev3pgmvvx94kvtq5d932d
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNckxwRktHSEw5Vkx6OUJ6
bkFkS29tWGpLeHRKRVRYQ09MajhTMDE4ZVRFCkZVVi9IdXZ0Umd1b3kvVFNveHdi
Mk5COXBnd1M4eUNJVy9GS1pSbmJVK28KLS0tIHRIbTdFa2VWNXRRMXRFU1BrbWpu
My9hRGlNdGMxc0FnZ2IwSDNhSlh2WDAKQWwCXl9zvdnkc3octm82cNuGrYKkloym
XvmpvKU2//cKihkOhECYVjYVtyLNarbHh1kWIBtaduQzmkfyIX8Ksg==
-----END AGE ENCRYPTED FILE-----
recipient: age18zaq9xg9nhqyl8g7mvrqhsx4qstay5l9cekq2g80vx4920pswdfqpeafd7
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-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMAxK/JaB2/SdtAQ/9EfLg6PqyYMXdh3DoucKjcXCo7srGv9cK3iVmG0VOUf1f
OcKzUh1AIQOtcIxXoNf2On0g6PB99Pgoz24gjoZ7kt7b7WI5Uhu+/Dbu42kMRxou
3uJpaCucm3XLM/wSOjf7oU+GLORs64JL1+XLaNvn5DUsc+TpiOJa9Nsizagrs/wW
V81IdAxCMci7bllTwzimBTnLNx5Uao1yYrqJBfQxjoD+3d0gNsNI9uhQgmcA4Eoe
sVey0yKgbtY8oRjX7fYCRZyEX8UzGuclUsUxfHND2fvI8uSKfOzkpG5Vy9egd6xJ
cSRwlWTvaQJ3TqMwhKXqyIc9gC3BDmIBYvxsbq27ehq1JE+eYjIqJX1FuHTMXDku
hMuW2A3vLk7jwdRc2R38kW6wEHtjup6FOVYGqUKjd7VYJbE7vgihKdwIV0UFjyns
1IoZhLbFIw5v06jpPrblqyiOFeFk0JQlIJgP5fEpskWvG29aKd7lY08wnwiDZNwN
o7lddU4jgKsyic+SuvzdvznBkxA8Lazaj9RWvlJBfKWrX484zV2ZSZq3z6SsmjCY
ZLfFZx59AeWgcp054wwICDC2FrYJMPQd7AQ9uVRsEaWE1+ygfZGwGp5R3f0rLMhw
dwzcML37/dL0gAnDQEy+7EWjVvci8g7f/MHFlrFSuXewWy5QiaBaYyoCw41j76XU
aAEJAhB3FdKu5/mY0ZvI/RpKR6ZqfXq8h9EcBOQVChWR/ilq3b4xoXCm5TdYf120
6jd7rcy6GUZlL+Zu9K1y0hPCLEsgMswZDklssFMSgep4UXB+SeUNYIQ+PwU8Wmlu
sA5E6bX0FBiM
=IPl2
-----END PGP MESSAGE-----
fp: EF643F59E008414882232C78FFA8331EEB7D6B70
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQEMA1QflAioE8i3AQf/dhnhiHriQyiB4bDrEbNV44BY0Ani7NUpXyNIw6iTZUhc
yg0WKTUNTFgJYH3R5wH0U5m5FXtevgonaflDESf1ImjP9qtYMOvCRUMaVqzSv+CM
gpz9EPDF5m71c4W5fqm3lfVMH2JVUD2g+YKt7bbIi/igj+XhDPD21wBFHcwCivBx
Mu3Lqg5nZc4YEN+nUDjVbsy/DLl3Cuo6QdCTvcrhXfxY7RxxwR/iVIakXf08W1cC
RKJy+fY2KVtPhluRE6kVrMLswHxdDtbaRDV2ejTRILvPX9mrddZInTR9OJackWde
kOvU2YSJQvFE6w/o+CGiMzDLcqQiWwbVD2RcV84fW9JeAQPi0uFkNrKqFt2ojnkI
stmMB5h33kht2R9b0KbdPhf1LJk0Jn3asdiDcj2rVL3FiWMN+W/UBPkKXK4fBCX7
Rrp3XbDUjC9kJGJw5fJIV+qSfzgDgbZDv6Qjkni5OQ==
=HiA3
-----END PGP MESSAGE-----
fp: 21C9579E6503CA815A68ABD8541F9408A813C8B7
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DsZXvxFXTXoQSAQdASh7Vr4o7modBjS8E7kdLj1imFou3r3D51w26rNst/Eww
tS2tX+fG/wdJIY1xb7vaYQ+oP6WClenuglpRUI+bln+Vfcf9e4b5e15WZ2CDEP2h
0l4BAXQ9tKsmD52Z8Q5TB3xJUOrLrNR9898tFIXIzvPnQm+1YF3HU6IXvVjlKYXf
oBubJ0nVdAAiJRCdzL2IZ/3SWKgut10DaS2nQeaWOBXPpmg0u4s5bMRRp4zzDqoX
=bai/
-----END PGP MESSAGE-----
fp: 9633412309CCB83BFA39BA5F2FEF746201D7FCFE
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DerEtaFuTeewSAQdAgOu0hnPTPyFdJmVNMenRqyg5ENORjwTAmqqXKvNRvEMw
58ZnLC//bIy66k0zqYE8UbZqynrfcbtZwXLrQ2jVuWfA5Q0FtOyvTFgINtC6Tuhu
0l4B4yanK5Cux74O368HnxofZJCvQa9XGT1lc4NGQ4O7BycwnXDN2fL5Lm0pWxmk
+ZXZaKChtMUsoCBRuqE81DkRAGaqz684L8ntrH7tK3THOPN1hIyJ3kpz6EXRarA4
=4pXC
-----END PGP MESSAGE-----
fp: 057870A2C72CD82566A3EC983695F4FCBCAE4912
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMAxjNhCKPP69fAQ/9HQOeNYf4HOV9AN0yYK34mBx9z+jH+4zJ6SiFvjhcXpad
qk48SouK4d1nOt4WmY4aZ4gmk47Fnqstd2JvHaTldTA3tS3yGCQ4VWH9xE31f85R
bAPnBqEJVUoQeYveERVDC71BpeRutlL5bbUxV0+8Vw+6l222dIsPjDNBi/PsGSQ9
RmrqSBdPdi3cZcQ6ARrLA36tBbjTDBR2IrtLYTrXtS66jn46gFYaY+B+AvVwGL1M
+W9QEyW74mn6J/mPxqUCZFnMHUCXe63isHrMCQ2TEEiwXZgDMB4hO3C2jLnTOmOz
XrbATm2/gTczFhbPmxiqhJH/HTVi88tlK8Amxg31WSUC5PlsQ4gQiFNDcK7KROG9
vEzQiqol/2xQuddMigqYB+reOx8V8a86a0U27imnCflGw1qBTvB63JN8qGeq7rG8
0/keQV3jaQWsxv6OK2YjgD5rAfapFghuyCm/Cu2SRm5Tz3jAwwwwBO+jCjcJIbGS
1YHQzLUUtafOOyWFckfnHHKs7NnzVt52RbAoC7qlcpUPnmL40EAncQFUgzPpsrrm
Xzn7DredGQH04PPv26XLVoPS19Q3o/j9GTPNoUxskevhOv01bbc5epzdMOEuSva6
paRqhiaXsciNi0vHSvE4MrGtGrFpVyKQYnPFQoVyjGkAvMfwGSptVc7hNWD1yR/S
XgH5S0QbIxWmuXxy2Q50JBhTmG+MPczgE6El4XVqf4MetsyK0NkooLMr0xFLGhe/
6uJTu6OBOrRXW6GXbtuBVpY7bjjz2Oo5wfSRMxGSjFCp+1W5XJrvbhyuZq5Pg+s=
=SYMN
-----END PGP MESSAGE-----
fp: F38C9D4228FC6F674E322D9C3326D914EB9B8F55
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA46L6MuPqfJqAQ/7Bp2P2LHPjISMYoaOOyO2tTSOx1OSN7OwLK6JGEDtrAdF
RS1tCcCSKw1tiwxyKj3KoigovAGiqHuqQo08ycRpyYj3mRERIL6r9FpsfpNg2WIX
9I0tBjLG0oLvTd5G+e4eWqf/psa2imtJ8XccMVw/eFsEzCRH3QmqaZP6k6CSRjG1
BVWzhV7o7QL1OO3RDTnVf2oLoOg1FiR62rnd/YWNlE2p6AIANAJpUy09YfnS1BZd
Zw1A2UDEqyFRiUSgqRYAuXykFpsfoAAgVxVOXYQCLhO9P8+8Kxav9jjWGhjX0uOw
3B8ahrbHO8GyQ0alBvE1rTyKuX0JEcrlbuFyQj4NsUiZe4wWlbpuzrPhOLw4s+d/
lyyR8u20mqBLv47e1GA/WxTtn5L+6ADs/8CXd6YlZ6eXFEU6X++Jb3MubYOuDqda
b3Gv3RSHUEnktdSXy3vPhgZ/jJDIpiXfEYlpu8Jew52uRoQzfHTlhGJZXs7LxqMV
YA8kA6FK+3RkkhcHBhC+ALczUHybZ0q6t95EDqzH85KmAfS3DdMWWm0k/XziL52c
7cbUsYuSPD//9l+wC3WA23U+yKbpDShlFQnfgzf3mUilVLiHHwBs37ZFf1rqIA57
3kI5Kyl/2yl1snSLxL1ScC3ZQ1QUy1888ogQk2tBfo9lAA712AYxRW3q2lYGW+nS
XgEBiAX/zlU1quBXmF5gfcDckxPe7KSsfXKz6/1IbPK6iLEPzvGb/1043Lk1bFlH
ln6ZtWbByzqX8gGejgIqfxq1P4NhKSSTz9UuCc1fRAIBLOo8SEJw8edy3kcca3w=
=ZoJ9
-----END PGP MESSAGE-----
fp: 8996B62CBD159DCADD3B6DC08BB33A8ABCF7BC4A
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DQrf1tCqiJxoSAQdADbNfYR8kdZ9ihwwU0TSBhIV0vYKiXaV6IiheL+zD83cw
w90e0B9v+zlt07CsPKHP6I0U68Hn446U3sV1rxSB84pHsqb/+f0DJLxwvdOWTXcq
0l4Bzhs4ptFhwWXoftKe60afPoXLoXP4ZwrKJRMNVf+4L/WPJisZyjQTAC7nHN5d
i5c7JVXGIyXVRzg1jNUcjddM1XdBACgpsEwAA6dNUmAOMFoISQckyudXKvIpoGAB
=UDDM
-----END PGP MESSAGE-----
fp: B71138A6A8964A3C3B8899857B4F70C356765BAB
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DzAGzViGx4qcSAQdA6Cv+6xrYUOxW2bAlrtomuNBZ/jfPE8aZMboKwHgQ9QEw
DNyPe+JNiI613UlHzi6vZWQyMtno3KX6i29iR9/HfdlFoaXKccqxHXWQjunzjp4V
0lgBQv1YU0LU6XQfiF2LfdN0KD+A0HbGVq4OKJruMACT7hSHoSwPdz5PnENX08Q7
6y5bN8rCj1RNkMVFZtnsWZJ39nx389sJqSDOJ0Krj0RNgPQtxn/vNeHz
=AWTw
-----END PGP MESSAGE-----
fp: D2E9C0807BF681F5E164DAFC5EE1B61CD90954CD
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA2pVdGTIrZI+ARAAqTQx/Uik2MtmgCTPg+xe3WBzut8tKKFPAChJYrNSXPyB
cimTNFrXQa5kF7SuaEE4YZ1TGxflReaAGjss+IqbKoKLDkyP3anPCrUEbwwDkOmo
67lXbp0oDkHGVrnutFCDqHp6JnEEpa5W6TrCfSrw1UlDfGAAPIf1rxsJk6v2MbtN
9J5YIjEkK86Y+8w8J7BFjbjwn0SPxUDawJVUHRmvnV3Ym3z0KxKkAcFHudELGl69
PkKt4/ffu49ncmt6PIoLSD5YghVUUVhn7/K6EhbZG7O4XL2TNVqf4D8ub5wwI0/q
ktsH2EDBEXlF5jxACm1Xx6NQTt7iWdVRM1tuDcCpU6I7dWqQdVrAx0LKGTTtKcWy
hL4fhLOo557kNyHXxZTitx/VZ8dPdgNr6hJoMdKz9hVRqQj8Bl0YCYQX7PUg+7GL
FLeForgaE0ipurT+i3p4YmL0cdBRzOeM6igGPrf1F6Bjjggpu/HOj8wb/VRkIkrS
m8RbuBEhpx1M39rcg/XC7CCzgpZmGwVOFE72c58663Ry9fR5ral/hXBGEwEP795v
3ThMg1mnzThwvcHt8JkPJPQ9StNasQkhcUKLQu5Ss4xT4DhgG3ZzuB/QInLsCKU4
Zqw+J7D1gbwFanYtxoaxToXB40VwN/DnVLloMlDOFOiDzfmMbLqGY5ci8q9LCtzU
aAEJAhCbXAV++AGUpQ74BgqBbI8D3gN62YMzEePCY5u4a9v/HeIBwFfXSsl6Su6v
5CziGqIgep0IWa9Xu089nKSuvcl3MjWyi3GkIl2DfMf//meXErrqTU2IReo7irMd
woZlOnP3qhNP
=zo9d
-----END PGP MESSAGE-----
fp: 878FEA3CB6A6F6E7CD80ECBE28506E3585F9F533
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DKKbvh61jX5USAQdAu0Tsmv9Nee0P7wCNvoDNm1iREinyjbMVlE2k/gP63CMw
uuXlFMAVbrHOEg2cHnRRYVCPvHRlM4sCHZrQmxfyerM7Nw6UL6qRdwFMaWWqYRSU
1GgBCQIQ+rjuiQtM/CYPGM5PwV1lg5B1nazt2tzHIMGpYswKcNtJ7HmjLuqQmVr8
Kycbj/C2PPtQmcTQxF2iOtVc6l6eZs3sq3eVKU6jz/GW41Vfr4wY4WTsuurDgy10
lSonRrLKPLMwmw==
=T6Nd
-----END PGP MESSAGE-----
fp: 41FFAF3D519CF5C039FBD8414BCC213729AF0E49
unencrypted_suffix: _unencrypted
version: 3.8.1

View file

@ -1,7 +0,0 @@
{ ... }:
{
sops = {
defaultSopsFile = ./secrets.yaml;
};
}

View file

@ -3,11 +3,9 @@
{
imports = [
./configuration.nix
./mas.nix
./networking.nix
./postgresql.nix
./matrix-synapse.nix
./nginx.nix
./sops.nix
];
}

View file

@ -1,124 +0,0 @@
{ 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\" <root@localhost>";
reply_to = "\"Authentication Service\" <root@localhost>";
# 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" ];
};
}

View file

@ -41,29 +41,23 @@
max_upload_size = "500M";
admin_contact = "mailto:yuri+ccchh@nekover.se";
default_room_version = "12";
};
extraConfigFiles = [
"/run/secrets/matrix_registration_shared_secret"
"/run/secrets/matrix_mas_config"
"/secrets/matrix-registration-shared-secret.secret"
];
};
systemd.services.matrix-synapse.serviceConfig.ReadWritePaths = [ config.services.matrix-synapse.settings.media_store_path ];
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" ];
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";
};
};
}

View file

@ -1,19 +1,17 @@
{ ... }:
{
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.interfaces.net0 = {
ipv4.addresses = [
{
address = "172.31.17.150";
prefixLength = 25;
}
];
};
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";

View file

@ -17,18 +17,6 @@
];
};
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;
@ -49,11 +37,6 @@
}
];
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.
@ -65,68 +48,6 @@
'';
};
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;
# increase header buffer size because mjolnir sometimes uses very large URIs which nginx would normally block
large_client_header_buffers 4 16k;
'';
};
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

View file

@ -11,11 +11,6 @@
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}";

View file

@ -1,192 +0,0 @@
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:
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IHFyYkk3dyBFRnla
R1FMdGJDd2R6ZFc3cHZwd1RNV3VKQ1JYVzFwZDNvTXI0Mlpia1hvClJzUkZLQk5t
Rm02M3R5c1drU2RjMFVYNFNrall3RjJzeStlcm8vRXVQOEkKLS0tIFpPZGZXWVlQ
VjZNTTFRRC83dUxvb0w2MGFhN3N5TGVkTEpwSmFENGo5M0EKN1rpNbPZQ6USeNT/
1k8zXsk7EhYDuuH3ySECZvJ4jZjcZaNhLXgv3gI6NfZR16tLmoZk574yTaCt3xgL
f9SYtA==
-----END AGE ENCRYPTED FILE-----
recipient: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBQgnQAq6FUSDK8bxtYPjx3oRCAKG+xy9J3Gas2ztJk
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwQVFMYk1pZGw5US91UnRV
MGtPQW5WTi9wZzdQZWx0clBKcFF1RHc4cGhBClVjWk1na1BpSmE3YmtyVXIzaGNI
TlUxdEZHS1dGV3RHSU9YaWxpQjFmRmMKLS0tIFR0TzNZTXdCOXZrNVVVRnd4bml0
MGp5RUJjWFVwbjA4Y2xacmtEVTlpSE0KXx9x2FVSl+4/sWyOzX50Kk/NI4NBRbdu
kvJuOmile3PgxeZrG+KL7cEps6oJpBfKMmBev02Z9rMXJBN1kuDcDQ==
-----END AGE ENCRYPTED FILE-----
recipient: age19h7xtfmt3py3ydgl8d8fgh8uakxqxjr74flrxev3pgmvvx94kvtq5d932d
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnSE5ZOTBOWDRoRC90cG9B
S2Y5VmhjTnJvYzdVRkdoTGhzRGxnOGRXdUdnClNFZjFmdkxPOHROSjdET3VuRmNP
cjNLSnZycStBK28xVDVDOG9YaUE1Sk0KLS0tIG9KL29iUXIwVmY2VGpiU0Nkemdy
UzVQNlMyM2piMHN2MW5adzlJVXppT2MKzkvjVN63AOQnHe5iMKh3uHeTBGUuBkXi
bDyk/IEwE8QLK9sLWtxXSb9zX8b25rR4F9zePXvfyTRSf2P9QPCoZg==
-----END AGE ENCRYPTED FILE-----
recipient: age1f7ams0n2zy994pzt0u30h8tex6xdcernj59t4d70z4kjsyzrr3wsy87xzk
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-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMAxK/JaB2/SdtAQ//Q6+QM2pzG9Oh9n7H+phGfX35VAvwl7qZ4FGDBMdZfRZz
seVfBexuL4o8qnVV33WAS4Oh9fUSK0mUHY4DlSc/IhZ7YQt22XbOj90qBj+EDaOj
qJ5lulRaN+azlt4NomkyM4nrXs+M6bFLby4wWQLrLN5Eu9tqK7CK5Z3UVtYTkML0
QMwRP0IH7hdKT3NhVpFL0sXDa5yq86EW3Kxk8LSyepIYR/6qkM1MTDj3br4xjBT7
p4WotIJdjYHuuHvTfbVEN6g7uZE+Tk1Ss3m5rxhdwCbNlmSqnwqx/AXcTE3NsuoW
ziIxcY7x9ACrV6rcIgQLTBMebwh6BedlqjTZfrJMkPz1n0SHqpL0Liz+Vq8phgeo
o0EUPDvFKIcbDJQpIKRb+iSy9WzeSON8GQPd06WFxD3IwHFoAWFdImb1FERwGIym
vEy14JGXSGDScUwrgjeDW9APoM7oWPtjXVPHnIcSQpt7cgn4Nse5BoYBQZZt+7VQ
HhYIIByIxMBYG6K/3ckhHVc3MtJEmjftE+dSXYkC4jyJtwX63fTEw6D4soiUf00t
8oGSwXtecsHQEmeKx360Jk989KXqpbo0i+LO2WjU4foJ1X4MaSllwITz/ZcnQHRz
utjKN0d2VUf9K2DP5CI/GKdMffF8bYodmfT7H3zv64bfGMggOujnhjoqK8wgEDDU
aAEJAhBcl/7ziJ325FIQRF3Nl1RDv3mrlcuuXMMbU/MqpQ33lLcsERYe/L+92QcD
OphOuQ3ReqkrzwxjglT2V5ylXUPfZnwM/0Z48a/xp7/zNfMRD8yfAEGr+bkpequ0
Zvx0zXHY8AwV
=HV9I
-----END PGP MESSAGE-----
fp: EF643F59E008414882232C78FFA8331EEB7D6B70
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQEMA1QflAioE8i3AQf9E6bfKP4QNL5Hq+MyTeDnz3ij6V71SCL4gxk2Ar7iQF6u
Or5g2w1eJBt6h/DSvtXhlFaqzlXuItMeUFi48a4D82beM/46lrWVKFJtKrinE6ZS
ornW8TVNhGmo3T04l12efnL6ii/AyOnrGGiHo+69s9b3Yc5+Pjue+BjBHi2a6/qf
rccJzbMe5EsjLNSkEi+zr3QPXRKzl4BzTD6yDCI2ulIHcQguh9B4jWZxwx+P5zk8
8cTjbv5ZjtTa3IjuWnEaU6JEu/rSCTYKi1Oj4jrnCQ0tQvu6yvRpfnBdIAu+82yO
L5TLG7nC+iAiC7wN6V3FgdNH7DUGFKTNDMZm7llVU9JeAUD+yhTNHpwqebzZ+xWQ
hnAe4ytJJugK1pJ5QHFX61+12fe8aLjsHyJt+oMKpLi8SCIZjmMgf+cmAE6YBiK/
2/VxgewGn2gm55SqKJg8aeHt+k6yMNoAZu19dNA00A==
=4XbJ
-----END PGP MESSAGE-----
fp: 21C9579E6503CA815A68ABD8541F9408A813C8B7
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DsZXvxFXTXoQSAQdA0lS2szzIAtKwWDwVp0WWJd4mfd8P2zQc3dk6+HwglCEw
O4R0tpsmNImmeMss/lRhswvTeFGh3aa5ISCgftJ//nDM+Jvq1QGZOxCKxa8vQHh9
0l4Bg2qErfMMhR2iG3gk8oAbL2WRydX+cIR8OwrKDu7rjyfW1JlY9Zhqf97ZfuwZ
e0wVEQVnb4EsFX4VVMetTbQcD6TgtVpV9U49LZe8YqmN26hdfK/A1ZR+hNLAoTWV
=Drsm
-----END PGP MESSAGE-----
fp: 9633412309CCB83BFA39BA5F2FEF746201D7FCFE
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DerEtaFuTeewSAQdABZzQhnIdn0EuEhxi1Ch2zQbHXPVLivQdgvQe8qumNU4w
y3OYzClKRaQNdzS/0OaiXyDRS5+IAbYTQUokxcjlayQYQDmseiaHYAjqP/OiLbSs
0l4Ba8x5iq9YvPaaEWqXHsFUlJpmQoY7vW1kmz+yECCxx2TFjxL8n9fHPTMe1Jg1
OgaZMrQjc3NWcRcpYPvWmB8cPEm7PZEx+pg4KCpaoG0a3YmSDr5xk6wwjgJ6ULo6
=islN
-----END PGP MESSAGE-----
fp: 057870A2C72CD82566A3EC983695F4FCBCAE4912
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMAxjNhCKPP69fAQ//SCCveu3FVKIJep3wW86VLVl0Cd1h+rK0JtrkPe2cfLO3
zXy4dBlo8+fkXokrnB0hhYRLwlrBLC/m/nptuxuj9hbjQE84TUb2cbd/7s5KAx0G
H5qXxYbSqy5TTAoMS7XoJDlYsBE0aQWrOAbJ53AmykByUEpmCutmlnMowvwjn9eq
vAO2gl3ZXEInxo39R6NxEdcV5sZmPcKt3QJi4pSH9mk60LaEGS7L0QL/fqClH5jb
VEh4HUmnA9i2pkZSsMzotyKr8VCKjqCI3bP+GTSI1n+RaMXxWxL1HLEqTOYdTx5a
OBTfk9Z0kbnevOfr3Zm2qU/VlnPDWPKdx2+4NP9Q+bHsx7O3r8HQmgOGS6kODTtx
whWaiQBpNCalrD9ntFqCZ2pz9wKzqO00SDUFEVDu+1puk2FX8RgxdoScw9Pgq5Ua
d+44fOcEtsD9e76p03IhHY7/ridJfd8F+gPqqPoQyPP5Q75tlaCnI18J6hYVQc1U
8OgxwMvHVFXCYlpGMFTj79zLKWxH5zFzGN+uO/SbzL5xpsL78aZP0fkoJa+TR9Zg
2fnWnSIFVoloROubrgutaTQH3yW9Pj5m8n12wXjvwJ3NofO7kTkH/xq1xtBZBKLd
rEmpf7Xr24d+pOKRh2c8cA++l4If805ohgSsTTezHPoG/MaW/Rmt4RmrWcSUOvHS
XgHlyoKANKEtnnKz7LFhyW/tP9tl2tMs4dJdGukuPEZa0AjyxvoELNNiCQg2angd
N7j2MPHesHeXEL3f4/FX26G8E8PiAw/OA6fc1JEQDvBeYSWDJDPQAYznM5EHBm4=
=/MB8
-----END PGP MESSAGE-----
fp: F38C9D4228FC6F674E322D9C3326D914EB9B8F55
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA46L6MuPqfJqARAAkx1/qDlCyaYOTWLMBeXs1KwkYlMZWHGsFKwlGnOOx57N
Jv4rzRGsz2kEfBTl2zyEjKU7f7PR8zMuzHLxcfhYFI+2x1ju9TR7k64Isad3mpPT
gCt3NqJy9qp5075mJtVjY4bG50hXydPOsnw/d4aO1Mv8DWdOGC2Y3AmXgtqL45jf
296piqaS0outzMK0vc2X5/1jBcHywdSIHlHsJcFV4O46YIi9G00hVIgI0KMJbUNP
RXWn6sX/rGJ7rhTXGl9/P3Qktxyu7q21KYKj81blpeCb+K86N0XfCYcLY562CZ2d
hz24REsYK2emtsDplVPxzzKulYF56FZoWC4xdrxic94jf4EQHCZMksyDAg3hwJZ6
7nceELAgMtJUfR/pPAncBsLsSh4JEk0z0fBmYm+0i1KLTaMUTNLZ2RxaMkMnqRid
Uw/N9jMknV4wIlQDt17Hx4cU8/vfidFlFg4KMCMACnBiEtnCNctmIcZIeclkM2b5
ZQpoAWFJcp3OwsLvYQeDnhTahdoLYsWxF1+3j63Kb6ZYDSMQyYAWswdlY5DlIHoY
vhVdtsj0ZgKwcT4rfIfDBAYFDeCtxfSPl3r/TuHaK9IeBg2AJxPCeDAuFNsdKMqT
eH2XPK7gzusvPl0ftgmAs5awOMq1/cDUr4LZl3ktHxtY7m7UT0hGQg65xrxmwOTS
XgFkAkiGb3z08d4PVb1pEQjO8vu4Xi4czLq62eQgt3zt0TATFAGBKdRuzkSiUyG9
Q83yQijtAhNQBcW7Yncde89A/dStODUXDZPso50mHscKG64Xlu4zSIXzAesIw00=
=jn8U
-----END PGP MESSAGE-----
fp: 8996B62CBD159DCADD3B6DC08BB33A8ABCF7BC4A
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DQrf1tCqiJxoSAQdARbiTXH7f2RfRmA2r0AlLBuf2O0Tm4+R5K9uSIyjuMAcw
KQM9BhxvwcMq8b1gueFxc9KPRqGWErgBlJm/cSDeiTRqKQDQQy5TqzieEzHSwJGH
0l4BBsKJzalQmXj2SRET+OTURGDYcZRtdtS5kM2x8/XH6aTjl77VLzt3o1P6A0LY
mwXmwEdy2lbpGxlST66OjJmprMbkvRAeG2C8cwxxLD9F+Xijif3fsD8XFT1m92Tm
=9w44
-----END PGP MESSAGE-----
fp: B71138A6A8964A3C3B8899857B4F70C356765BAB
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DzAGzViGx4qcSAQdAKaXe5ffZGu85ZTuLCuAcJjIVbS4jpoxc0bP2zghVyhIw
S1FO7nwMyn4gngmJw+6aHUVZ9K2eGctVMI1xeRnk+gv/kw/TT+bKC+5lJbcTrVPl
0lgBwW13D1CnpukBbBIF/Sn8YV/58EZ1ORXf8dk47kPyHao4ATOetwxVpHTFN2ha
L1tiR9F2+EvgRgX2uyXStzIJ9bRVeWFZwc6pTMo6Hy4wWXd+MSvG0JFj
=MnQQ
-----END PGP MESSAGE-----
fp: D2E9C0807BF681F5E164DAFC5EE1B61CD90954CD
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA2pVdGTIrZI+AQ/8DnoVmNOeanDM1qupjs+5aRQx/J0WK9rAaaNWEQoWZCF6
y40rD/IeQVJtr6fWrfaFSLEM+i7rpWt3drXEnlDTrZLxlsPlg16covAMq9D1NM52
V8bz5MUfU3dV1Z+1Ov3OpatPvH97912cgRu3USvx+5rNQB8SEA+p3tmyIGhRXYD2
ZdwcegqY6K79OXsttuF+Z7o4Sm59I9/itezzXwwOPTwHANPn5nC4Yoj5DPrC3Lyx
DfNlrUKneR4Vx/6iZoZxKQ7xp3bUlj+/GijP9jwvl3oxsK5FX05CO0WHh+ivkQkB
T8G0Jmkjag71jhD1uN7sh+LS0wVbT4G2d6f63gGnlLgJYumGA3LGE6momrpLn24A
MtdIDwMXP6HzpiPc4nl48z8xk+sOTrKQNS1AcZg0ghS9QQSN2BNQjOulc3h6Oako
jKUHmGJwK1tc/yz10VleK6Ato4MkfZtgDY9OKPDDjm6qHyMLpNnafHUxJW7xvfTM
n6HS3KijQT9ZG/Wnfe40SbTeZ/bVaHm7Kd8JF5j4ey64iUIPOPgzZ5o6vONhail4
iVJ3W54XQqinzx6EQ0hEVdB8DDR0XcV9SZbKOrmBnB470SbCCcENX7Jl4CK0pL0P
6SokTWOwPX3ZVojKxtxWhcJ4vEfK7rl8oNTOuTRcX4ia6bE3br1PaCWR6cixN1DU
aAEJAhD0SxSeK+U4ccQYvtK3owFgaTDjiV6puGGiSlTLXUHK+xebeEL2XBBRBpTl
rb93QHfA8c7AIjIsTvrQuzM8bKHVDSVTluTmERPmW0RtV8OKnbi9Cqu/Q6pEcsJZ
7kbc0pvzIRa8
=bi8F
-----END PGP MESSAGE-----
fp: 878FEA3CB6A6F6E7CD80ECBE28506E3585F9F533
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DKKbvh61jX5USAQdAkOSps7psNS8n56p8oRw5FwPJzpwy/mzRP1vmzp53xmsw
gI2gka7Asv9ujumXLQSP5mlvaLp4G2NZrjUNO3k2f1sURpwYishBl35ae2H2Vc2s
1GgBCQIQneuitb5Kil+z5ukQNZQphYUNBvxAiQ/TW1e7LcyC5ZhOsiUDXS84AlWt
I3Fc74QuCjUAW0PLejiB8jqt6qs7DHvFO6ismBZgUSU4ABQwN55DV/E7yTiL767n
cB5aUeyqO1Ukvw==
=Hn0x
-----END PGP MESSAGE-----
fp: 41FFAF3D519CF5C039FBD8414BCC213729AF0E49
unencrypted_suffix: _unencrypted
version: 3.10.2

View file

@ -1,7 +0,0 @@
{ ... }:
{
sops = {
defaultSopsFile = ./secrets.yaml;
};
}

View file

@ -1,10 +0,0 @@
{ ... }:
{
networking = {
hostName = "mqtt";
domain = "z9.ccchh.net";
};
system.stateVersion = "23.11";
}

View file

@ -1,34 +0,0 @@
# 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 ];
}

View file

@ -0,0 +1,7 @@
{ config, pkgs, ... }:
{
networking.hostName = "netbox";
system.stateVersion = "23.05";
}

View file

@ -3,9 +3,9 @@
{
imports = [
./configuration.nix
./netbox.nix
./networking.nix
./nginx.nix
./penpot.nix
./sops.nix
./postgresql.nix
];
}

View file

@ -0,0 +1,30 @@
# 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";
};
}

View file

@ -0,0 +1,26 @@
# 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";
prefixLength = 25;
}
];
};
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 = "62:ED:44:20:7C:C1";
linkConfig.Name = "net0";
};
}

View file

@ -0,0 +1,67 @@
# 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
{ config, pkgs, ... }:
{
services.nginx = {
enable = true;
# So nginx can access the Netbox static files.
user = "netbox";
virtualHosts."acme-netbox.hamburg.ccc.de" = {
default = true;
enableACME = true;
serverName = "netbox.hamburg.ccc.de";
listen = [
{
addr = "0.0.0.0";
port = 31820;
}
];
};
virtualHosts."netbox.hamburg.ccc.de" = {
default = true;
forceSSL = true;
useACMEHost = "netbox.hamburg.ccc.de";
listen = [
{
addr = "0.0.0.0";
port = 8443;
ssl = true;
proxyProtocol = true;
}
];
locations."/static/" = {
alias = "${config.services.netbox.dataDir}/static/";
};
locations."/" = {
proxyPass = "http://${config.services.netbox.listenAddress}:${builtins.toString config.services.netbox.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;
client_max_body_size 25m;
'';
};
};
networking.firewall.allowedTCPPorts = [ 8443 31820 ];
networking.firewall.allowedUDPPorts = [ 8443 ];
}

View file

@ -0,0 +1,7 @@
{ pkgs, config, ... }:
{
services.postgresql = {
package = pkgs.postgresql_15;
};
}

View file

@ -1,7 +0,0 @@
{ config, pkgs, ... }:
{
networking.hostName = "penpot";
system.stateVersion = "24.05";
}

View file

@ -1,63 +0,0 @@
{ 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 ];
}

View file

@ -1,198 +0,0 @@
# 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 <no-reply@design.hamburg.ccc.de>";
PENPOT_SMTP_DEFAULT_FROM = "Penpot <no-reply@design.hamburg.ccc.de>";
# 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";
};
}

View file

@ -1,190 +0,0 @@
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:
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IHFyYkk3dyA5bkFY
VHVYS0RZSG10RGhTT1dpQnprcVhFVy9KVlVDS3dDWjQzaVRxTm40CmhUUldsMjll
STl1ZU5xRjJJQ0FNVkxCR0VSVGM4bVpkUmVVSUhtU2ZHVGMKLS0tIGgxQTRlZ1ZR
R2tjL2R3OUFTdDFEMnNiWi9IYzlZTVFCMFhxekxsVnVkaUUKSLpxdEHOe5+IRByq
vrH244bPEoZ2aHoVK4PxSSljWsvRSvtpYdH6NVdVTUIfkzlv3MuGQovQrt32G8OO
IakrQA==
-----END AGE ENCRYPTED FILE-----
recipient: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBQgnQAq6FUSDK8bxtYPjx3oRCAKG+xy9J3Gas2ztJk
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4aDNod1EwdEV2UGp1Mm9I
bGwxNEFMZ3FPVmR1V1k4L1IvZU0yZFlzR1RzCk9rRmRZNlM3R214QTB6VjN2SjJY
aHFhcWs2WGZ1UHlSSmxxeFNSM2NOR00KLS0tIGZ5VGY2SUN0MmxhQ3pYam4wWlF1
bmlhK3Y5SWsrcXBManhDWjRVcFNLNUUKKQzCBmLytcDdcHIfGmB0iymInigSeKQ8
UM+qEHMCLxmYA393OBJOAiaZIS5ECjH/cBqQ9o3eRYV9ul8nbX7Pdg==
-----END AGE ENCRYPTED FILE-----
recipient: age19h7xtfmt3py3ydgl8d8fgh8uakxqxjr74flrxev3pgmvvx94kvtq5d932d
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4ZzhhRnYyMVZCdzNNZlVO
NlQrSkx0SFExQlNxQjZPclpZWTM0cXVwWmxnCnFEcFJqV21MaWF0Tm1kRE5uMWdO
T2NCRXBlSjFJN1R6SVhoYlJPQ1lrNlkKLS0tIHd6YzU2WHZKWmN3UHBCYzgwNVdz
V1QrNWFsbURzMGJ3enR6TnZCTEtaSFEKT3xVkvQtdAuoZSIpaMWR3txp3ofZox9B
9PjOz+iUSnCMFF39Of9LMk+vcnXWSkwAvANxZF7u9naqRyzmuQ0q+g==
-----END AGE ENCRYPTED FILE-----
recipient: age10ku5rphtsf2lcxg78za7f2dad5cx5x9urgkce0d7tyqwq2enva9sqf7g8r
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-09-24T18:45:13Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMAxK/JaB2/SdtAQ//SgjrK7PsMLCHFc7edKoH4mUncr/7YVostmtuP4VXHdyJ
s2/pmvkthcPOcAgmQmdxZtOQcaMgwe0RP0SOP8k5D5xwosFuzVAXS13BRiL+/tRX
bn4SdU0y40Mlz7D1YazTwERSMcl8GyQBig6rQFmcXlyjYyZ6T7udix1hzadSuLTB
TAZuKGTQQ4MIspuck4ECE3IZjxX1WJdLP6tKbm9lUxyHGoaoNjUbZdesZ8r5+i28
YDYOfejBHRVpAuC8UeeqK2tI14DvbZJxOHvwUPKCjUEBGx9K6OvXqNb183aa/dvP
/64Q1o1tg2NcYUIYTAz7EXf0cElcLs+Obob1aWwm9szcPBGz9A4eBcYJOLIBmAJH
Xdz16XGbekG+3Qo7DtMLPgFgLqNiZH0+zrB1fREhoLcR1abuNr4JQcLWo3wNjjks
65rLrBgIZqm/DLxXiNeThlfINXD+hmGoq7Q+b+yVNorb+OKJ2UI05CWFwtNd7KGn
YD/BPAGhlU2XHuAMW1gXQa8YRM8zgqidPtiQ/f1JVtqQ5K1q6hrLdsqffTGzgiTd
h7sJYSbWZdTtdMBrxkCMwiQwysax7uCLMABBtYhs3suDUqw3I+1ydws5lC2XAKMt
3IynlfvpoQ0Fc4738cz1anWBqcxA+pow6I9X62AzMgWET+mPXvO4KnsYF3yVX3vU
aAEJAhAUrWFLx4f8WE2SKJA+lKRvwWpTajCuq4ZFX8nruhRThFxQg4ED7qO4JOYf
6rV6z9RMqYEOzwFRro1n9X/GZqVK3dRrdr7TA6sw0TO0N/Ml0G9IkUh0WenG4j0y
JuaulVZtAmNZ
=tU0x
-----END PGP MESSAGE-----
fp: EF643F59E008414882232C78FFA8331EEB7D6B70
- created_at: "2026-09-24T18:45:13Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQEMA1QflAioE8i3AQf+NcXza72u7+UVEhmerS7UVgOJp+/V0yM7SKrIoCcYsGeJ
xpMkPL+HPJPdb1n1DkLvdtE+reLmJluqE8zUKVmt5F8zoOWzryl9heIPTKGUn2Ob
3Q3Ii//IDevt8QlJw8ER8LV+b9TTQr8uJM7ae7BOf0q8n8MO181qKBe9vh7mnC58
Gw9eonMJbYGvlbRSdt/YSjhdE3zPvhGhyUdku3ZSzJluvz8gl81LAGSnTyi56uOg
L7KJ3MUtfoKvqmBKcrKAV+lRcr/ObIYAkNSgi1oo+/57VVQey9Iupt0bm7u8u1vf
aaIMdHimhheyiaHBrQPFA2lXTUEOBuzjP8tBxqAjndJeAYybqQmA7n5eIrlQWhfG
+neYXvtAI6GS2o7PG9g7NATw5rbTykN5DQ+4Lz7vSTuEnzQgGFUmLeGGW4WB4SER
y731AiChF7QDwV+nemn/Pz1i0P773V6p6PnxQF6Oww==
=TLNn
-----END PGP MESSAGE-----
fp: 21C9579E6503CA815A68ABD8541F9408A813C8B7
- created_at: "2026-09-24T18:45:13Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DsZXvxFXTXoQSAQdA5PHvt52vHAENUHn6Igvmx6laghevAa0f1EscWfaGBVIw
1JGnlPt8Mb4LpOWGVKS3rtFN05ZM6EFAinITwK7x4Ihu9hjh6faeUHRX7aRg5qms
0l4BQYV/F7hM9fqVvNxIjygrRYHOXnct9R7b8x/xcKNsIZPBbE5t8dwQ9OX0u+6s
TyjVZPcRod2AZkZcbFQTg/8mnF8Q8j2ruSysc7miJEgWkIZuL3aOgC9kyJL5xJpt
=j9u3
-----END PGP MESSAGE-----
fp: 9633412309CCB83BFA39BA5F2FEF746201D7FCFE
- created_at: "2026-09-24T18:45:13Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DerEtaFuTeewSAQdAPQd7h/JhnmXCse1qFMR1bTvwMWy3lKRQpdlhO+tovgQw
Vv8ZtRs/Gxkr3lWGMOvVGgWzi1glx5H2vmJpZFLhn2Vk74h3UynTBnYBl3x8fGiN
0l4BjeDWq1JSA4LwxbVcvMD3iWWKrg1DCSK8jLwD9j/vwOoN9BBvTj+8QSV9eMAj
qmU7GvieILjsGFupiaGR20gVzvmFRHzzpDkbOBiDbpXOf8V/u2jNMdbWcdwhD5HR
=1Mjc
-----END PGP MESSAGE-----
fp: 057870A2C72CD82566A3EC983695F4FCBCAE4912
- created_at: "2026-09-24T18:45:13Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMAxjNhCKPP69fARAAk8jXUa+jL/emHUaYCV3MkYu+CK/s2Mtu4W9R7Vl89iwi
mJbtdWZ+xkCcYBjO8dE8ZtKpRftjjjket44nMC5Wvk3hd6W8axCEhOV3sWMuGLfC
IwxUwxDBDFmBNptpPoBj481NrOadtnqG7wAJMeNOMbqiwTycapTB66l0Kyi6efCd
sIL6jU3oXRNxDISN8R7+n9U19+06iG0oNKH82fBwHEa9Mk+h+5W6nJwuP0etEJ6u
5OjvPyUrdiusHi3Qi+xSrlG8v1h5wVef1IyYKnmpq9HwPtUqVaGMbPR05KRQy3rV
mJeHLkNCHNB9qSW5LI/1rAiNbAyYMz5oYVmmoQ2srXL9FB9r8B+Q8QEtT+ySBAUJ
B1wNf56wWeizs6XMfgPQ5kZlVSeSPJ5Oct3IqxdAAHInI2piTmhgQ74hHqLNm3Ps
SIWgWy+sv/K+uAXLnecKCnBCptlpbyrFVFMXEp5VR+Et4qDmxT+jhRx74RmiQXM+
iwHlO0JOa1kOmhqYaCGC+ekp+3DlYDVpP4EJdeONurOkF3g7kxNgZ+OVJFbV5DEL
Pe+cXW7LHPgITdk8OTCs7VYPoiFMJVqBTR67hg19ctJxCFezVfMuHuK0T8/uM2hs
LhVlrh0ydXXUdYN+GZ+AfE4ZmYu7A6inzOsRg+F/5MTCHGn4zBsHHoDLyTpZnOzS
XgGIiY07kgIxTgIkoyxH4nB26uhhym8VJv32P0r2FuLDdbXe62jNSwjbsnCFLdqn
B4AK3U1/DVbyKfidCZ3ba0EkwEftobFUY75YUz73Kd65ivwuDuu384tWKAu7q7E=
=4ou+
-----END PGP MESSAGE-----
fp: F38C9D4228FC6F674E322D9C3326D914EB9B8F55
- created_at: "2026-09-24T18:45:13Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA46L6MuPqfJqAQ//eoAuBD/ctbrnLBh+Cd+EY8Thp1TQ9JRAeqB+qiBltjPd
78FJ8DpZ39cB2SODZT0RRE4gKan1lTsbVtCdxAfdXnS1jumeqsXQYyWECJ/fvgHU
PDhDPsykBGxmjUc8Buy+6Bu4azqko5adPc9zjLKc9kaTJcqZBcIVohtzGZ/Upzkw
Uoi48AoxJ95Z6cqyFXpEuHo+eR8veqWbFEDzcuIkAkKZ+4fFNk3Y6v0xMx0NaZnp
kTGu5LhNZ81ZbPbKMRhyMfF+YLhPiaI5UipSC2WmB3MQv0vCcV62pTMgL/u7we+D
lkoD+AkzUjpz1qcYl8suMi7LxqmaSmMlLorYgChZSgeGAeGFOSYzzFgN/6DFCYXL
1Q7KRbP6IYcE56DQN6triya7vPHlHUA/UjeV/BPcn0KIqtNBXalxWCBjFYMMEZI1
tlcfxGmw0KIIglMWHDzZhln2+zrtD7anP2lwatnj8f9UmOIdGz87RjiFndHlargu
rHa1qIfsoxXUqgXwSfv9ryoJOzBJiQvb5jjlI9JWQXs0GN96DuM8oSnPzXAr5W3O
CLx/LbyiSPvyGwqWPRqi5LaVKSiUhhivhzyMplvgqWwiLLhi83RsW1v9YrexXipH
zt5j8g68JMUmKjRhNV3Bf4pGJILYkejRPYTGt/q67w+2PL9GhjZ9hLF0kqrsavTS
XgHohCE2wuJbs+Bp+yZo3aYX/jtLFDj8XP5JL7yTizQL138x1VOoHWYYrBQGfepD
KSbKPOx9A9sa9vllmAobtkKCnJ/PpbzNXNXfnhf2RtAmnDO+sr/dyOWG4QUw1i0=
=oFbn
-----END PGP MESSAGE-----
fp: 8996B62CBD159DCADD3B6DC08BB33A8ABCF7BC4A
- created_at: "2026-09-24T18:45:13Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DQrf1tCqiJxoSAQdAvop8KmNgXpYYqwazWQAnnexQEb9260lwUnUhLuXhkUUw
lpxjpO60ndYRYbfP6iAF4uhYkvyok2SW0j081KnylXw0sdDmUg+XEiR2Nk/4yAQj
0l4BCyZVmG0J4PZl2O65RbNRwUUSKF0aYZAhAWJNG6oa8XB30w1CHJAwlFduaWZY
8nrjbfk69JTEpWcgUtMz6V7Hvk+CNBuU5k4v6Q35IDo8nhgEYrXr/WseReRmZTqF
=E4hb
-----END PGP MESSAGE-----
fp: B71138A6A8964A3C3B8899857B4F70C356765BAB
- created_at: "2026-09-24T18:45:13Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DzAGzViGx4qcSAQdAooo6HDOKpzbacvbYg1RFHnySAmxrIJlVy3ac1J5KuUQw
ZJf51XOm109+vBBCKiAHPZNmniqtWWmLn1pxQY/mCt0VPI8/EP9ROU689GWh4SLD
0lgBbsQ9zuFjf4UaTA4xE1lfaGaxv85/SpETMSjDyt3ivA5ksmdMhyUbP1F6fNgC
Ts/k5fa6F4uoQJzqr+lpwOfjeSCUk2wPEgybJvpglB1fzOQfXsEx7ztk
=hc8L
-----END PGP MESSAGE-----
fp: D2E9C0807BF681F5E164DAFC5EE1B61CD90954CD
- created_at: "2026-09-24T18:45:13Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA2pVdGTIrZI+AQ//QmrsWkhKLY+67XPFY+LZkcHW0yNq29o9WXTGPnnGKAHm
EsWOnKsa9K7cCfSu4nzMZHvN2UhXG2mi68I9vvNlfW9ax6KlSXU9rkUiBhGgsXV9
0kurZYB/X+H52xvfKP51SibVHlK1g6Z54SqYAX/vksga9u9PlJUpqOSFSxBq5pAW
L8BW0RMePHOvWiO0wPT1QmqPQe4slr89BCSYqa3c0vQQnZAtIoMDRh4NWEMQmjkz
UJzHAB4GDRQwzBpEe+Pki4mC1654oRpQ4DaZpxvbmRxDSUOcDT0dAFvlmn0iKZmr
mEzit8cXxu3QWL0uR6WFH/FtfOsKN4fNlqeh2RSERrQ0ZDALVp2Fn3xQ/E3dl6FD
sO3PjS3Z64gAGFgw0CLy2bfZPGBDZa/zxtGTCmQzEHyUbz2DIK5UCFC2Qs144mDL
AUgzikiZyoQGA4kvexABt7Jagh7+4r+nAZrekcFuQAu5Fz1PyhIA+SAf+O8xOwTW
no7/J9NZSPI11s6OJ7HVslSxuma+I1THGisf8rKGfPO7VF1+ewY5C0y8rEkCLq/Y
GR+j4AYDgHTaIk0L6o2TPWenZ5rK8c9kLpYhze2viVzPYL+6oj7FO9AYB7reCowf
+bvTKK9UoCoEEX6zTWs1nbZlxkRwqs2J3euE6m19q2EGc/ijVTdJ71xX7ulC+E3U
aAEJAhC3tEvKSEPLJGotzVoE4x8rDadfmO40ftkgjX+ns2pNrXIZHHOlJ9zfE9OJ
N9appSBaKK23x3enmyaYSqiGtJcCgZGuTIdji+p26PIkp5Oo+iVXTGLSUKWjJQaZ
q7GQcwKy8P6c
=ed7v
-----END PGP MESSAGE-----
fp: 878FEA3CB6A6F6E7CD80ECBE28506E3585F9F533
- created_at: "2026-09-24T18:45:13Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DKKbvh61jX5USAQdAYWZcr5AzRrNuWb5veea8xJyk/PYu1bAOc6Vb+oMR51ow
sJ0M3kZyyhflPYAhJGEI+FDZ4oFedDc6xn33aZk89UAf7xhaqI7sDzH5I6rY9z0Q
1GgBCQIQTNhtZO3DR+u94P/quyFD/duU6be8XX74/q9tIMPzo26vCrc/gI3naaf0
FrRfeOaLwMcfZBkAx8H8TwoPC5b27+mORi7MabMJLFpD50/CBqCkGhNpoC6xNHp2
RiVakEKXn8Gn4Q==
=dFiK
-----END PGP MESSAGE-----
fp: 41FFAF3D519CF5C039FBD8414BCC213729AF0E49
unencrypted_suffix: _unencrypted
version: 3.8.1

View file

@ -1,7 +0,0 @@
{ ... }:
{
sops = {
defaultSopsFile = ./secrets.yaml;
};
}

View file

@ -1,10 +1,7 @@
{ ... }:
{
networking = {
hostName = "ptouch-print-server";
domain = "z9.ccchh.net";
};
networking.hostName = "ptouch-print-server";
system.stateVersion = "23.11";
}

View file

@ -11,7 +11,9 @@
];
};
defaultGateway = "10.31.208.1";
nameservers = [ "10.31.208.1" ];
nameservers = [
"10.31.208.1"
];
};
systemd.network.links."10-net0" = {

View file

@ -90,7 +90,9 @@ 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;
security.pam.services.sshd.allowNullPassword = true;
# The following doesn't need to be set in order for empty passwords to work
# apparently:
# security.pam.services.sshd.allowNullPassword = true;
services.openssh.extraConfig = ''
Match User print
PubkeyAuthentication no

View file

@ -0,0 +1,7 @@
{ config, pkgs, ... }:
{
networking.hostName = "public-reverse-proxy";
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,8 @@
{ config, pkgs, ... }:
{
imports = [
./configuration.nix
./nginx.nix
];
}

View file

@ -0,0 +1,67 @@
# 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 ];
}

View file

@ -1,10 +1,7 @@
{ ... }:
{
networking = {
hostName = "public-web-static";
domain = "hosts.hamburg.ccc.de";
};
networking.hostName = "public-web-static";
system.stateVersion = "23.05";
}

View file

@ -6,7 +6,6 @@
./networking.nix
./nginx.nix
./virtualHosts
./sops.nix
./spaceapid.nix
];
}

View file

@ -1,19 +1,17 @@
{ ... }:
{
networking = {
interfaces.net0 = {
ipv6.addresses = [
{
address = "2a00:14b0:42:102::17";
prefixLength = 64;
}
];
};
defaultGateway6 = "2a00:14b0:42:102::1";
nameservers = [ "212.12.50.158" "192.76.134.90" ];
search = [ "hamburg.ccc.de" ];
networking.interfaces.net0 = {
ipv4.addresses = [
{
address = "172.31.17.151";
prefixLength = 25;
}
];
};
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";

View file

@ -1,17 +1,7 @@
{ ... }:
{
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;
}
'';
};
services.nginx.enable = true;
networking.firewall.allowedTCPPorts = [ 8443 31820 ];
networking.firewall.allowedUDPPorts = [ 8443 ];

View file

@ -1,191 +0,0 @@
spaceapid_config_ccchh_credentials: ENC[AES256_GCM,data:0fOL/gFCazBqRG2QuuRiUN/xQsfAFY+5xx5Y9PUIRMn7yh+kZjC3zrjOKyP/98x1cqwBjXTSJX9IZCiNTDS4drjhCleKTX7zsL3KluWhZwS0bey8iUYLjhaXuH2gE5h7kk18S6acpBF75JAdwmfP5Tw+ewggIt3AHtDoDWLxSHbRYsHACeyb5BC7ftAOSpqhqQTBP756XfUe+dPrvsECD6YzYRgU4JGaKKm69M97yoeghvkLgKYSxN4urelZTLGhe1tqgA6eCSznRV7+lWHcKfocjqCsbruxB4711/p7FlFD/miohT78SFe+scTLM0o7t2o2Kz4n05gJHp+1X3mp5bfyZaRceyceWkwEgxg58zjlhA3oC9CJjNAa3fPFolMVHzZJMGPVnn0t0OPTsr7VxoIJewOm/zlPxN0=,iv:5Dep+oBqAnvKiowbRbRkMGrpTEbTEbzv0tVXz6lKVdU=,tag:qOkqNCkvWrmXZ6bAtBkjSw==,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:
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IHFyYkk3dyA1WDl0
ZlFpYzlHOEYyUU00S29rYUFzMEN0WnJQRFg2V1hJNDl1Um1aOWhNCkorNWYxYVpF
WHYxb2w2MU1BUTg0SHpMMWVvdFhCT2FiaVAxelFxV1JGaDAKLS0tIEJZeDE4M3NB
NWR5b21NdzJqTVNuN1VZL2dtbktSMGE5MEtvT0Q2MWV1ejQK4QUXZDapOKiK212R
zFljy+YMiv2UwNmYPQVMs1faUR0Kanz+9Ga+vlasYVeFrh820RJGYuHf/a0gX+yN
0y06Xg==
-----END AGE ENCRYPTED FILE-----
recipient: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBQgnQAq6FUSDK8bxtYPjx3oRCAKG+xy9J3Gas2ztJk
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBIb0s1Q1FBZXRUbnl6MkFY
TlpGL25sazg2b1Z2aG5YY1R2amo1T2k0NXc4Ck1oNG9kUWl2aThKOTN3TVJxOHdh
UTlMcHhiY0Ywb2Q5czk2S3FsUHBwWm8KLS0tIGNNK2FiTnRlTElLallBY2ZvS3RC
VTlTdGQwMExTVHFkTkNvZ0UvTTVGRzgKYjtzcd6PzGw+UODLP/N6GEwV79evdBbV
zP0kZuW44qlXSWny5jPFsd4QdjvOqxrszawVdd0gGwSnkBhi9iaLmQ==
-----END AGE ENCRYPTED FILE-----
recipient: age19h7xtfmt3py3ydgl8d8fgh8uakxqxjr74flrxev3pgmvvx94kvtq5d932d
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjWkdPdCtoazZqVEZCRE56
a3FidCt3NzY4MlpCQ21CRTh0eHVqQmNYUjJVCnhMSUVnVE5xZm56OEtkdWsxNEZx
WXZtYVgvOUd3U1FncUZhV05DTjg4b0EKLS0tIERDOFpRa1RoakJqbDFwUGVORnRN
ZXJJSnErWVBuSmx0eHdmUVdCd3VzSU0K9D2NbKWKGsBXCq1Le1Th3K5Vhd8xKyg4
y249KtohVeG4ohBYDkUgo9BBHdD0emldWY0vdtZoFWL4pNjVmPxt/Q==
-----END AGE ENCRYPTED FILE-----
recipient: age19s7r8sf7j6zk24x9vumawgxpd2q8epyv7p9qsjntw7v9s3v045mqhmsfp0
lastmodified: "2026-08-11T13:23:00Z"
mac: ENC[AES256_GCM,data:jZ9G+EcoGBfWv3uYVkk6DF3HJxHpxMYZQW/4BQd4V/YrluZp5dg4Bw/coRb3ka8n1EBLj+hxPSJyCtXwRlW1sMUvl4mbKpMTe5dtd67lpDMXbQ/3AA53cD/52Mlvv76Ywff7kjx4XhbBCnYEdBfMABcVLPd/rgmKtMKRtaYLjmQ=,iv:yPwKgsg2JgqB3QT7GG2+UlPlP+REOjlo/FKYwgmctZw=,tag:944RbdkitJ37aEmcrX7iQQ==,type:str]
pgp:
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMAxK/JaB2/SdtAQ/+I78vHU6uDl+1aPkKC2ExESx1kjMWffeIJzCkOT1j2iMr
qFBPHUwpWzGxJvtaVFYfYOE81+SuiBf4WT5YmzNhXta9Sl7wxof76MkdSEpbOpZy
8t7L+Zlbj1GLawlZClBIL28Gyus1yj2uEmUrr0CbC/aII64K0b7Y7cfh7O7FY54O
JDYgY0uCJVbGvcLpOJ7NN6olk2qmMqlrORauh37O5nLtZALaZVUKr24PL9aKUtjt
j7/gpEiqBWHvRywrUavJ+7YR2n6k7oRUZwuLdIjdSmuxCiro61xd9LPf5cf1Lyl5
K87Qog0SssuX9H+mRMyne09MjQHQjMLZbeRnrIf49LPJM+Zjp5cdh3GfKYQcHJRp
dhkrEwniG7RLZjZuhFIvtbn63iumgMvxDr4XQ2tYjL1F4K5Sr8rPTcj3lY7qiWTG
zrkgbgZp3A7mgwX5STAdioRoSEhyzSUiSVp2sKGL9n3hvEagMn/x+9JPwmkECeDi
YQ6Rh9+o4AxVx4jHkp+ZXDmLsZtz4/yi+1uH5Y7Uw15UfEweBR9Lkk47ISZz+jBk
6AWuvqFQjGP5YqCronT+JnS3rNd1A6FG45mY1FWx4yrlvwInIIG1FG5AbCTljYzt
Htw+a1Y0rGNK/NWy82bI6NzlFOaYjP+MRfWhGcUJ9S6K1BwfsLMmescAM/fqe5jU
aAEJAhBE8lQwLFmUsaSlZxFY6e5VhJZZe6rV76H2dKDzmFrnzJMTRHLfS/7Jio8w
V+s07XIn3nUWlEAYw0s/fTyeZt+4C3BbGHpWqR0mfXyfQ1IrVUIyniPoQES6klxb
0vqnk3MdG775
=gkyj
-----END PGP MESSAGE-----
fp: EF643F59E008414882232C78FFA8331EEB7D6B70
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQEMA1QflAioE8i3AQf+OPoy4ml8rFHFjRCdFHGoGFNdLn0d+nwf3Jt1bS5PwhUz
jDpKNgHairYl7wRSvMEJKz+M+EM9PzfRbLYZT8hKZ5CPagnSc51Dv3pb3RKoE2UF
3bwDp6ztZptn7r7WWRGEbyloQxhwT+1dZuyZ6T0awO/cuwtzQCgaDEEI0ilQczVe
TWELdjZ9cGZW+voEDYyfPoLxlnZUHkwWjUGeTfsIYbsBk+tYxaOSPPwtpN4/Kuf9
cxR12W9ey26dkVa2k7L/PyDlUNnybahxxI/a+0V0z9kxgAby0l9OQp48YVDhTlM+
Td60+jiEN/AUPBlSoyD0m6SALO3SLtxhYYkzBoElOdJeARGMbckAndk39/vq0XeM
VGmEcdPSY8epRUW41AZZ93Hw1gK4mU5O0WM8s1q2QjwVbNsb2U9Kl8NfeKYKSmv9
TbWxmDijHZP1WBouD2Nnt2fubN1f7Hn2z7iB3Lz4JQ==
=x3ci
-----END PGP MESSAGE-----
fp: 21C9579E6503CA815A68ABD8541F9408A813C8B7
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DsZXvxFXTXoQSAQdA1kqcsYnmxzdJRFqlJ7YsBnT2jEdBjcYuKc1xbOZnbm8w
giLt/oK2mtHsZzTBHtK56H+Luv6CpXx62EG8VXvyo4vBQGO2i6AUCaUwHL27O6MV
0l4BqOQW86N4vNQgQZazWcNw38VRCYNh5RaAWQZfu2bmRy+3vYkbbio7k7Gihxbh
1otYyLG6WvKahU4eSSiGiPAAIsjdkz7qdrsh/SOEL2y0E+NEsm4toJgg2+krpNMU
=EhAh
-----END PGP MESSAGE-----
fp: 9633412309CCB83BFA39BA5F2FEF746201D7FCFE
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DerEtaFuTeewSAQdA3vmV3GVLiANIRhtHyZBO9v6zKiDj2xAnQzHIjPFnYhIw
YctBRQvccnLZfUnTFl+H0g/tyxcFe71UY01EWGXfIVn3jk1urYHme4FjKUlfmWs+
0l4B0GVgPEN/g4MR46yt3u9GRe7gR79DqzOiwFEGI1Ay24GKynwcx4zADbpBTrTs
1lm2EXF4cm2jIHFls7NUuDNIABkH3VhXc6Tq3o11Ypn7PRS3mPZ88mz4dgxNLmmw
=DmZZ
-----END PGP MESSAGE-----
fp: 057870A2C72CD82566A3EC983695F4FCBCAE4912
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMAxjNhCKPP69fARAAhQPx9gAYKVe4lkpymsf2a2QRwHCthvYICrrXqCwKJNxI
Bgb/qhVIxE0T/hutQWtsEZVfFl1v1/5Z+Sw1wUwIjJgxRq4UdAkIQasD+PIi9plz
iVYPD3J7GkhAZp8R22YXcC/Du65qyw9zaJCIwo87oEBdxS19p6/Pqo1OQhF/9AIN
sbEQHGOYuZuZzfUUIJbdptD7AOejVtVpZCSfvRtRpouJjQXiJIXkWxEjVLFkS08y
mXv2VEip8rlyE/B/IlxszQ3I2IUjAKTOBdIzBGaHJcsn2rZXsAs3OjwSxBNSKdbj
tuEQQ6Bl/YXv60bJir++ElEbWn+sLdjfsXigjfL88h2CZt47qtq7Mfo1MMkOf/3A
XDPN4ht45wG7uvykJK2gzuj1wmiWt7+uK+5/FnaDMItwr5Gk6TJRCTXH7AvD1GN6
jnw2qiaap3SAvdMMpAtX7CGG/iWDVnI1dceY3WmNTsk8541WVv7gPkaQKIgspYk+
DV4MO/bzlXKs5UOEe57vZqrQd6gUUUJlwb8wdg+6EtmAZgvywT+EhQXzDnSYyDem
ujgqmlCa/wS7K+CbfQNb4AXhBxAL0I8KPihPSDVt3Rb7bd33029QB88ySellPd0e
75ETK3pAm8zVPdho+Om3RAptJxj+7UmDfyu51Q7n4GektTpRL+/mOSIusS96jarS
XgG3XYOWC1D3S9y5VC78YakMZ8tI6Mhpv7XweBhXEBqYAvhpb5BQdnq4wqldck/u
UJ8jdvdl8lWV3qP8VBH/MRfTSiz0GLF71SallSmJoaeBoIX54n9qpQwKu5oU9aE=
=nyzO
-----END PGP MESSAGE-----
fp: F38C9D4228FC6F674E322D9C3326D914EB9B8F55
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA46L6MuPqfJqARAAn4eH4JuZ2bvb3tQTqxjHrLiZwWUXfq9c/d5Do22n+pq5
02kIo1cBkjnFFhQE1cvRk1qyj7Pl554GP7KDktgqhu/MV8H8DEYfTv84jErN/HXv
VQMu5tnTEYiwDXobuoM1zJCTWR/eWKw1TL9TyQ37OswMU/dDyJdf85/4wHrBWDUT
OadL6l7jk9H3dH21wPNkuNxaNC0EosRHjWIpUW5LmocOz+Ba63a6Qml11vZQIHk0
iAbzbr7SPzsQYNaxEFcEoYfr42lw9aaJDF3Tn91BaLzZjHJ0MebTm+dckLianUIy
/YtyjnfA1KARx87fK9MUVg6WkUXO9K+iaep2fVxRSqSfZCnX92+JOqcsUKlSvIeF
XyFKYrrKIBqYpWisdaRbocU57Oh1gGYiI/CPvF37V6GpEN6TMTmrjtWdadvLGU84
hH86AAK3ORCLqWc0EBqD/gPDuPQpLCjJz5jPP1QgtAXF6jvxIajW8NvJhHPSFLka
Uz6C8YiADYx/1D3VJ3CtpoJ4ZSa/xgKJJrsLEpooLOcimDTaOCgXI7fsY8wXIcTo
Tdf1w7G/JyTAjTpUFikjfAtwzm5pKkzJ96r7V6E10NKGOIx9Q5x/+Hz79jjuaVi8
tL99kD71lCJ/OEXfLs92ZUAi8xBVS4/mpiIxek/HyfZvjGjgFWjVZ2gpzPNHi67S
XgFHmRGdj5HnJS1KRwevPrDI9SRlBneu03ivBo5jvaOaFTbKfMywRtb1bubtsIJ6
b13sbGx3wK9ylKRi/u7Wo81BQGvABDYYbaSTm2R6A86ig6uUKSmp062pMNVkdwM=
=nYuV
-----END PGP MESSAGE-----
fp: 8996B62CBD159DCADD3B6DC08BB33A8ABCF7BC4A
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DQrf1tCqiJxoSAQdABycjGTy8xEbkDILJSQ1QpSF555mzDxcrNLvfj1/Y7j8w
Q0sqz8AbRMYmHcfoJsSgqNPzX7fQadT6LrAx7NLDWPEaR03ovdl2g/bHMeTL6q2y
0l4Bk8IdSl9frBBKr2UOKbhNHuTVaPRqyEjjI5mVyHY+0LHQPIn6yfIGk1fNgmYS
xH/pghg5dZdGNQz4FkxKBA7P0CjCz1T5qMaUizPhZTjff25CqPLXORbpGQhc1W+G
=QKYi
-----END PGP MESSAGE-----
fp: B71138A6A8964A3C3B8899857B4F70C356765BAB
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DzAGzViGx4qcSAQdAOYA8y/QEaYJpj81erxGtnRou4WzmHWblGFwHFBM4NTEw
UJGnJ5F4XHDU1kiHwGJkmVdNAaTZILQjfPZGPH/lDLeG4bXQmpht/mwekh4UbPg+
0lgBxGWdLSjhz4uE+LpfdRhpyrrcdJ3v7t/R5vd1EfrjY5CiuzbIg4H+b65D/wtJ
B+p7J+gdxHp6BOqYFS4Pyku2xajIddlPjhE9f6BHu6HmN+H0hczjFWYN
=o8gE
-----END PGP MESSAGE-----
fp: D2E9C0807BF681F5E164DAFC5EE1B61CD90954CD
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA2pVdGTIrZI+ARAAvNGqj9o1CZWPRA92ARJoeyP2oVJXUyZTuv+m5nWufee8
BL2RcMCeMbXGCzMm++Sr+NwEQVGeJdKON7A1au4DgZskr4+V88/dl/d0YRJRTW8Q
Wff/gqXzwP0lotS8GFtMIRuwHhlHRBOPEtC2W/TomNwUU73N7yDYZZNXtUefKD3+
U7m9ITAf/VRGE9VzO0AgfpEVTuy1goye6qLt5jauk+NL4mcL5Rc7Mge4e0QHWyZF
EWAjXPdN9YvL4VrI3tLrpRpScgKrGX8OFdn8XwR6Uhy0N9YUnyWDYEkmEulbA+T0
W/1KvlJ6UAGqPCEcQwf4mWkxBVWpvfTnCtU7WUwUF3R/iN/C1oT8O7cRfELj3vPH
dQzo2Bkk2D1g2cJvz/scG5BDWnxSNBf8s6s4Lk5pyFDq/wIITeKTyuQzCwrMgxlq
jsWx5yKGtKD33c+nJVdtQia9sE90I2bvzK5Ms7PzJo/ePZMWxseG7myMlKxMlnAn
vJ2bovyuaN5GQHK8FQQqMlIdiX15mujc20xBjM4TUByCX4Bf5aGp9LQUz2go4q47
1LX4M/N3gLrLQ48BVI6MTOa0iu2M62WcHyBUBVxoi9MqGxXuqgw4koBq2NPdRDgO
VFlGg7DxFkSS16HAUoH+Rr7NLcOjf/verp8fZ8B3Dv1ekbNncGEcGzpBg/MzdHnU
aAEJAhBrzWp0dIWUI2gBHC7cGIXc4J1BvLafNT5elcwONUJaPTsbdIvC7cvSALkf
OSN9DfEJDfnTUHZfuh3kB/pmOjeqMwBmYDWWHxakqs/H06wbeWzIb5tonSDHmtA+
m6QDMQ+4VlN8
=EKZZ
-----END PGP MESSAGE-----
fp: 878FEA3CB6A6F6E7CD80ECBE28506E3585F9F533
- created_at: "2026-09-24T18:45:14Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DKKbvh61jX5USAQdAq3pzRuhl99Jshep49dS0lyNKi06ZEvGd/TELQM56oQgw
wMGmqictTPhYqvOUaQxtFZkuZcYmC+G0Az4j7COZuJa2PxrfubPMTqztPn8s2fhH
1GgBCQIQw5Q4dUgUHxpGTDnXOue14UHm6vYtiHnl0nFDv0b9mLWRSvYLdUZ+jbDL
MlMl1ntxLS1Kko+UTNR2kKC5JQAPcWT2P1zlqb5if7/H5eHwNpsBXTB+WrXXEfkQ
tdXY71KRXL569Q==
=PnlM
-----END PGP MESSAGE-----
fp: 41FFAF3D519CF5C039FBD8414BCC213729AF0E49
unencrypted_suffix: _unencrypted
version: 3.13.3

View file

@ -1,7 +0,0 @@
{ ... }:
{
sops = {
defaultSopsFile = ./secrets.yaml;
};
}

View file

@ -2,6 +2,26 @@
"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",
@ -14,6 +34,26 @@
}
],
"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": "%",
@ -25,13 +65,12 @@
]
}
],
"ext_3d_printer_busy_state": [
"CO2": [
{
"sensor_data": {
"unit": "bool",
"location": "Loetschlauch",
"name": "mk4",
"description": "Prusa mk4 busy state"
"unit": "ppm",
"location": "Hauptraum",
"description": "Sensor im Hauptraum (Typ: SCD41)"
},
"allowed_credentials": [
"club-assistant"
@ -39,34 +78,9 @@
},
{
"sensor_data": {
"unit": "bool",
"unit": "ppm",
"location": "Loetschlauch",
"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"
"description": "Sensor im Lötschlauch (Teil der Werkstatt, Typ: SCD41)"
},
"allowed_credentials": [
"club-assistant"
@ -77,7 +91,7 @@
"state": {
"open": {
"allowed_credentials": [
"dooris"
"dooris-hauptraum"
]
}
}

View file

@ -4,7 +4,7 @@
"14"
],
"space": "CCCHH",
"logo": "https://hamburg.ccc.de/images/logo.svg",
"logo": "https://next.hamburg.ccc.de/images/logo.svg",
"ext_ccc": "erfa",
"url": "https://hamburg.ccc.de/",
"location": {
@ -14,6 +14,7 @@
},
"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",

View file

@ -1,20 +1,19 @@
{ pkgs, ... }:
let
version = "v0.1.0";
spaceapidSrc = pkgs.fetchgit {
spaceapidSrc = builtins.fetchGit {
url = "https://git.hamburg.ccc.de/CCCHH/spaceapid.git";
rev = version;
hash = "sha256-2SDhliltzyydPPZdNn/htDydiK/SHQcYyG/dQ0EyFrY=";
ref = "main";
rev = "bbeb0d0e2b4538faed275b9891fb55149bc3a2f8";
};
spaceapid = pkgs.buildGoModule rec {
pname = "spaceapid";
inherit version;
version = "main";
src = spaceapidSrc;
ldflags = [
"-X main.version=${version}"
"-X main.version=${version}-${spaceapidSrc.rev}"
];
# Since spaceapid doesn't have any dependencies, we can set this to null and
@ -39,7 +38,7 @@ in
After = [ "network.target" "network-online.target" ];
};
serviceConfig = {
ExecStart = "${spaceapid}/bin/spaceapid -c ${spaceapidConfigResponse},${spaceapidConfigDynamic},/run/secrets/spaceapid_config_ccchh_credentials";
ExecStart = "${spaceapid}/bin/spaceapid -c ${spaceapidConfigResponse},${spaceapidConfigDynamic},/secrets/spaceapid-config-ccchh-credentials.secret";
User = "spaceapi";
Group = "spaceapi";
Restart = "on-failure";
@ -48,10 +47,14 @@ in
wantedBy = [ "multi-user.target" ];
};
sops.secrets."spaceapid_config_ccchh_credentials" = {
mode = "0440";
owner = "spaceapi";
group = "spaceapi";
restartUnits = [ "spaceapid.service" ];
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";
};
};
}

View file

@ -1,74 +0,0 @@
{ ... }:
let
domain = "bildungsurlaub.hamburg.ccc.de";
dataDir = "/var/www/${domain}";
deployUser = "bildungsurlaub-website-deploy";
in
{
services.nginx.virtualHosts = {
"acme-${domain}" = {
enableACME = true;
serverName = "${domain}";
listen = [
{
addr = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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;
port_in_redirect off;
'';
};
};
systemd.tmpfiles.rules = [
"d ${dataDir} 0755 ${deployUser} ${deployUser}"
];
users.users."${deployUser}" = {
isNormalUser = true;
group = "${deployUser}";
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINDVK+4GeUtFGzRNrcoHagjB+/4z3GyrtHuIDQP54j4i mailto:dante@briefhaus.de"
];
};
users.groups."${deployUser}" = { };
}

View file

@ -14,10 +14,6 @@ in
serverName = "branding-resources.hamburg.ccc.de";
listen = [
{
addr = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
@ -30,12 +26,6 @@ in
useACMEHost = "branding-resources.hamburg.ccc.de";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
addr = "0.0.0.0";
port = 8443;

View file

@ -1,25 +1,12 @@
{ 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-${domain}" = {
"acme-c3cat.de" = {
enableACME = true;
serverName = "${domain}";
serverAliases = [
"www.${domain}"
];
serverName = "c3cat.de";
listen = [
{
addr = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
@ -27,17 +14,11 @@ in {
];
};
"www.${domain}" = {
"c3cat.de" = {
forceSSL = true;
useACMEHost = "${domain}";
useACMEHost = "c3cat.de";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
addr = "0.0.0.0";
port = 8443;
@ -47,48 +28,7 @@ in {
];
locations."/" = {
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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";
return = "302 https://wiki.hamburg.ccc.de/club:c3cat:start";
};
extraConfig = ''
@ -103,17 +43,4 @@ in {
'';
};
};
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}" = { };
}

View file

@ -1,111 +0,0 @@
{ pkgs, ... }:
let
domain = "c3dog.de";
dataDir = "/var/www/${domain}";
deployUser = "c3dog-website-deploy";
in {
security.acme.certs."${domain}".extraDomainNames = [ "www.${domain}" ];
services.nginx.virtualHosts = {
"acme-${domain}" = {
enableACME = true;
serverName = "${domain}";
serverAliases = [
"www.${domain}"
];
listen = [
{
addr = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"www.${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
addr = "0.0.0.0";
port = 8443;
ssl = true;
proxyProtocol = true;
}
];
locations."/" = {
return = "302 https://c3dog.de$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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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;
'';
};
};
systemd.tmpfiles.rules = [
"d ${dataDir} 0755 ${deployUser} ${deployUser}"
];
users.users."${deployUser}" = {
isNormalUser = true;
group = "${deployUser}";
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB7iXsVArl4SbDczb4U3zGkZCiVO/lfn12gkOEOnKmEX deploy key for c3dog.de"
];
};
users.groups."${deployUser}" = { };
}

View file

@ -1,136 +0,0 @@
{ ... }:
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 = "[::]";
port = 31820;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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}" = { };
}

View file

@ -1,113 +0,0 @@
{ ... }:
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 = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"cryptoparty.hamburg.ccc.de" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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}" = { };
}

View file

@ -2,34 +2,12 @@
{
imports = [
./bildungsurlaub.hamburg.ccc.de.nix
./branding-resources.hamburg.ccc.de.nix
./c3cat.de.nix
./c3dog.de.nix
./cpu.ccc.de.nix
./cryptoparty-hamburg.de.nix
./docs.c3voc.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
./infra-docs.hamburg.ccc.de.nix
./spaceapi.hamburg.ccc.de.nix
./staging.c3cat.de.nix
./staging.c3dog.de.nix
./staging.cryptoparty-hamburg.de.nix
./staging.docs.c3voc.de.nix
./staging.hacker.tours.nix
./staging.hackertours.hamburg.ccc.de.nix
./staging.hamburg.ccc.de.nix
./staging.infra-docs.hamburg.ccc.de.nix
./www.hamburg.ccc.de.nix
./diday.org.nix
./staging.diday.org.nix
./historic-easterhegg
./ueberwachungsfrei-kundgebung.nix
./didays.de.nix
./staging.didays.de.nix
];
}

View file

@ -1,131 +0,0 @@
{ ... }:
let
domain = "diday.org";
dataDir = "/var/www/${domain}";
deployUser = "diday-website-deploy";
in
{
services.nginx.virtualHosts = {
"acme-${domain}" = {
enableACME = true;
serverName = "${domain}";
listen = [
{
addr = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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}" = { };
}

View file

@ -1,73 +0,0 @@
{ pkgs, ... }:
let
domain = "didays.de";
dataDir = "/var/www/${domain}";
deployUser = "didays-deploy";
in {
services.nginx.virtualHosts = {
"acme-${domain}" = {
enableACME = true;
serverName = "${domain}";
listen = [
{
addr = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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;
port_in_redirect off;
'';
};
};
systemd.tmpfiles.rules = [
"d ${dataDir} 0755 ${deployUser} ${deployUser}"
];
users.users."${deployUser}" = {
isNormalUser = true;
group = "${deployUser}";
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBEcEfs6qiUwjlqsHwzS1WvaVQOPEhRRup5RE+K1wZ72 deploy key for didays"
];
};
users.groups."${deployUser}" = { };
}

View file

@ -1,73 +0,0 @@
{ pkgs, ... }:
let
domain = "docs.c3voc.de";
dataDir = "/var/www/${domain}";
deployUser = "c3vocdocs-website-deploy";
in {
services.nginx.virtualHosts = {
"acme-${domain}" = {
enableACME = true;
serverName = "${domain}";
listen = [
{
addr = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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;
port_in_redirect off;
'';
};
};
systemd.tmpfiles.rules = [
"d ${dataDir} 0755 ${deployUser} ${deployUser}"
];
users.users."${deployUser}" = {
isNormalUser = true;
group = "${deployUser}";
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMQbTkwHeNiq73XMbahRsyIWCzVLuN1Cu+f7XZMUh/6S deploy key for docs.c3voc.de"
];
};
users.groups."${deployUser}" = { };
}

View file

@ -1,125 +0,0 @@
{ config, pkgs, ... }:
let
elementAdminVersion = "0.1.11";
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-tSUTDPspQJjvP1KN4nUr4LYyjNQFj4pKMMA8JmavIxo=";
};
nativeBuildInputs = [
pkgs.nodejs
pkgs.pnpm.configHook
];
pnpmDeps = pkgs.pnpm.fetchDeps {
inherit (finalAttrs) pname version src;
fetcherVersion = 2;
hash = "sha256-Hf4PWey5bczSNbc3QQ9z9X3OVUZ7VHXw7BHGQqJWPac=";
};
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 = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
virtualHosts."element-admin.hamburg.ccc.de" = {
forceSSL = true;
useACMEHost = "element-admin.hamburg.ccc.de";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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 ];
}

View file

@ -1,10 +1,10 @@
{ pkgs, ... }:
let
elementWebVersion = "1.12.18";
elementWebVersion = "1.11.59";
element-web = pkgs.fetchzip {
url = "https://github.com/element-hq/element-web/releases/download/v${elementWebVersion}/element-v${elementWebVersion}.tar.gz";
sha256 = "sha256-RvPJg28hgOgFs0GFZ9EPypQkUPkAns0alXYJeNst4Bk=";
url = "https://github.com/vector-im/element-web/releases/download/v${elementWebVersion}/element-v${elementWebVersion}.tar.gz";
sha256 = "sha256-iVTd5zWUJh9wkbKMh+5hq0ucQaLLY29w1xCLxDIdQ18=";
};
elementSecurityHeaders = ''
# Configuration best practices
@ -24,10 +24,6 @@ in
serverName = "element.hamburg.ccc.de";
listen = [
{
addr = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
@ -40,12 +36,6 @@ in
useACMEHost = "element.hamburg.ccc.de";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
addr = "0.0.0.0";
port = 8443;

View file

@ -1,78 +0,0 @@
{ 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 = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
locations."/shop" = {
return = "302 https://tickets.hamburg.ccc.de";
};
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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}" = { };
}

View file

@ -1,87 +0,0 @@
{ 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 = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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}" = { };
}

View file

@ -7,10 +7,6 @@
serverName = "hamburg.ccc.de";
listen = [
{
addr = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
@ -21,15 +17,8 @@
"hamburg.ccc.de" = {
forceSSL = true;
useACMEHost = "hamburg.ccc.de";
default = true;
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
addr = "0.0.0.0";
port = 8443;
@ -94,19 +83,6 @@
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";
};
# Redirects for blog post edits.
locations."/blog/2026/05/23/der-ccchh-sagt-nein-zu-olympia-in-hamburg" = {
return = "302 https://hamburg.ccc.de/blog/2026/05/31/der-ccchh-sagt-nein-zu-olympia-in-hamburg/";
};
locations."/blog/2026/05/23/der-ccchh-sagt-nein-zu-olympia-in-hamburg/" = {
return = "302 https://hamburg.ccc.de/blog/2026/05/31/der-ccchh-sagt-nein-zu-olympia-in-hamburg/";
};
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
@ -118,8 +94,6 @@
real_ip_header proxy_protocol;
error_page 404 /404.html;
port_in_redirect off;
'';
};
};

View file

@ -1,12 +0,0 @@
{ ... }:
{
imports = [
./eh03.nix
./eh05.nix
./eh07.nix
./eh09.nix
./eh11.nix
./eh20.nix
];
}

View file

@ -1,123 +0,0 @@
{ 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 = "[::]";
port = 31820;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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;
'';
};
};
}

View file

@ -1,122 +0,0 @@
{ 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 = "[::]";
port = 31820;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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;
'';
};
};
}

View file

@ -1,128 +0,0 @@
{ 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 = "[::]";
port = 31820;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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;
'';
};
};
}

View file

@ -1,127 +0,0 @@
{ 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 = "[::]";
port = 31820;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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;
'';
};
};
}

View file

@ -1,128 +0,0 @@
{ 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 = "[::]";
port = 31820;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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;
'';
};
};
}

View file

@ -1,113 +0,0 @@
{ 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 = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"www.eh20.easterhegg.eu" = {
forceSSL = true;
useACMEHost = "eh20.easterhegg.eu";
serverAliases = [
"eh20.hamburg.ccc.de"
];
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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;
'';
};
};
}

View file

@ -1,73 +0,0 @@
{ pkgs, ... }:
let
domain = "infra-docs.hamburg.ccc.de";
dataDir = "/var/www/${domain}";
deployUser = "infra-docs-deploy";
in {
services.nginx.virtualHosts = {
"acme-${domain}" = {
enableACME = true;
serverName = "${domain}";
listen = [
{
addr = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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;
port_in_redirect off;
'';
};
};
systemd.tmpfiles.rules = [
"d ${dataDir} 0755 ${deployUser} ${deployUser}"
];
users.users."${deployUser}" = {
isNormalUser = true;
group = "${deployUser}";
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINfwfy9f3R/tDOiUeG5DA9oIGDDEAP270MqFG3V1P11L deploy key for infra-docs"
];
};
users.groups."${deployUser}" = { };
}

View file

@ -7,10 +7,6 @@
serverName = "spaceapi.hamburg.ccc.de";
listen = [
{
addr = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
@ -23,12 +19,6 @@
useACMEHost = "spaceapi.hamburg.ccc.de";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
addr = "0.0.0.0";
port = 8443;

View file

@ -1,70 +0,0 @@
{ 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 = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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.
}

View file

@ -1,70 +0,0 @@
{ pkgs, ... }:
let
domain = "staging.c3dog.de";
dataDir = "/var/www/${domain}";
deployUser = "c3dog-website-deploy";
in {
services.nginx.virtualHosts = {
"acme-${domain}" = {
enableACME = true;
serverName = "${domain}";
listen = [
{
addr = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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}"
];
# c3dog deploy user already defined in c3dog.de.nix.
}

View file

@ -1,110 +0,0 @@
{ ... }:
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 = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"staging.cryptoparty.hamburg.ccc.de" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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.
}

View file

@ -1,83 +0,0 @@
{ 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 = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
addr = "0.0.0.0";
port = 8443;
ssl = true;
proxyProtocol = 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;
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" = {};
}

View file

@ -1,72 +0,0 @@
{ pkgs, ... }:
let
domain = "staging.didays.de";
dataDir = "/var/www/${domain}";
deployUser = "didays-deploy";
in {
services.nginx.virtualHosts = {
"acme-${domain}" = {
enableACME = true;
serverName = "${domain}";
listen = [
{
addr = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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}"
];
# didays deploy user already defined in didays.de.nix.
}

View file

@ -1,72 +0,0 @@
{ pkgs, ... }:
let
domain = "staging.docs.c3voc.de";
dataDir = "/var/www/${domain}";
deployUser = "c3vocdocs-website-deploy";
in {
services.nginx.virtualHosts = {
"acme-${domain}" = {
enableACME = true;
serverName = "${domain}";
listen = [
{
addr = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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}"
];
# docs.c3voc deploy user already defined in docs.c3voc.de.nix.
}

View file

@ -1,71 +0,0 @@
{ 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 = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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.
}

View file

@ -1,73 +0,0 @@
{ 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 = "[::]";
port = 31820;
}
{
addr = "0.0.0.0";
port = 31820;
}
];
};
"${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
listen = [
{
addr = "[::]";
port = 8443;
ssl = true;
proxyProtocol = true;
}
{
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.
}

Some files were not shown because too many files have changed in this diff Show more