diff --git a/.sops.yaml b/.sops.yaml index 31d03aa..fd76726 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -1,11 +1,38 @@ +# SOPS configuration for StuRa HTW Dresden infrastructure +# +# This file defines which keys can decrypt which secrets. +# Add GPG public keys (.asc files) or age keys to keys/hosts/ and keys/users/ +# to grant decryption access to hosts and users respectively. + keys: - - &goeranh age16m8vvvpw4azfy6gygtstyyj6nd2sf848f7f7argaghwhct38muxsgxpeek - - &gradient age1kfxhahmxprheer63shv68slpmk5qz29nyx3kp4q6n879zz9ha34q04n50x + # Admin/user keys - add GPG public keys here + # Example: + # - &user_admin_key age1... or pgp fingerprint + + # Host keys - add host-specific keys here + # Example: + # - &host_proxy_key age1... or pgp fingerprint + # - &host_git_key age1... or pgp fingerprint + +# Define which keys can access which files +creation_rules: + # Default rule: all secrets can be decrypted by admin keys + - path_regex: secrets/.*\.yaml$ + # key_groups: + # - pgp: + # - *user_admin_key + # - age: + # - *user_admin_key # Host-specific secrets (example) -creation_rules: - - path_regex: hosts/gradient/secrets.sops.yaml$ - key_groups: - - age: - - *gradient - - *goeranh + # - path_regex: secrets/proxy/.*\.yaml$ + # key_groups: + # - pgp: + # - *user_admin_key + # - *host_proxy_key + + # - path_regex: secrets/git/.*\.yaml$ + # key_groups: + # - pgp: + # - *user_admin_key + # - *host_git_key diff --git a/default.nix b/default.nix index 17b85ef..1a1f679 100644 --- a/default.nix +++ b/default.nix @@ -37,16 +37,9 @@ in experimental-features = [ "nix-command" "flakes" - "blake3-hashes" ]; # trusted-users = [ "administration" ]; auto-optimise-store = true; - trusted-substituters = [ - "https://gradient.adm.htw.stura-dresden.de/cache/stura" - ]; - trusted-public-keys = [ - "gradient.adm.htw.stura-dresden.de-stura:rVy7JDos8CTvKJsrotP2/y/ICbCNv69HKy0Dfsgrafs=" - ]; }; optimise.automatic = true; gc = { diff --git a/flake.lock b/flake.lock index 0a573e0..4e0f8b8 100644 --- a/flake.lock +++ b/flake.lock @@ -8,9 +8,7 @@ "flake-parts": "flake-parts", "flake-utils": "flake-utils", "napalm": "napalm", - "nixpkgs": [ - "nixpkgs" - ], + "nixpkgs": "nixpkgs", "pyproject-build-systems": "pyproject-build-systems", "pyproject-nix": "pyproject-nix", "systems": "systems", @@ -79,21 +77,6 @@ "type": "gitlab" } }, - "crane": { - "locked": { - "lastModified": 1777335812, - "narHash": "sha256-bEg5xoAxAwsyfnGhkEX7RJViTIBIYPd8ISg4O1c0HFc=", - "owner": "ipetkov", - "repo": "crane", - "rev": "5e0fb2f64edff2822249f21293b8304dedaaf676", - "type": "github" - }, - "original": { - "owner": "ipetkov", - "repo": "crane", - "type": "github" - } - }, "disko": { "inputs": { "nixpkgs": [ @@ -185,24 +168,6 @@ "type": "github" } }, - "flake-utils_2": { - "inputs": { - "systems": "systems_2" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "git-hooks": { "inputs": { "flake-compat": [ @@ -251,34 +216,12 @@ "type": "github" } }, - "gradient": { - "inputs": { - "crane": "crane", - "flake-utils": "flake-utils_2", - "nixpkgs": "nixpkgs" - }, - "locked": { - "lastModified": 1777807825, - "narHash": "sha256-LIHC5ayGLbEXY7wBrd71EE12xZDBltYqeE4qdEvWbC0=", - "owner": "wavelens", - "repo": "gradient", - "rev": "0f5779845044d2a39e5f599f781d6cfb9248a219", - "type": "github" - }, - "original": { - "owner": "wavelens", - "repo": "gradient", - "type": "github" - } - }, "mailserver": { "inputs": { "blobs": "blobs", "flake-compat": "flake-compat_2", "git-hooks": "git-hooks", - "nixpkgs": [ - "nixpkgs" - ] + "nixpkgs": "nixpkgs_2" }, "locked": { "lastModified": 1773912645, @@ -323,11 +266,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1777268161, - "narHash": "sha256-bxrdOn8SCOv8tN4JbTF/TXq7kjo9ag4M+C8yzzIRYbE=", + "lastModified": 1771848320, + "narHash": "sha256-0MAd+0mun3K/Ns8JATeHT1sX28faLII5hVLq0L3BdZU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1c3fe55ad329cbcb28471bb30f05c9827f724c76", + "rev": "2fc6539b481e1d2569f25f8799236694180c0993", "type": "github" }, "original": { @@ -352,29 +295,29 @@ "type": "github" } }, - "nixpkgs-unstable": { + "nixpkgs_2": { "locked": { - "lastModified": 1777268161, - "narHash": "sha256-bxrdOn8SCOv8tN4JbTF/TXq7kjo9ag4M+C8yzzIRYbE=", - "owner": "nixos", + "lastModified": 1773831496, + "narHash": "sha256-JW2/QPyCVzmouqEp1H9kNa8JXd7xEhlam9sy3TYfhDY=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "1c3fe55ad329cbcb28471bb30f05c9827f724c76", + "rev": "826430a188181a750ffa5948daff334039c5d741", "type": "github" }, "original": { - "owner": "nixos", - "ref": "nixos-unstable", + "owner": "NixOS", + "ref": "nixos-25.11-small", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_2": { + "nixpkgs_3": { "locked": { - "lastModified": 1777077449, - "narHash": "sha256-AIiMJiqvGrN4HyLEbKAoCSRRYn0rnlW5VbKNIMIYqm4=", + "lastModified": 1776734388, + "narHash": "sha256-vl3dkhlE5gzsItuHoEMVe+DlonsK+0836LIRDnm6MXQ=", "owner": "nixos", "repo": "nixpkgs", - "rev": "a4bf06618f0b5ee50f14ed8f0da77d34ecc19160", + "rev": "10e7ad5bbcb421fe07e3a4ad53a634b0cd57ffac", "type": "github" }, "original": { @@ -438,10 +381,8 @@ "inputs": { "authentik": "authentik", "disko": "disko", - "gradient": "gradient", "mailserver": "mailserver", - "nixpkgs": "nixpkgs_2", - "nixpkgs-unstable": "nixpkgs-unstable", + "nixpkgs": "nixpkgs_3", "sops": "sops" } }, @@ -452,11 +393,11 @@ ] }, "locked": { - "lastModified": 1777338324, - "narHash": "sha256-bc+ZZCmOTNq86/svGnw0tVpH7vJaLYvGLLKFYP08Q8E=", + "lastModified": 1776771786, + "narHash": "sha256-DRFGPfFV6hbrfO9a1PH1FkCi7qR5FgjSqsQGGvk1rdI=", "owner": "Mic92", "repo": "sops-nix", - "rev": "8eaee5c45428b28b8c47a83e4c09dccec5f279b5", + "rev": "bef289e2248991f7afeb95965c82fbcd8ff72598", "type": "github" }, "original": { @@ -480,21 +421,6 @@ "type": "github" } }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, "uv2nix": { "inputs": { "nixpkgs": [ diff --git a/flake.nix b/flake.nix index dd25bed..f0f177e 100644 --- a/flake.nix +++ b/flake.nix @@ -4,14 +4,11 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11"; - nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; authentik = { url = "github:nix-community/authentik-nix"; - inputs.nixpkgs.follows = "nixpkgs"; }; mailserver = { url = "git+https://gitlab.com/simple-nixos-mailserver/nixos-mailserver?ref=nixos-25.11"; - inputs.nixpkgs.follows = "nixpkgs"; }; sops = { url = "github:Mic92/sops-nix"; @@ -21,22 +18,17 @@ url = "github:nix-community/disko"; inputs.nixpkgs.follows = "nixpkgs"; }; - gradient = { - url = "github:wavelens/gradient"; - }; }; outputs = { self, nixpkgs, - nixpkgs-unstable, authentik, mailserver, disko, sops, - gradient - }@inputs: + }: let sshkeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINABEf0jBjtDdezDDtvl1v27l0DbHP2XUgMARTZXC+MR goeranh@node5" @@ -52,6 +44,15 @@ pkgs = nixpkgs.legacyPackages.x86_64-linux; in pkgs.mkShell { + # Import GPG keys from keys directory + sopsPGPKeyDirs = [ + "${toString ./.}/keys/hosts" + "${toString ./.}/keys/users" + ]; + + # Isolate sops GPG keys to .git/gnupg (optional) + # sopsCreateGPGHome = true; + nativeBuildInputs = [ sops.packages.x86_64-linux.sops-import-keys-hook ]; @@ -183,7 +184,7 @@ result: input: result // { - "${input}" = nixpkgs-unstable.lib.nixosSystem { + "${input}" = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = let @@ -196,10 +197,8 @@ disko.nixosModules.disko authentik.nixosModules.default mailserver.nixosModules.mailserver - gradient.nixosModules.default - sops.nixosModules.sops { - _module.args = { inherit self inputs modulesPath; }; + _module.args = { inherit self modulesPath; }; } ]; }; diff --git a/hosts/gradient/README.md b/hosts/gradient/README.md deleted file mode 100644 index d8116f3..0000000 --- a/hosts/gradient/README.md +++ /dev/null @@ -1,210 +0,0 @@ -# Git Host - Forgejo - -Forgejo git server at 141.56.51.7 running in an LXC container. - -## Overview - -- **Hostname**: git -- **FQDN**: git.adm.htw.stura-dresden.de -- **IP Address**: 141.56.51.7 -- **Type**: Proxmox LXC Container -- **Services**: Forgejo, Nginx (reverse proxy), OpenSSH - -## Services - -### Forgejo - -Forgejo is a self-hosted Git service (fork of Gitea) providing: -- Git repository hosting -- Web interface for repository management -- Issue tracking -- Pull requests -- OAuth2 integration support - -**Configuration**: -- **Socket**: `/run/forgejo/forgejo.sock` (Unix socket) -- **Root URL**: https://git.adm.htw.stura-dresden.de -- **Protocol**: HTTP over Unix socket (Nginx handles TLS) - -### Nginx - -Nginx acts as a reverse proxy between the network and Forgejo: -- Receives HTTPS requests (TLS termination) -- Forwards to Forgejo via Unix socket -- Manages ACME/Let's Encrypt certificates -- WebSocket support enabled for live updates - -### OAuth2 Auto-Registration - -OAuth2 client auto-registration is enabled: -- `ENABLE_AUTO_REGISTRATION = true` -- `REGISTER_EMAIL_CONFIRM = false` -- Username field: email - -This allows users to register automatically via OAuth2 providers without manual approval. - -## Deployment - -See the [main README](../../README.md) for deployment methods. - -### Initial Installation - -**Using nixos-anywhere:** -```bash -nix run github:nix-community/nixos-anywhere -- --flake .#git --target-host root@141.56.51.7 -``` - -**Using container tarball:** -```bash -nix build .#containers-git -scp result/tarball/nixos-system-x86_64-linux.tar.xz root@proxmox-host:/var/lib/vz/template/cache/ -pct create 107 /var/lib/vz/template/cache/nixos-system-x86_64-linux.tar.xz \ - --hostname git \ - --net0 name=eth0,bridge=vmbr0,ip=141.56.51.7/24,gw=141.56.51.254 \ - --memory 2048 \ - --cores 2 \ - --rootfs local-lvm:8 \ - --unprivileged 1 \ - --features nesting=1 -pct start 107 -``` - -### Updates - -```bash -# From local machine -nixos-rebuild switch --flake .#git --target-host root@141.56.51.7 - -# Or use auto-generated script -nix run .#git-update -``` - -## Post-Deployment Steps - -After deploying for the first time: - -1. **Access the web interface:** - ``` - https://git.adm.htw.stura-dresden.de - ``` - -2. **Complete initial setup:** - - Create the first admin account via web UI - - Configure any additional settings - - Set up SSH keys for git access - -3. **Configure OAuth2 (optional):** - - If using an external identity provider (e.g., authentik) - - Add OAuth2 application in the provider - - Configure OAuth2 settings in Forgejo admin panel - - Auto-registration is already enabled in configuration - -4. **Set up repositories:** - - Create organizations - - Create repositories - - Configure access permissions - -## Integration with Proxy - -The central proxy at 141.56.51.1 handles: -- **SNI routing**: Inspects TLS handshake and routes HTTPS traffic for git.adm.htw.stura-dresden.de -- **HTTP routing**: Routes HTTP traffic based on Host header -- **ACME challenges**: Forwards `/.well-known/acme-challenge/` requests to this host for Let's Encrypt verification -- **Auto-redirect**: Redirects HTTP to HTTPS (except ACME challenges) - -This host handles its own TLS certificates via ACME. The proxy passes through encrypted traffic without decryption. - -## Troubleshooting - -### Forgejo socket permissions - -If Forgejo fails to start or Nginx cannot connect: - -```bash -# Check socket exists -ls -l /run/forgejo/forgejo.sock - -# Check Forgejo service status -systemctl status forgejo - -# Check Nginx service status -systemctl status nginx - -# View Forgejo logs -journalctl -u forgejo -f -``` - -**Solution**: Ensure the Forgejo user has proper permissions and the socket path is correct in both Forgejo and Nginx configurations. - -### Nginx proxy configuration - -If the web interface is unreachable: - -```bash -# Check Nginx configuration -nginx -t - -# View Nginx error logs -journalctl -u nginx -f - -# Test socket connection -curl --unix-socket /run/forgejo/forgejo.sock http://localhost/ -``` - -**Solution**: Verify the `proxyPass` directive in Nginx configuration points to the correct Unix socket. - -### SSH access issues - -If git operations over SSH fail: - -```bash -# Check SSH service -systemctl status sshd - -# Test SSH connection -ssh -T git@git.adm.htw.stura-dresden.de - -# Check Forgejo SSH settings -cat /var/lib/forgejo/custom/conf/app.ini | grep -A 5 "\[server\]" -``` - -**Solution**: Ensure SSH keys are properly added to user accounts and SSH daemon is running. - -### ACME certificate issues - -If HTTPS is not working: - -```bash -# Check ACME certificate status -systemctl status acme-git.adm.htw.stura-dresden.de - -# View ACME logs -journalctl -u acme-git.adm.htw.stura-dresden.de -f - -# Manually trigger certificate renewal -systemctl start acme-git.adm.htw.stura-dresden.de -``` - -**Solution**: Verify DNS points to proxy (141.56.51.1) and proxy is forwarding ACME challenges correctly. - -## Files and Directories - -- **Configuration**: `/nix/store/.../forgejo/` (managed by Nix) -- **Data directory**: `/var/lib/forgejo/` -- **Custom config**: `/var/lib/forgejo/custom/conf/app.ini` -- **Repositories**: `/var/lib/forgejo/data/gitea-repositories/` -- **Socket**: `/run/forgejo/forgejo.sock` - -## Network - -- **Interface**: eth0 (LXC container) -- **IP**: 141.56.51.7/24 -- **Gateway**: 141.56.51.254 -- **Firewall**: Ports 22, 80, 443 allowed - -## See Also - -- [Main README](../../README.md) - Deployment methods and architecture -- [Proxy README](../proxy/README.md) - How the central proxy routes traffic -- [Forgejo Documentation](https://forgejo.org/docs/latest/) -- [NixOS Forgejo Options](https://search.nixos.org/options?query=services.forgejo) diff --git a/hosts/gradient/default.nix b/hosts/gradient/default.nix deleted file mode 100644 index 09cadee..0000000 --- a/hosts/gradient/default.nix +++ /dev/null @@ -1,95 +0,0 @@ -{ - config, - inputs, - lib, - pkgs, - modulesPath, - ... -}: -{ - imports = [ - "${modulesPath}/virtualisation/proxmox-lxc.nix" - ]; - - sops = { - defaultSopsFile = ./secrets.sops.yaml; - secrets = { - "gradient-jwt".owner = "gradient"; - "gradient-crypt".owner = "gradient"; - "gradient-worker".owner = "gradient-worker"; - }; - }; - - networking = { - hostName = "gradient"; - fqdn = "gradient.adm.htw.stura-dresden.de"; - interfaces.eth0.ipv4.addresses = [ - { - address = "141.56.51.127"; - prefixLength = 24; - } - ]; - - defaultGateway = { - address = "141.56.51.254"; - interface = "eth0"; - }; - firewall.allowedTCPPorts = [ - 80 - 443 - ]; - }; - - services = { - openssh.enable = true; - - gradient = { - enable = true; - frontend.enable = true; - domain = "${config.networking.fqdn}"; - jwtSecretFile = "/run/secrets/gradient-jwt"; - cryptSecretFile = "/run/secrets/gradient-crypt"; - configurePostgres = true; - configureNginx = true; - # serveCache = true; - reportErrors = true; - - worker = { - enable = true; - serverUrl = "ws://127.0.0.1:3000/proto"; - workerId = "8f56dd3a-5698-4512-8bf7-ab8dcfaed46c"; - peersFile = "/run/secrets/gradient-worker-peers"; - capabilities = { - fetch = true; - eval = true; - build = true; - }; - packages.nix = inputs.nixpkgs-unstable.legacyPackages.x86_64-linux.nix; - settings = { - logLevel = { - default = "debug"; - }; - }; - }; - }; - - nginx.commonHttpConfig = '' - real_ip_header proxy_protocol; - set_real_ip_from 141.56.51.1/32; - ''; - nginx.virtualHosts."${config.networking.fqdn}".listen = [ - { - port = 80; - addr = "0.0.0.0"; - } - { - port = 443; - addr = "0.0.0.0"; - ssl = true; - proxyProtocol = true; - } - ]; - }; - - system.stateVersion = "25.11"; -} diff --git a/hosts/gradient/secrets.sops.yaml b/hosts/gradient/secrets.sops.yaml deleted file mode 100644 index 6e4f9fa..0000000 --- a/hosts/gradient/secrets.sops.yaml +++ /dev/null @@ -1,27 +0,0 @@ -gradient-jwt: ENC[AES256_GCM,data:0RgUOHbz5qtBOE1+wldyhzE6b4275JTkzdjgQBbVUnHtNVvqmQUs94JGfB2HRteVJS2pRmRxyh+YYUpuErkmaw==,iv:C6AqWjVs6MGjTJ/QEFq9kz7kSglMXi+rtlmkEK0i4r0=,tag:HvmCN947JveYFDITZfAEMA==,type:str] -gradient-crypt: ENC[AES256_GCM,data:j6KRaxQItKtolZXPxN1Rp4NalX5rYnHvQzL/R0naobgM2nMUiOJJeKiZ5yooXbaNC1wrwWNfMrNDYkm8bxVJeA==,iv:2wiiyJu3u9cEwwos0DhgKiwp0qYSw1z6MdOvpWsf+Is=,tag:GOfN78rlovnPXgiCAE9diA==,type:str] -gradient-worker: ENC[AES256_GCM,data:IktOl14QzBee16ZxZZMmseMomlyF+teJoxsNmqDXcPHq4ZZv7QWDQAjIct4hz1CHofaBfXzVM372WSLTX51/zw==,iv:OZsC9EX4fRUv7Q9AbnXBaskX9hS/wgFctOepz39NyDU=,tag:GHPx4yXb7ta5pj4+yI2PRQ==,type:str] -sops: - age: - - recipient: age1kfxhahmxprheer63shv68slpmk5qz29nyx3kp4q6n879zz9ha34q04n50x - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2OHc0aWRocmx2QkUzcnFa - T3Z5MWp3U2I1c2RZMytnU1hkd0p4ZHNWSW5vCmFuZHBJYjMrSUwranVDNHR1RmFr - dVhSVmdPUGd1czFjM3p3dlBLcTU0T1UKLS0tIDl1eHBkL1lBUWh0ckhya1dJTjdY - WmhPVEl3ZytOdmdaQ3pkN2lLTnRPMzAKCKj7VvRPTBXfsqa6FnJi3ZkWNUXN8JG8 - NlcK9QL/pMoExpoLHfw8ram4Y2i9up4oONeA2iKR12Dh86Y8RUUJfg== - -----END AGE ENCRYPTED FILE----- - - recipient: age16m8vvvpw4azfy6gygtstyyj6nd2sf848f7f7argaghwhct38muxsgxpeek - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRVXNoVktTL0VvdVIrVWx6 - cFpLMnhJcmFWYlVKWWZIVUR1NGMzRWhOWngwClVRZ092dDFEMHJ3d3JkdFkwVVI2 - YW9BK0hBNnB6UmM0bzBYYVNqS0QxcFEKLS0tIHljSm03TTRjTVlSam4xN2NhMUJ6 - aDNFUi9SL1BhZHMxVUFkTzR6bk16cWsKeS3Y8b/WlvdgmY5yLjTfTHJwBZoZ7RU8 - GPLB8ezNB3U7XxO05hwlUQJbTkMVhSzu+nKfEavdS1KMoXaxfxhrwA== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-04-22T08:34:30Z" - mac: ENC[AES256_GCM,data:74FyYHQ/bMZ3wxodMlvAXYl2UWNkv8arWSDeJwCEfRWz05bzXWy6UaMLWc+dSoqJsVvT3SRVuBMrtilsckVqCVQ4C96c730IVWB/b5juIXtEsp1JiWgS+F3yC992HDGmoGnAkSE/vzZBu3DRA8/eMwkoTtGscpDhnAzUVrkCNUk=,iv:BzhopR3jxZyKZhwRxh1lKaIaGgE5IbIe/AG35D1juZA=,tag:frnRzapbiU49TpkISZ4GEQ==,type:str] - unencrypted_suffix: _unencrypted - version: 3.12.1 diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 7fa2238..40740fb 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -20,49 +20,22 @@ } ]; defaultGateway.address = "141.56.51.254"; - firewall.enable = false; + firewall = { + allowedTCPPorts = [ + 22 + 53 # DNS + 80 + 443 + 1005 + 2142 + ]; + allowedUDPPorts = [ + 53 # DNS + 123 # NTP + ]; + }; nftables = { enable = true; - ruleset = '' - table inet filter { - set blacklist4 { - type ipv4_addr - flags interval - # manage: nft add element inet filter blacklist4 { 1.2.3.0/24 } - } - - set blacklist6 { - type ipv6_addr - flags interval - # manage: nft add element inet filter blacklist6 { 2001:db8::/32 } - } - - chain input { - type filter hook input priority filter; policy drop; - - iif "lo" accept - ct state established,related accept - - ip saddr @blacklist4 drop - ip6 saddr @blacklist6 drop - - # public ports - tcp dport { 80, 443, 1005, 2142 } accept - - # lan-only: dns and ntp - ip saddr 141.56.51.0/24 tcp dport 53 accept - ip saddr 141.56.51.0/24 udp dport { 53, 123 } accept - } - - chain forward { - type filter hook forward priority filter; policy drop; - } - - chain output { - type filter hook output priority filter; policy accept; - } - } - ''; }; }; @@ -479,7 +452,6 @@ frontend http-in bind *:80 - mode http tcp-request connection expect-proxy layer4 if { src 178.104.18.93 } maxconn 60000 backlog 8192 @@ -503,8 +475,8 @@ prev: name: value: prev + '' - http-request redirect scheme https code 301 if !is_acme is_${name} use_backend ${name}_80 if is_${name} + http-request redirect scheme https code 301 if !is_acme is_${name} '' ) "" forwards} @@ -638,47 +610,6 @@ stura.monitoring.extraLogInputs = [ "haproxy_geoip" ]; - users.users.root.packages = [ - (pkgs.writeShellScriptBin "nft-blacklist" '' - set -euo pipefail - - usage() { - echo "Usage: nft-blacklist " - echo " add - add entry to blacklist set" - echo " del - remove entry from blacklist set" - exit 1 - } - - [[ $# -ne 2 ]] && usage - - ACTION="$1" - ADDR="$2" - - if [[ "$ADDR" == *:* ]]; then - SET="blacklist6" - elif [[ "$ADDR" == *.* ]]; then - SET="blacklist4" - else - echo "Error: cannot determine address family for '$ADDR'" >&2 - exit 1 - fi - - case "$ACTION" in - add) - ${pkgs.nftables}/bin/nft add element inet filter "$SET" "{ $ADDR }" - echo "Added $ADDR to $SET" - ;; - del) - ${pkgs.nftables}/bin/nft delete element inet filter "$SET" "{ $ADDR }" - echo "Removed $ADDR from $SET" - ;; - *) - usage - ;; - esac - '') - ]; - environment.systemPackages = with pkgs; [ ]; diff --git a/hosts/redmine/default.nix b/hosts/redmine/default.nix index 2bbd398..3e3e183 100644 --- a/hosts/redmine/default.nix +++ b/hosts/redmine/default.nix @@ -134,9 +134,9 @@ #### Der StuRa speichert nicht! services.nginx.logError = ''/dev/null emerg''; - # services.nginx.appendHttpConfig = '' - # access_log off; - # ''; + services.nginx.appendHttpConfig = '' + access_log off; + ''; services.nginx.commonHttpConfig = '' real_ip_header proxy_protocol; set_real_ip_from 141.56.51.1/32; diff --git a/hosts/v6proxy/default.nix b/hosts/v6proxy/default.nix index 39e2521..270ef2c 100644 --- a/hosts/v6proxy/default.nix +++ b/hosts/v6proxy/default.nix @@ -38,44 +38,16 @@ "9.9.9.9" "1.1.1.1" ]; - firewall.enable = false; + firewall = { + enable = true; + allowedTCPPorts = [ + 22 + 80 + 443 + ]; + }; nftables = { enable = true; - ruleset = '' - table inet filter { - set blacklist4 { - type ipv4_addr - flags interval - # manage at runtime: nft add element inet filter blacklist4 { 1.2.3.0/24 } - } - - set blacklist6 { - type ipv6_addr - flags interval - # manage at runtime: nft add element inet filter blacklist6 { 2001:db8::/32 } - } - - chain input { - type filter hook input priority filter; policy drop; - - iif "lo" accept - ct state established,related accept - - ip saddr @blacklist4 drop - ip6 saddr @blacklist6 drop - - tcp dport { 22, 80, 443 } accept - } - - chain forward { - type filter hook forward priority filter; policy drop; - } - - chain output { - type filter hook output priority filter; policy accept; - } - } - ''; }; }; @@ -130,45 +102,7 @@ }; }; - users.users.root.packages = [ - (pkgs.writeShellScriptBin "nft-blacklist" '' - set -euo pipefail - - usage() { - echo "Usage: nft-blacklist " - echo " add - add entry to blacklist set" - echo " del - remove entry from blacklist set" - exit 1 - } - - [[ $# -ne 2 ]] && usage - - ACTION="$1" - ADDR="$2" - - if [[ "$ADDR" == *:* ]]; then - SET="blacklist6" - elif [[ "$ADDR" == *.* ]]; then - SET="blacklist4" - else - echo "Error: cannot determine address family for '$ADDR'" >&2 - exit 1 - fi - - case "$ACTION" in - add) - ${pkgs.nftables}/bin/nft add element inet filter "$SET" "{ $ADDR }" - echo "Added $ADDR to $SET" - ;; - del) - ${pkgs.nftables}/bin/nft delete element inet filter "$SET" "{ $ADDR }" - echo "Removed $ADDR from $SET" - ;; - *) - usage - ;; - esac - '') + environment.systemPackages = with pkgs; [ ]; system.stateVersion = "25.11"; diff --git a/hosts/wiki/default.nix b/hosts/wiki/default.nix index 179780d..c73a5cb 100644 --- a/hosts/wiki/default.nix +++ b/hosts/wiki/default.nix @@ -201,8 +201,8 @@ #### https://www.mediawiki.org/wiki/Extension:UserMerge UserMerge = pkgs.fetchzip { # url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_43-ed4a689.tar.gz"; - url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_45-433f6c2.tar.gz"; - sha256 = "sha256-JyY4pJNBKQ9bOKrilPWCheZ5ihWwPM6ZJ0qHsZ3coPk="; + url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_45-437c211.tar.gz"; + sha256 = "sha256-DWdcvubqZkvtywuDEOjui68WYuETt5hGpJJlpZ+pJgE="; }; }; diff --git a/keys/.gitignore b/keys/.gitignore new file mode 100644 index 0000000..ce29a38 --- /dev/null +++ b/keys/.gitignore @@ -0,0 +1,18 @@ +# Prevent accidental commit of private keys +*.key +*.priv +*.private +*_priv +*-priv +*.sec +*secret* + +# Only allow public keys +!*.asc +!*.gpg +!*.pub +!*.age + +# Allow this gitignore and README +!.gitignore +!README.md diff --git a/keys/README.md b/keys/README.md new file mode 100644 index 0000000..587f370 --- /dev/null +++ b/keys/README.md @@ -0,0 +1,40 @@ +# Keys Directory + +This directory contains GPG/age public keys for sops encryption. + +## Structure + +- `hosts/` - Host-specific public keys (for servers to decrypt their own secrets) +- `users/` - User/admin public keys (for team members to decrypt secrets) + +## Adding Keys + +### GPG Keys + +Export your GPG public key: +```bash +gpg --export --armor YOUR_KEY_ID > keys/users/yourname.asc +``` + +Export a host's public key: +```bash +gpg --export --armor HOST_KEY_ID > keys/hosts/hostname.asc +``` + +### Age Keys + +For age keys, save the public key to a file: +```bash +echo "age1..." > keys/users/yourname.age +echo "age1..." > keys/hosts/hostname.age +``` + +## Usage + +When you enter the dev shell (`nix develop`), all keys in these directories will be automatically imported into your GPG keyring via the sops-import-keys-hook. + +## Important + +- Only commit **public** keys (.asc, .age files with public keys) +- Never commit private keys +- Update `.sops.yaml` to reference the fingerprints/keys for access control diff --git a/keys/hosts/.gitkeep b/keys/hosts/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/keys/users/.gitkeep b/keys/users/.gitkeep new file mode 100644 index 0000000..e69de29