diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 120000 index 0000000..ca60d86 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1 @@ +/nix/store/1w2s62i701n28sj08gn1445qr4v3vijp-pre-commit-config.json \ No newline at end of file diff --git a/.sops.yaml b/.sops.yaml index 66644ad..fd76726 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -1,17 +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 age1qp7w80k3qtj79xsl0gwsfrkm037xrlnhm6th7tcyrvufh3szzp6s2pe7ra - - &mail age156ak7kc79tuwpv0hk9atl5dg27jqs6ddfqxvr9m4twqgsr23lgvsdmyfpr - - &auth age1njnkkr489hfmpn337zna2k3z66y9086t7cpcmz2vn68p4x43aujs6wh0g5 + # 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: - - path_regex: hosts/mail/secrets.sops.yml$ - key_groups: - - age: - - *mail - - *goeranh - - path_regex: hosts/auth/secrets.sops.yml$ - key_groups: - - age: - - *auth - - *goeranh + # 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) + # - 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/flake.lock b/flake.lock index 9ed7807..c4d6b5e 100644 --- a/flake.lock +++ b/flake.lock @@ -114,6 +114,22 @@ } }, "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "NixOS", + "repo": "flake-compat", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_3": { "flake": false, "locked": { "lastModified": 1761588595, @@ -169,12 +185,34 @@ } }, "git-hooks": { + "inputs": { + "flake-compat": "flake-compat_2", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1772893680, + "narHash": "sha256-JDqZMgxUTCq85ObSaFw0HhE+lvdOre1lx9iI6vYyOEs=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "8baab586afc9c9b57645a734c820e4ac0a604af9", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "git-hooks_2": { "inputs": { "flake-compat": [ "mailserver", "flake-compat" ], - "gitignore": "gitignore", + "gitignore": "gitignore_2", "nixpkgs": [ "mailserver", "nixpkgs" @@ -195,6 +233,27 @@ } }, "gitignore": { + "inputs": { + "nixpkgs": [ + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_2": { "inputs": { "nixpkgs": [ "mailserver", @@ -219,8 +278,8 @@ "mailserver": { "inputs": { "blobs": "blobs", - "flake-compat": "flake-compat_2", - "git-hooks": "git-hooks", + "flake-compat": "flake-compat_3", + "git-hooks": "git-hooks_2", "nixpkgs": "nixpkgs_2" }, "locked": { @@ -381,6 +440,7 @@ "inputs": { "authentik": "authentik", "disko": "disko", + "git-hooks": "git-hooks", "mailserver": "mailserver", "nixpkgs": "nixpkgs_3", "sops": "sops" diff --git a/flake.nix b/flake.nix index 53bdc81..c4a2649 100644 --- a/flake.nix +++ b/flake.nix @@ -18,6 +18,10 @@ url = "github:nix-community/disko"; inputs.nixpkgs.follows = "nixpkgs"; }; + git-hooks = { + url = "github:cachix/git-hooks.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = @@ -28,6 +32,7 @@ mailserver, disko, sops, + git-hooks, }: let sshkeys = [ @@ -42,6 +47,12 @@ devShells.x86_64-linux.default = let pkgs = nixpkgs.legacyPackages.x86_64-linux; + pre-commit-check = git-hooks.lib.x86_64-linux.run { + src = ./.; + hooks = { + nixfmt-rfc-style.enable = true; + }; + }; in pkgs.mkShell { # Import GPG keys from keys directory @@ -53,11 +64,15 @@ # Isolate sops GPG keys to .git/gnupg (optional) # sopsCreateGPGHome = true; + shellHook = '' + ${pre-commit-check.shellHook} + ''; + nativeBuildInputs = [ sops.packages.x86_64-linux.sops-import-keys-hook ]; - buildInputs = [ + buildInputs = pre-commit-check.enabledPackages ++ [ pkgs.sops ]; }; @@ -196,7 +211,6 @@ disko.nixosModules.disko authentik.nixosModules.default mailserver.nixosModules.mailserver - sops.nixosModules.default { _module.args = { inherit self modulesPath; }; } diff --git a/hosts/auth/authentik.nix b/hosts/auth/authentik.nix deleted file mode 100644 index 4ae125b..0000000 --- a/hosts/auth/authentik.nix +++ /dev/null @@ -1,84 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: -{ - users.groups.authentik = { }; - users.users.authentik = { - isSystemUser = true; - extraGroups = [ "docker" ]; - group = "authentik"; - }; - - virtualisation.docker.enable = true; - - systemd.services = { - authentik-secrets-setup = { - enable = true; - }; - }; - users.groups.authentik-ldap = {}; - users.users.authentik-ldap = { - isSystemUser = true; - group = "authentik-ldap"; - }; - systemd.services.authentik-ldap.serviceConfig = { - DynamicUser = lib.mkForce false; - User = "authentik-ldap"; - }; - services.authentik-ldap = { - enable = true; - environmentFile = config.sops.secrets."auth/ldap-env-file".path; - # environmentFile = "/var/lib/authentik-ldap-env"; - }; - services.authentik = { - enable = true; - # environmentFile = "/var/lib/authentik_secret"; - environmentFile = config.sops.secrets."auth/env-file".path; - settings = { - email = { - host = "mail.${config.networking.domain}"; - port = 25; - username = "authentik@${config.networking.domain}"; - use_tls = false; - use_ssl = false; - from = "authentik@${config.networking.domain}"; - }; - disable_startup_analytics = true; - avatars = "initials"; - }; - }; - - systemd.services.authentik-secrets-generator = { - enable = true; - requiredBy = [ - "authentik-secrets-setup.service" - "authentik-worker.service" - ]; - script = '' - echo "AUTHENTIK_SECRET_KEY=$(${pkgs.openssl}/bin/openssl rand -hex 32)" > /var/lib/authentik_secret - ''; - }; - - services.nginx = { - enable = true; - virtualHosts = { - "auth.${config.networking.domain}" = { - enableACME = true; - forceSSL = true; - locations."/" = { - proxyPass = "http://localhost:9000"; - proxyWebsockets = true; - recommendedProxySettings = true; - extraConfig = '' - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - ''; - }; - }; - }; - }; -} - diff --git a/hosts/auth/default.nix b/hosts/auth/default.nix deleted file mode 100644 index 0d135dc..0000000 --- a/hosts/auth/default.nix +++ /dev/null @@ -1,45 +0,0 @@ -{ - config, - lib, - pkgs, - modulesPath, - ... -}: -{ - sops = { - defaultSopsFile = ./secrets.sops.yml; - secrets = { - "auth/env-file".owner = "authentik"; - "auth/ldap-env-file".owner = "authentik"; - }; - }; - imports = [ - "${modulesPath}/virtualisation/proxmox-lxc.nix" - ./authentik.nix - ]; - - networking = { - hostName = "auth"; - domain = lib.mkForce "test.htw.stura-dresden.de"; - useDHCP = false; - interfaces.eth0.ipv4.addresses = [ - { - address = "141.56.51.96"; - prefixLength = 24; - } - ]; - - defaultGateway = { - address = "141.56.51.254"; - interface = "eth0"; - }; - - firewall.allowedTCPPorts = [ - 80 - 443 - 3389 - ]; - }; - - system.stateVersion = "25.05"; -} diff --git a/hosts/auth/secrets.sops.yml b/hosts/auth/secrets.sops.yml deleted file mode 100644 index 45c456a..0000000 --- a/hosts/auth/secrets.sops.yml +++ /dev/null @@ -1,27 +0,0 @@ -auth: - env-file: ENC[AES256_GCM,data:WDJ3daYCxybublm8VWO8W5HHmYYWKOcw81f+fQ0Vz78EOvbYI+SgEwnuAd/0/eeGkTPEJPSCfbymArs+YRTdibgO5y/34jdN0DOVQetZLPXrDbcZ/Sg=,iv:bykKdvkgmxwgptkGHKH4rnFknPA0PTrW+mEqIzIYERk=,tag:8UKhLz/VoPiXckcIEBfrLg==,type:str] - ldap-env-file: ENC[AES256_GCM,data:CpgiiUin3hj8+aykcSU2rasaCFt/CAC5lK3Ek7zxzw6hYCkhwxIc9a4Xfy9SxSQtASJ5dOOrOaa8gA1ahf4Z1g/1981fhxlQPeJd9PlJFgdL4CP5P6ZrPBKZKgygnreUo6HC7Rfc9x2CRmnDhQvMVUmQL9akZRNYasX+9IlRyKmLSFmi35IuryFhVLwfjfECmq51/Xo2WYzjWrayfFuOpS0jHWicQxXvXq6QcLvqmbk5euXiHDkFXOXcwMRr6mAompDAKa9BKXqcRDbxOWqzJ1gflEJvOJi249PeYFo+poTK1CUtBCTejFo=,iv:P1xN6wq5oeba1LSEn6UiArOka37alV/PhI5kOmpfDG0=,tag:Xisd5elHQ8mhvE6YEbCuLg==,type:str] -sops: - age: - - recipient: age1njnkkr489hfmpn337zna2k3z66y9086t7cpcmz2vn68p4x43aujs6wh0g5 - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHRmV2dGt1UXZ3M2RKd24y - V0x4MzZyYUh0aDVwQ1NmOCtyOHR6Z1c0R1ZNCi80Nk9PZFVTcVFIQjlZVXJNeXBN - TC9td05ZeWVVTCtFSWhqazN6bFF3akkKLS0tIEV3YzdRUDA5Q2dBd2JWUWNqOTU4 - SnZtdVd4Q3lCaStJTnV4U2cvZUZEMlkK85XYSh6VbDFPKPIhKBKtkErGtgsHjXxy - kq14EXwfZnnBlR76JMQgPvSLrDLdj+4tDIVcuE4JplCoSvbGKckGww== - -----END AGE ENCRYPTED FILE----- - - recipient: age1qp7w80k3qtj79xsl0gwsfrkm037xrlnhm6th7tcyrvufh3szzp6s2pe7ra - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkQm5nUHkzZExKOXNzNjk4 - Y1JURVJwNXhFUGZJak8vbEtCNnE2dHFuNVVNClJHQ3E2RGJkbUtlMDNwcy9Ib01Q - dG9nRTVJejkySTdlb2IrbHF4Z3ZMTmcKLS0tIHUwNndGdW9EaWwyNmRUb2NQU2Vs - MC9VSmVqVlVHRlJ4NXozUkQ4ZDVEVlkKbfVoBNsral3n7rG7ujUgdQXF68EVB+4G - MKMuOiY05QGBViLYyKh1jioHv6nds1hCuc2vpLNB3J0KT3I2q/a0VQ== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-03-21T16:42:34Z" - mac: ENC[AES256_GCM,data:i9hTUqbrmc2mD8PAbCe2gWern4ArMIkTQWN7eaJcsjZ9m6LZjOQFpnrpgPg6fj3hazgnFn86veNvQGe/J50NLnwj2FCyF3jKG3xkc7rKa9fyD0Yz0XnpbNKtDb2YGxwyBmLsnnyl6sdpyvPipZYCfwM+bhB8OERIXVXKwbZOn1A=,iv:dKI/NsMcVBNBOw0kYEQqrgfdvLKDg4NM/yRBYDqXIxU=,tag:xkg0z7IUy2m4ivosB925vQ==,type:str] - unencrypted_suffix: _unencrypted - version: 3.12.1 diff --git a/hosts/mail/default.nix b/hosts/mail/default.nix deleted file mode 100644 index c4bf5f3..0000000 --- a/hosts/mail/default.nix +++ /dev/null @@ -1,210 +0,0 @@ -{ - config, - lib, - pkgs, - modulesPath, - ... -}: -let - generatedAliases = pkgs.writeText "generated-aliases" ( - lib.concatStringsSep "\n" ( - lib.mapCartesianProduct - ({ aliases, domain }: "${aliases}@${domain} root@test.htw.stura-dresden.de") - { - aliases = [ - "abuse" - "hostmaster" - "noreply" - "postmaster" - "webmaster" - ]; - domain = config.mailserver.domains; - } - ) - ); - -in -{ - sops = { - defaultSopsFile = ./secrets.sops.yml; - secrets = { - "ldap_passwd".owner = "dovecot2"; - }; - }; - imports = [ - "${modulesPath}/virtualisation/proxmox-lxc.nix" - ]; - - security.pam.loginLimits = [ - { - domain = "*"; - type = "soft"; - item = "nofile"; - value = "8192"; - } - ]; - - networking = { - hostName = "mail"; - domain = lib.mkForce "test.htw.stura-dresden.de"; - useDHCP = false; - interfaces.ens18.ipv4.addresses = [ - { - address = "141.56.51.95"; - prefixLength = 24; - } - ]; - - defaultGateway = { - address = "141.56.51.254"; - interface = "eth0"; - }; - }; - - services.nginx.virtualHosts = { - "lists.${config.networking.domain}" = { - enableACME = true; - forceSSL = true; - # locations."/" = { - # proxyPass = "http://127.0.0.1:18507"; - # }; - }; - }; - services.automx2 = { - enable = true; - domain = "${config.networking.domain}"; - settings = { - automx2 = { - db_uri = "sqlite:////var/lib/automx2/db.sqlite"; - proxy_count = 1; - }; - }; - }; - services.mailman = { - enable = true; - hyperkitty = { - enable = true; - }; - serve.enable = true; - webHosts = [ - "lists.${config.networking.domain}" - ]; - }; - - services.mailman.siteOwner = "mailman@${config.networking.domain}"; - mailserver = { - enable = true; - fqdn = "mail.${config.networking.domain}"; - domains = [ - "${config.networking.domain}" - "lists.${config.networking.domain}" - ]; - ldap = { - enable = true; - bind = { - # dn = "cn=dovecot,ou=users,DC=test,DC=htw,DC=stura-dresden,DC=de"; - dn = "cn=dovecot,ou=users,dc=mail,dc=htw,dc=stura-dresden,dc=de"; - # passwordFile = "/var/lib/dovecot_ldap_passwd"; - passwordFile = config.sops.secrets.ldap_passwd.path; - }; - dovecot = { - userFilter = "(&(objectClass=posixAccount)(mail=%u))"; - passFilter = "(&(objectClass=posixAccount)(mail=%u))"; - userAttrs = "cn"; - }; - postfix = { - filter = "(|(&(objectClass=posixAccount)(mail=%s))(&(objectClass=posixAccount)(cn=%s)))"; - mailAttribute = "mail"; - uidAttribute = "cn"; - }; - #searchBase = "DC=test,DC=htw,DC=stura-dresden,DC=de"; - searchBase = "dc=mail,dc=htw,dc=stura-dresden,dc=de"; - uris = [ - "ldap://auth.test.htw.stura-dresden.de:3389" - ]; - }; - - certificateScheme = "acme-nginx"; - enableImap = true; - enableImapSsl = true; - enableManageSieve = true; - enableSubmission = true; - enableSubmissionSsl = true; - extraVirtualAliases = { }; - lmtpSaveToDetailMailbox = "no"; # DOS potential - mailboxes = { - Drafts = { - auto = "subscribe"; - specialUse = "Drafts"; - }; - Sent = { - auto = "subscribe"; - specialUse = "Sent"; - }; - Spam = { - auto = "subscribe"; - specialUse = "Junk"; - }; - Trash = { - auto = "subscribe"; - specialUse = "Trash"; - }; - }; - maxConnectionsPerUser = 10; - messageSizeLimit = 10 * 1000 * 1024; # 10 MiB - - stateVersion = 3; - }; - - # services.dovecot2.mailLocation = lib.mkForce "maildir:/var/vmail/%n"; - services.postfix = - let - submissionOptions = { - # hash:/etc/postfix/virtual, - smtpd_sender_login_maps = lib.mkForce "ldap:/run/postfix/ldap-sender-login-map.cf"; - smtpd_client_restrictions = "permit_sasl_authenticated,reject"; - }; - in - { - masterConfig = { - submission = { - args = [ "-v" ]; - }; - submissions = { - args = [ "-v" ]; - }; - }; - settings.main = { - unknown_local_recipient_reject_code = 550; - relay_domains = [ - "hash:/var/lib/mailman/data/postfix_domains" - ]; - transport_maps = [ - "hash:/var/lib/mailman/data/postfix_lmtp" - ]; - local_recipient_maps = [ - "hash:/var/lib/mailman/data/postfix_lmtp" - ]; - }; - # mapFiles = { - # "valias" = lib.mkForce "/var/lib/postfix/valias"; - # "virtual" = lib.mkForce "/var/lib/postfix/virtual"; - # }; - submissionOptions = submissionOptions; - submissionsOptions = submissionOptions; - }; - - security.acme.acceptTerms = true; - security.acme.defaults.email = "cert@stura.htw-dresden.de"; - - networking.firewall.allowedTCPPorts = [ - 25 - 80 - 443 - 597 - ]; - - system.stateVersion = "24.11"; - -} - diff --git a/hosts/mail/secrets.sops.yml b/hosts/mail/secrets.sops.yml deleted file mode 100644 index b9d0b6a..0000000 --- a/hosts/mail/secrets.sops.yml +++ /dev/null @@ -1,25 +0,0 @@ -ldap_passwd: ENC[AES256_GCM,data:adUZCZcYfoxBQm3e4YeeXcQJSZjB3+v2zSNy7q0Ao39aDQMH5H0w4o9MXTREkPHW53JejC2ivo8Zl3yUhkeYRw==,iv:XB25CmtUGf+PeSsHtr+CA/HIfZq1IrOBPPQD3/r6Kc4=,tag:A/WGViM/Ix7n6mhjnbCtZg==,type:str] -sops: - age: - - recipient: age156ak7kc79tuwpv0hk9atl5dg27jqs6ddfqxvr9m4twqgsr23lgvsdmyfpr - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsenVrS0tkTWZRY2xDZklO - WTcwaENIY2I1bTFGMEZZVzBoeUNrT2RESmhFCnZXU2M1SjlGQWo0OEp0TzI0c21u - UkNuNEdQQldQdy9uSzhveEM2eFZrRUkKLS0tIGV4S3lreHJPVS96VUZ6SXRaSklW - MUE4eXN0bkNkU0dCckppdldvV2V4dHcKdKh6ekq6hB5pCUAEPdASqsxqAKZDwzCv - NyS2jitHo9XBtMQVJg4PmNcoRs5XLdqy2tP8upnGelj0B/Q9D+dhag== - -----END AGE ENCRYPTED FILE----- - - recipient: age1qp7w80k3qtj79xsl0gwsfrkm037xrlnhm6th7tcyrvufh3szzp6s2pe7ra - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRVlVrdXhGMDRxMjhPb3Nv - c3lBS25OKzJIaWhHWHpKQXo0N1dFTnZLaHdnClVFVTFPVE1rNFVEclFVc3VjQVhu - SjF6Nnp6dE9oRUJYUVVnOWVpVE11WVkKLS0tIEJ0aVJzejROMHFPK1JQbkJjbUdi - bGU3WWhVMGJ2LzI4N2E1Zy9RNnJ2V2MK4UQPwE5GUVTGvnuZ9knQ+BHmzmRLA1V5 - SinlJfHcs+9B7haHzAekDdNqZgEUh2tblabHqq/vNWzd0rWpK31Dww== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-03-21T17:05:32Z" - mac: ENC[AES256_GCM,data:A2tbQ8obTjzKeISAbDy0Sqi+WvpqZwkKSW2PmV67V2u/svNfC7C/ebNHp6p0I9N97y026WzboXnRwon7M1jaJ8dPn2hqGReZIIHW5w5rBK0uAeEH5wCMnNGslox4D7+L27zc4VZMK4tjFP6F7EKkq7TIjf+HzEYW+kpbqM2erVo=,iv:EKa3JBlDiU/FcF2T/hQtmaFlYiAbFIlytR3fSfJjVBc=,tag:B4N/4XxhdtNYKTRT1O+UyA==,type:str] - unencrypted_suffix: _unencrypted - version: 3.12.1 diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix index 3a727f3..897e27e 100644 --- a/hosts/proxy/default.nix +++ b/hosts/proxy/default.nix @@ -143,18 +143,6 @@ httpPort = 80; httpsPort = 443; }; - bbb = { - dest = "141.56.51.94"; - domain = "bbb.htw.stura-dresden.de"; - httpPort = 80; - httpsPort = 443; - }; - bbb-test = { - dest = "141.56.51.94"; - domain = "bbb.test.htw.stura-dresden.de"; - httpPort = 80; - httpsPort = 443; - }; } # zusätzlich zu den oben definierten wird hier noch ein redirect für jeden nginx virtualhost in diese flake generiert // (builtins.foldl'