diff --git a/.github/workflows/fmt.yaml b/.github/workflows/fmt.yaml deleted file mode 100644 index 93d16c5..0000000 --- a/.github/workflows/fmt.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: main - -on: - push: - branches: - - main - pull_request: - branches: - - main - -jobs: - check-flake: - name: Nixpkgs Formatting - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - name: Install Nix - uses: cachix/install-nix-action@v18 - with: - extra_nix_config: | - experimental-features = nix-command flakes - - - run: nix-channel --add https://nixos.org/channels/nixos-22.11 nixos - - run: nix-channel --update - - run: nix shell nixpkgs#nixpkgs-fmt -c nixpkgs-fmt . --check diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 8f203d2..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: main - -on: - push: - branches: - - main - pull_request: - branches: - - main - -jobs: - check-flake: - name: Check Flake - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - name: Install Nix - uses: cachix/install-nix-action@v18 - with: - install_url: https://releases.nixos.org/nix/nix-2.13.3/install - extra_nix_config: | - experimental-features = nix-command flakes - - - uses: cachix/cachix-action@v12 - with: - name: fruitbasket - authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - extraPullNames: nix-community - - - run: nix build - - - run: nix flake check diff --git a/.sops.yaml b/.sops.yaml index 0b6cb06..7513f79 100755 --- a/.sops.yaml +++ b/.sops.yaml @@ -7,9 +7,11 @@ keys: - &helene B43C3A8A92CA28486AC6C4E2F115100C787C1C19 - &fugi BF37903AE6FD294C4C674EE24472A20091BFA792 - &emmanuel E83F398E6423179FE4F63D4FF085CAD394DE329D - - &jonas A4F92BC7B792108A463995827C1F2DA2BC929412 - &joachim B1A16011B86BACB56ADB713DB712039D23133661 + - &hendrik FBBFAC260D9283D1EF2397DD3CA65E9DD6EB319D + - &frieder age1x76ajqw8w4l5vlkwt5s3flz5a5jq5qlxv7uppmnf8ckj9egh9ekqjclzt6 - &quitte age1wvdnprpnq2rcc4se3zpx2p267n0apxg2jucvlm93e3pfj439ephqh2506t + - &tomate age18lwgjazaxujqgcc5j0gjllnykhtjn6p0q44jzrsk4au2a5k6nd9s77kd6d creation_rules: - path_regex: secrets/quitte\.yaml$ @@ -21,9 +23,23 @@ creation_rules: - *rouven - *fugi - *joachim - - *jonas + - *hendrik age: + - *frieder - *quitte + - path_regex: secrets/tomate\.yaml$ + key_groups: + - pgp: + - *bennofs + - *revol-xut + - *felix + - *rouven + - *fugi + - *joachim + - *hendrik + age: + - *frieder + - *tomate - path_regex: secrets/admin\.yaml$ key_groups: - pgp: @@ -33,4 +49,5 @@ creation_rules: - *rouven - *fugi - *joachim - - *jonas + - *hendrik + - *frieder diff --git a/flake.lock b/flake.lock index bfeb662..5da240b 100644 --- a/flake.lock +++ b/flake.lock @@ -1,19 +1,59 @@ { "nodes": { - "course-management": { + "authentik": { "inputs": { + "authentik-src": "authentik-src", + "flake-compat": "flake-compat", + "flake-parts": "flake-parts", "flake-utils": "flake-utils", - "nixpkgs": [ - "nixpkgs" - ], - "poetry2nix": "poetry2nix" + "napalm": "napalm", + "nixpkgs": "nixpkgs", + "poetry2nix": "poetry2nix", + "systems": "systems" }, "locked": { - "lastModified": 1694358978, - "narHash": "sha256-gHWIIYJZepq1/3oFVkUkl0n52bRJWnNgmGaiZ2aGEwc=", + "lastModified": 1745663775, + "narHash": "sha256-zRamFjTxegQE0Ysi46sfDU2CIghiMWJIdEYdq7O0jiQ=", + "owner": "nix-community", + "repo": "authentik-nix", + "rev": "a8a5de789006bb1dea0ffb5370a8f7e453d06113", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "authentik-nix", + "type": "github" + } + }, + "authentik-src": { + "flake": false, + "locked": { + "lastModified": 1744135136, + "narHash": "sha256-7wvoCRhLipX4qzrb/ctsozG565yckx+moxiF6vRo84I=", + "owner": "goauthentik", + "repo": "authentik", + "rev": "74eab55c615b156e4191ee98dc789e2d58c016f9", + "type": "github" + }, + "original": { + "owner": "goauthentik", + "ref": "version/2025.2.4", + "repo": "authentik", + "type": "github" + } + }, + "course-management": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_2", + "poetry2nix": "poetry2nix_2" + }, + "locked": { + "lastModified": 1730751072, + "narHash": "sha256-+FQjzCNV3k8U4BfNcFmoZTRf8aO9ufn3s7kkzHj/b7s=", "owner": "fsr", "repo": "course-management", - "rev": "5ccbee8151c5caa519ebdb2ce2b8ec52b7749949", + "rev": "60b7062ce47ee9f0609e701ad5eb5e3e0a857ff2", "type": "github" }, "original": { @@ -22,16 +62,73 @@ "type": "github" } }, - "flake-utils": { + "ese-manual": { "inputs": { - "systems": "systems" + "nixpkgs": [ + "nixpkgs" + ] }, "locked": { - "lastModified": 1687709756, - "narHash": "sha256-Y5wKlQSkgEK2weWdOu4J3riRd+kV/VCgHsqLNTTWQ/0=", + "lastModified": 1730889586, + "narHash": "sha256-SLgo7UjWLaFaaUPFqzKbr9DLAGzm5kparfxuJHEpK3w=", + "ref": "refs/heads/main", + "rev": "a111147ce5eaea4f1d691afe1203e7529d68522d", + "revCount": 9, + "type": "git", + "url": "https://git.ifsr.de/ese/manual-website" + }, + "original": { + "type": "git", + "url": "https://git.ifsr.de/ese/manual-website" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1743550720, + "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c621e8422220273271f52058f618c94e405bb0f5", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": [ + "authentik", + "systems" + ] + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "dbabf0ca0c0c4bce6ea5eaf65af5cb694d2082c7", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -45,11 +142,47 @@ "systems": "systems_2" }, "locked": { - "lastModified": 1687709756, - "narHash": "sha256-Y5wKlQSkgEK2weWdOu4J3riRd+kV/VCgHsqLNTTWQ/0=", + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "dbabf0ca0c0c4bce6ea5eaf65af5cb694d2082c7", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "inputs": { + "systems": "systems_6" + }, + "locked": { + "lastModified": 1681202837, + "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "cfacdce06f30d2b68473a46042957675eebb3401", "type": "github" }, "original": { @@ -65,11 +198,11 @@ ] }, "locked": { - "lastModified": 1693305731, - "narHash": "sha256-ku0FU1pn6eXGdoEx0Tg0Kp8c8wmd6TF7IrdOnX0Uco0=", + "lastModified": 1744024964, + "narHash": "sha256-zmYWGZ7/tRSCy/PzghdguMpAdauWiYr6AJnbYCVHBFE=", "owner": "fsr", "repo": "kpp", - "rev": "7c04f958bb652de680ae3311b6eab080ac64b3ad", + "rev": "03e9650edb8d1e9ff424c2c2799736fbae56314b", "type": "github" }, "original": { @@ -78,52 +211,217 @@ "type": "github" } }, + "napalm": { + "inputs": { + "flake-utils": [ + "authentik", + "flake-utils" + ], + "nixpkgs": [ + "authentik", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1725806412, + "narHash": "sha256-lGZjkjds0p924QEhm/r0BhAxbHBJE1xMOldB/HmQH04=", + "owner": "willibutz", + "repo": "napalm", + "rev": "b492440d9e64ae20736d3bec5c7715ffcbde83f5", + "type": "github" + }, + "original": { + "owner": "willibutz", + "ref": "avoid-foldl-stack-overflow", + "repo": "napalm", + "type": "github" + } + }, + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "authentik", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1729742964, + "narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "e04df33f62cdcf93d73e9a04142464753a16db67", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix-github-actions_2": { + "inputs": { + "nixpkgs": [ + "course-management", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1729742964, + "narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "e04df33f62cdcf93d73e9a04142464753a16db67", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix-index-database": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1745725746, + "narHash": "sha256-iR+idGZJ191cY6NBXyVjh9QH8GVWTkvZw/w+1Igy45A=", + "owner": "nix-community", + "repo": "nix-index-database", + "rev": "187524713d0d9b2d2c6f688b81835114d4c2a7c6", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-index-database", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1694499547, - "narHash": "sha256-R7xMz1Iia6JthWRHDn36s/E248WB1/je62ovC/dUVKI=", - "owner": "nixos", + "lastModified": 1745391562, + "narHash": "sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "e5f018cf150e29aac26c61dac0790ea023c46b24", + "rev": "8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7", "type": "github" }, "original": { - "owner": "nixos", - "ref": "nixos-23.05", + "owner": "NixOS", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-stable": { + "nixpkgs-lib": { "locked": { - "lastModified": 1693675694, - "narHash": "sha256-2pIOyQwGyy2FtFAUIb8YeKVmOCcPOTVphbAvmshudLE=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "5601118d39ca9105f8e7b39d4c221d3388c0419d", + "lastModified": 1743296961, + "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "release-23.05", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1730531603, + "narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, + "nixpkgs_3": { + "locked": { + "lastModified": 1745742390, + "narHash": "sha256-1rqa/XPSJqJg21BKWjzJZC7yU0l/YTVtjRi0RJmipus=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "26245db0cb552047418cfcef9a25da91b222d6c7", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-24.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1682134069, + "narHash": "sha256-TnI/ZXSmRxQDt2sjRYK/8j8iha4B4zP2cnQCZZ3vp7k=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "fd901ef4bf93499374c5af385b2943f5801c0833", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "notenrechner": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "utils": "utils" + }, + "locked": { + "lastModified": 1742228793, + "narHash": "sha256-USud87Uu/ZI6R+4vM0hxLdkOUr6nsJCnAEeIrtSRkCU=", + "ref": "refs/heads/main", + "rev": "c100e3dba23a089fbdf403d2ba31cf87614ee035", + "revCount": 10, + "type": "git", + "url": "https://git.ifsr.de/frieder.hannenheim/notenrechner.git" + }, + "original": { + "type": "git", + "url": "https://git.ifsr.de/frieder.hannenheim/notenrechner.git" + } + }, "poetry2nix": { "inputs": { - "flake-utils": "flake-utils_2", + "flake-utils": [ + "authentik", + "flake-utils" + ], + "nix-github-actions": "nix-github-actions", "nixpkgs": [ - "course-management", + "authentik", "nixpkgs" - ] + ], + "systems": [ + "authentik", + "systems" + ], + "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1688440303, - "narHash": "sha256-hFfOyityHdVFI0HNM+sqZfpi9Fbvjvy0N9O7FjuqPWY=", + "lastModified": 1743690424, + "narHash": "sha256-cX98bUuKuihOaRp8dNV1Mq7u6/CQZWTPth2IJPATBXc=", "owner": "nix-community", "repo": "poetry2nix", - "rev": "04714155bae013fb9b207e54d1faf9f0c3d08706", + "rev": "ce2369db77f45688172384bbeb962bc6c2ea6f94", "type": "github" }, "original": { @@ -132,27 +430,77 @@ "type": "github" } }, + "poetry2nix_2": { + "inputs": { + "flake-utils": "flake-utils_3", + "nix-github-actions": "nix-github-actions_2", + "nixpkgs": [ + "course-management", + "nixpkgs" + ], + "systems": "systems_4", + "treefmt-nix": "treefmt-nix_2" + }, + "locked": { + "lastModified": 1730284601, + "narHash": "sha256-eHYcKVLIRRv3J1vjmxurS6HVdGphB53qxUeAkylYrZY=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "43a898b4d76f7f3f70df77a2cc2d40096bc9d75e", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, + "print-interface": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1706540741, + "narHash": "sha256-4/JI3xhw76Z1oa8Ivn3AzR6zNqXkmSEgHl+v0PRGnTc=", + "owner": "fsr", + "repo": "print-interface", + "rev": "ca830bc64ee92ec24562e707ddf36c19a5607a94", + "type": "github" + }, + "original": { + "owner": "fsr", + "repo": "print-interface", + "type": "github" + } + }, "root": { "inputs": { + "authentik": "authentik", "course-management": "course-management", + "ese-manual": "ese-manual", "kpp": "kpp", - "nixpkgs": "nixpkgs", - "sops-nix": "sops-nix" + "nix-index-database": "nix-index-database", + "nixpkgs": "nixpkgs_3", + "notenrechner": "notenrechner", + "print-interface": "print-interface", + "sops-nix": "sops-nix", + "vscode-server": "vscode-server" } }, "sops-nix": { "inputs": { "nixpkgs": [ "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" + ] }, "locked": { - "lastModified": 1694495315, - "narHash": "sha256-sZEYXs9T1NVHZSSbMqBEtEm2PGa7dEDcx0ttQkArORc=", + "lastModified": 1745310711, + "narHash": "sha256-ePyTpKEJTgX0gvgNQWd7tQYQ3glIkbqcW778RpHlqgA=", "owner": "Mic92", "repo": "sops-nix", - "rev": "ea208e55f8742fdcc0986b256bdfa8986f5e4415", + "rev": "5e3e92b16d6fdf9923425a8d4df7496b2434f39c", "type": "github" }, "original": { @@ -163,16 +511,16 @@ }, "systems": { "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", "type": "github" }, "original": { "owner": "nix-systems", - "repo": "default", + "repo": "default-linux", "type": "github" } }, @@ -190,6 +538,146 @@ "repo": "default", "type": "github" } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "id": "systems", + "type": "indirect" + } + }, + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_6": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "authentik", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1730120726, + "narHash": "sha256-LqHYIxMrl/1p3/kvm2ir925tZ8DkI0KA10djk8wecSk=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "9ef337e492a5555d8e17a51c911ff1f02635be15", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "treefmt-nix_2": { + "inputs": { + "nixpkgs": [ + "course-management", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1730120726, + "narHash": "sha256-LqHYIxMrl/1p3/kvm2ir925tZ8DkI0KA10djk8wecSk=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "9ef337e492a5555d8e17a51c911ff1f02635be15", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "utils": { + "inputs": { + "systems": "systems_5" + }, + "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" + } + }, + "vscode-server": { + "inputs": { + "flake-utils": "flake-utils_4", + "nixpkgs": "nixpkgs_4" + }, + "locked": { + "lastModified": 1729422940, + "narHash": "sha256-DlvJv33ml5UTKgu4b0HauOfFIoDx6QXtbqUF3vWeRCY=", + "owner": "nix-community", + "repo": "nixos-vscode-server", + "rev": "8b6db451de46ecf9b4ab3d01ef76e59957ff549f", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixos-vscode-server", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 9f0c453..923b081 100755 --- a/flake.nix +++ b/flake.nix @@ -1,61 +1,132 @@ { inputs = { - nixpkgs.url = github:nixos/nixpkgs/nixos-23.05; - sops-nix.url = github:Mic92/sops-nix; + nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; + sops-nix.url = "github:Mic92/sops-nix"; sops-nix.inputs.nixpkgs.follows = "nixpkgs"; + nix-index-database.url = "github:nix-community/nix-index-database"; + nix-index-database.inputs.nixpkgs.follows = "nixpkgs"; kpp.url = "github:fsr/kpp"; kpp.inputs.nixpkgs.follows = "nixpkgs"; - course-management = { - url = "github:fsr/course-management"; + print-interface = { + url = "github:fsr/print-interface"; inputs.nixpkgs.follows = "nixpkgs"; }; - }; - outputs = { self, nixpkgs, sops-nix, kpp, course-management, ... }@inputs: - { - packages."x86_64-linux".quitte = self.nixosConfigurations.quitte.config.system.build.toplevel; - packages."x86_64-linux".default = self.packages."x86_64-linux".quitte; - formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixpkgs-fmt; - hydraJobs."x86-64-linux".quitte = self.packages."x86_64-linux".quitte; + ese-manual.url = "git+https://git.ifsr.de/ese/manual-website"; + ese-manual.inputs.nixpkgs.follows = "nixpkgs"; + vscode-server.url = "github:nix-community/nixos-vscode-server"; + notenrechner.url = "git+https://git.ifsr.de/frieder.hannenheim/notenrechner.git"; + notenrechner.inputs.nixpkgs.follows = "nixpkgs"; + authentik = { + url = "github:nix-community/authentik-nix"; + }; + + course-management = { + url = "github:fsr/course-management"; + # inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + outputs = + { self + , nixpkgs + , sops-nix + , nix-index-database + , kpp + , ese-manual + , vscode-server + , course-management + , print-interface + , authentik + , ... + }@inputs: + let + supportedSystems = [ "x86_64-linux" ]; + forAllSystems = nixpkgs.lib.genAttrs supportedSystems; + pkgs = forAllSystems (system: nixpkgs.legacyPackages.${system}); + + in + { + packages = forAllSystems (system: rec { + default = quitte; + quitte = self.nixosConfigurations.quitte.config.system.build.toplevel; + tomate = self.nixosConfigurations.tomate.config.system.build.toplevel; + }); + formatter = forAllSystems (system: pkgs.${system}.nixpkgs-fmt); + hydraJobs = forAllSystems (system: { + quitte = self.packages.${system}.quitte; + }); + + devShells = forAllSystems (system: { + default = pkgs.${system}.mkShell { + packages = with pkgs.${system}; [ + sops + ]; + }; + }); + overlays.default = import ./overlays; nixosConfigurations = { - quitte = nixpkgs.lib.nixosSystem { + quitte = nixpkgs.lib.nixosSystem rec { system = "x86_64-linux"; + specialArgs = inputs // { inherit system; }; modules = [ inputs.sops-nix.nixosModules.sops inputs.kpp.nixosModules.default + inputs.nix-index-database.nixosModules.nix-index + ese-manual.nixosModules.default course-management.nixosModules.default + vscode-server.nixosModules.default + authentik.nixosModules.default + ./hosts/quitte/configuration.nix - ./modules/bacula.nix - ./modules/options.nix - ./modules/base.nix - ./modules/sops.nix - ./modules/kpp.nix + ./options + + ./modules/core + ./modules/authentik ./modules/ldap ./modules/mail - ./modules/mailman.nix - ./modules/nginx.nix - ./modules/hydra.nix - ./modules/userdir.nix + ./modules/web + ./modules/courses + ./modules/wiki + ./modules/matrix + ./modules/keycloak + ./modules/monitoring + + ./modules/nix-serve.nix ./modules/hedgedoc.nix ./modules/padlist.nix - ./modules/postgres.nix - ./modules/wiki.nix - ./modules/ftp.nix - ./modules/stream.nix ./modules/nextcloud.nix - ./modules/matrix.nix - ./modules/mautrix-telegram.nix - ./modules/sogo.nix ./modules/vaultwarden.nix - ./modules/website.nix - ./modules/zsh.nix - ./modules/course-management.nix - ./modules/gitea.nix + ./modules/forgejo + ./modules/kanboard.nix + ./modules/zammad.nix + # ./modules/decisions.nix + ./modules/stream.nix + # ./modules/struktur-bot.nix { + nixpkgs.overlays = [ + self.overlays.default + ]; sops.defaultSopsFile = ./secrets/quitte.yaml; } ]; }; + tomate = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = inputs; + modules = [ + inputs.sops-nix.nixosModules.sops + inputs.nix-index-database.nixosModules.nix-index + vscode-server.nixosModules.default + print-interface.nixosModules.default + ./hosts/tomate/configuration.nix + ./modules/core/base.nix + ./modules/core/zsh.nix + ./modules/core/sssd.nix + { + sops.defaultSopsFile = ./secrets/tomate.yaml; + } + ]; + }; }; }; } diff --git a/hosts/quitte/configuration.nix b/hosts/quitte/configuration.nix index 98b70a7..7f75d9d 100644 --- a/hosts/quitte/configuration.nix +++ b/hosts/quitte/configuration.nix @@ -7,47 +7,61 @@ ./network.nix ]; - # Use the systemd-boot EFI boot loader. - boot.loader.systemd-boot.enable = true; - #boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages; - #boot.kernelParams = [ "video=VGA-1:1024x768@30" ]; + boot.loader.systemd-boot = { + enable = true; + extraInstallCommands = '' + ${pkgs.coreutils}/bin/cp -r /boot/* /boot2 + ''; + }; + # boot.kernelParams = [ "video=VGA-1:1024x768@30" ]; boot.loader.efi.canTouchEfiVariables = true; - #boot.supportedFilesystems = [ "zfs" ]; - #boot.zfs.devNodes = "/dev/"; + boot.supportedFilesystems = [ "zfs" ]; - services.qemuGuest.enable = true; - - # don't freeze the whole system while building something - nix.settings.cores = 16; - - # allows everyone in the nix-trusted group to perform builds - nix.settings.trusted-users = [ "@nix-trusted" ]; + services.zfs = { + trim.enable = true; + autoScrub.enable = true; + }; # Set your time zone. time.timeZone = "Europe/Berlin"; + i18n.defaultLocale = "en_US.UTF-8"; - # List packages installed in system profile. To search, run: - # $ nix search wget - environment.systemPackages = with pkgs; [ - vim - wget - git + security.sudo.extraRules = [ + { + commands = [ + { + command = "ALL"; + options = [ "NOPASSWD" ]; + } + ]; + groups = [ "admins" ]; + } + ]; + # prevent fork bombs + security.pam.loginLimits = [ + { + domain = "@users"; + item = "nproc"; + type = "hard"; + value = "2000"; + } + { + domain = "@nixbld"; + item = "nproc"; + type = "hard"; + value = "10000"; + } ]; - # Enable the OpenSSH daemon. - services.openssh.enable = true; - services.openssh.settings.PermitRootLogin = "yes"; - - # Open ports in the firewall. - networking.firewall.allowedTCPPorts = [ 443 80 ]; - # networking.firewall.allowedUDPPorts = [ ... ]; - # Or disable the firewall altogether. - # networking.firewall.enable = false; - - # Copy the NixOS configuration file and link it from the resulting system - # (/run/current-system/configuration.nix). This is useful in case you - # accidentally delete configuration.nix. - # system.copySystemConfiguration = true; + systemd = { + services.nix-daemon.serviceConfig = { + MemoryMax = "32G"; + }; + # all users together may not use more than $MemoryMax of RAM + slices."user".sliceConfig = { + MemoryMax = "32G"; + }; + }; # This value determines the NixOS release from which the default # settings for stateful data, like file locations and database versions diff --git a/hosts/quitte/hardware-configuration.nix b/hosts/quitte/hardware-configuration.nix index 3c7c759..5dad929 100644 --- a/hosts/quitte/hardware-configuration.nix +++ b/hosts/quitte/hardware-configuration.nix @@ -1,42 +1,52 @@ -# Do not modify this file! It was generated by ‘nixos-generate-config’ -# and may be overwritten by future invocations. Please make changes -# to /etc/nixos/configuration.nix instead. { config, lib, modulesPath, ... }: { - imports = - [ - (modulesPath + "/profiles/qemu-guest.nix") - ]; + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; - boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ]; + boot.initrd.availableKernelModules = [ "megaraid_sas" "xhci_pci" "nvme" "ahci" "usbhid" "usb_storage" "sd_mod" "sr_mod" ]; boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; boot.extraModulePackages = [ ]; - fileSystems."/" = - { - device = "/dev/disk/by-uuid/4d57c7c1-ed70-4fb1-af4c-4ba027b75248"; - fsType = "ext4"; - }; + fileSystems."/" = { + device = "rpool/nixos/root"; + fsType = "zfs"; + }; - boot.initrd.luks.devices."luksroot".device = "/dev/disk/by-uuid/cfb9b37e-152d-45e9-b75d-88d71471be45"; + fileSystems."/home" = { + device = "rpool/nixos/home"; + fsType = "zfs"; + }; - fileSystems."/boot" = - { - device = "/dev/disk/by-uuid/06C4-1FDB"; - fsType = "vfat"; - }; + fileSystems."/nix" = { + device = "rpool/nixos/nixnew"; + fsType = "zfs"; + }; + + fileSystems."/var/lib" = { + device = "rpool/nixos/var/lib"; + fsType = "zfs"; + }; + + fileSystems."/var/log" = { + device = "rpool/nixos/var/log"; + fsType = "zfs"; + }; + + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/3278-8D00"; + fsType = "vfat"; + options = [ "nofail" ]; + }; + fileSystems."/boot2" = { + device = "/dev/disk/by-uuid/3366-F71E"; + fsType = "vfat"; + options = [ "nofail" ]; + }; swapDevices = [ ]; - - # Enables DHCP on each ethernet and wireless interface. In case of scripted networking - # (the default) this is the recommended approach. When using systemd-networkd it's - # still possible to use this option, but it's recommended to use it in conjunction - # with explicit per-interface declarations with `networking.interfaces..useDHCP`. - networking.useDHCP = lib.mkDefault true; - # networking.interfaces.ens18.useDHCP = lib.mkDefault true; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; } diff --git a/hosts/quitte/network.nix b/hosts/quitte/network.nix index 858f70e..f984edd 100644 --- a/hosts/quitte/network.nix +++ b/hosts/quitte/network.nix @@ -1,88 +1,59 @@ -{ config, ... }: -let - wireguard_port = 51820; -in +{ config, lib, ... }: { - sops.secrets = { - "wg-fsr" = { - owner = config.users.users.systemd-network.name; - }; - }; - networking = { + # portunus module does weird things to this, so we force it to some sane values + hosts = { + "127.0.0.1" = lib.mkForce [ "quitte.ifsr.de" "quitte" ]; + "::1" = lib.mkForce [ "quitte.ifsr.de" "quitte" ]; + }; hostId = "a71c81fc"; domain = "ifsr.de"; hostName = "quitte"; rDNS = config.networking.fqdn; - enableIPv6 = true; - useDHCP = true; - interfaces.ens18.useDHCP = true; useNetworkd = true; + nftables.enable = true; - firewall.allowedUDPPorts = [ wireguard_port ]; - wireguard.enable = true; + firewall = { + logRefusedConnections = false; + trustedInterfaces = [ "podman0"]; + }; }; services.resolved = { enable = true; - #dnssec = "false"; - fallbackDns = [ "1.1.1.1" ]; + fallbackDns = [ "9.9.9.9" ]; }; - # workaround for networkd waiting for shit - systemd.services.systemd-networkd-wait-online.serviceConfig.ExecStart = [ - "" # clear old command - "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online --any" - ]; - systemd.network = { enable = true; + wait-online.anyInterface = true; # Interfaces on the machine - networks."10-ether-bond" = { - matchConfig.Name = "ens18"; + networks."10-wired-default" = { + matchConfig.Name = "enp65s0f0np0"; - address = [ "141.30.30.169/25" ]; + address = [ + + "141.30.30.194/26" + "2a13:dd85:b23:1::1337/64" + ]; routes = [ { - routeConfig.Gateway = "141.30.30.129"; + Gateway = "141.30.30.193"; } - ]; - networkConfig = { - DNS = "141.30.1.1"; - #IPv6AcceptRA = true; - }; - }; - - # defining network device for wireguard connections - netdevs."fsr-wg" = { - netdevConfig = { - Kind = "wireguard"; - Name = "fsr-wg"; - Description = "fsr enterprise wireguard"; - }; - wireguardConfig = { - PrivateKeyFile = config.sops.secrets."wg-fsr".path; - ListenPort = wireguard_port; - }; - wireguardPeers = [ { - # tassilo - wireguardPeerConfig = { - PublicKey = "vgo3le9xrFsIbbDZsAhQZpIlX+TuWjfEyUcwkoqUl2Y="; - AllowedIPs = [ "10.66.66.100/32" ]; - PersistentKeepalive = 25; - }; + Gateway = "fe80::7a24:59ff:fe5e:6e2f"; } ]; - }; - - # fsr wireguard server - networks."fsr-wg" = { - matchConfig.Name = "fsr-wg"; networkConfig = { - Address = "10.66.66.1/24"; - IPForward = "ipv4"; + DNS = [ + "9.9.9.9" + "149.112.112.112" + "2620:fe::fe" + "2620:fe::9" + ]; + LLDP = true; + EmitLLDP = "nearest-bridge"; }; }; }; diff --git a/hosts/tomate/configuration.nix b/hosts/tomate/configuration.nix new file mode 100644 index 0000000..dffdcea --- /dev/null +++ b/hosts/tomate/configuration.nix @@ -0,0 +1,176 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: + +{ + imports = + [ + # Include the results of the hardware scan. + ./network.nix + ./hardware-configuration.nix + ]; + + # Bootloader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + + nix = { + settings = { + substituters = [ + "https://cache.ifsr.de" + ]; + trusted-public-keys = [ + "cache.ifsr.de:y55KBAMF4YkjIzXwYOKVk9fcQS+CZ9RM1zAAMYQJtsg=" + ]; + }; + }; + + # Set your time zone. + time.timeZone = "Europe/Berlin"; + + # Select internationalisation properties. + i18n.defaultLocale = "de_DE.UTF-8"; + + i18n.extraLocaleSettings = { + LC_ADDRESS = "de_DE.UTF-8"; + LC_IDENTIFICATION = "de_DE.UTF-8"; + LC_MEASUREMENT = "de_DE.UTF-8"; + LC_MONETARY = "de_DE.UTF-8"; + LC_NAME = "de_DE.UTF-8"; + LC_NUMERIC = "de_DE.UTF-8"; + LC_PAPER = "de_DE.UTF-8"; + LC_TELEPHONE = "de_DE.UTF-8"; + LC_TIME = "de_DE.UTF-8"; + }; + + # Enable the X11 windowing system. + services.xserver.enable = true; + + # Enable the KDE Plasma Desktop Environment. + services.displayManager.sddm.enable = true; + services.xserver.desktopManager.plasma5.enable = true; + + # Configure keymap in X11 + services.xserver = { + xkb.layout = "de"; + xkb.variant = ""; + }; + + # Configure console keymap + console.keyMap = "de"; + + + + services.printing = { + enable = true; + stateless = true; + drivers = with pkgs; [ cups-kyocera ]; + browsing = true; + defaultShared = true; + # todo fix + allowFrom = [ "all" ]; + listenAddresses = [ "0.0.0.0:631" ]; + }; + + sops.secrets."print/smtp-password" = { + owner = config.services.print-interface.user; + group = config.services.print-interface.group; + }; + + services.print-interface = { + enable = true; + smtp = { + username = "print"; + passwordFile = config.sops.secrets."print/smtp-password".path; + }; + }; + + services.avahi = { + enable = true; + nssmdns4 = true; + openFirewall = true; + publish = { + enable = true; + userServices = true; + }; + }; + networking.firewall = { + allowedTCPPorts = [ + 631 + config.services.print-interface.listenPort + ]; + allowedUDPPorts = [ 631 ]; + }; + + # Enable sound with pipewire. + hardware.pulseaudio.enable = false; + security.rtkit.enable = true; + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + # If you want to use JACK applications, uncomment this + #jack.enable = true; + + # use the example session manager (no others are packaged yet so this is enabled by default, + # no need to redefine it in your config for now) + #media-session.enable = true; + }; + + # Enable touchpad support (enabled default in most desktopManager). + # services.xserver.libinput.enable = true; + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; [ + # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. + # wget + ]; + security = { + pam = { + u2f = { + enable = true; + }; + services = { + login.u2fAuth = true; + sudo.u2fAuth = true; + }; + }; + + }; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # 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 = "23.05"; # Did you read the comment? + +} diff --git a/hosts/tomate/hardware-configuration.nix b/hosts/tomate/hardware-configuration.nix new file mode 100644 index 0000000..4d71ba7 --- /dev/null +++ b/hosts/tomate/hardware-configuration.nix @@ -0,0 +1,42 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, modulesPath, ... }: + +{ + imports = + [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "ohci_pci" "ehci_pci" "usbhid" "usb_storage" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { + device = "/dev/disk/by-uuid/618e281f-a8bf-4129-bfc1-aa47f86a8c54"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { + device = "/dev/disk/by-uuid/0844-2A73"; + fsType = "vfat"; + }; + + swapDevices = + [{ device = "/dev/disk/by-uuid/8bdeb0c1-8f1e-43a7-b4b9-c06e27a94460"; }]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp3s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/tomate/network.nix b/hosts/tomate/network.nix new file mode 100644 index 0000000..dd04916 --- /dev/null +++ b/hosts/tomate/network.nix @@ -0,0 +1,40 @@ +{ config, ... }: +{ + sops.secrets.ifsr-apb-auth = { }; + networking = { + domain = "ifsr.de"; + hostName = "tomate"; + useNetworkd = true; + nftables.enable = true; + # Radius authentification + supplicant."enp3s0" = { + driver = "wired"; + configFile.path = config.sops.secrets.ifsr-apb-auth.path; + }; + }; + + services.resolved = { + enable = true; + fallbackDns = [ "9.9.9.9" ]; + }; + + systemd.network = { + enable = true; + + networks."10-wired-default" = { + matchConfig.Name = "enp3s0"; + + address = [ "141.30.86.196/26" ]; + routes = [ + { + Gateway = "141.30.86.193"; + } + ]; + networkConfig = { + DNS = "141.30.1.1"; + LLDP = true; + EmitLLDP = "nearest-bridge"; + }; + }; + }; +} diff --git a/keys/pgp/hendrik.asc b/keys/pgp/hendrik.asc new file mode 100644 index 0000000..ad13ab9 --- /dev/null +++ b/keys/pgp/hendrik.asc @@ -0,0 +1,23 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mDMEZNJqYBYJKwYBBAHaRw8BAQdAKncDaEdOUQGOqVBQuEsJ42wCcyLB7x1XcNDZ +VEQpVyO0JkhlbmRyaWsgV29sZmYgPGhlbmRyaWsud29sZmZAYWdkc24ubWU+iJAE +ExYIADgWIQT7v6wmDZKD0e8jl908pl6d1usxnQUCZNJqYAIbAwULCQgHAgYVCgkI +CwIEFgIDAQIeAQIXgAAKCRA8pl6d1usxnX6zAP9Rut+Yg31zBAiRdQxV4tlK+hko +wCq9WIKtIbBvrqv5/AEAujkRCgBpFeHzhId55QmvK0FXZgFgfy9wm/QtXb4+lQ64 +MwRk0mrEFgkrBgEEAdpHDwEBB0AidcMADt+W+eSbrInHeCPZThyd1V7NKEMhk3sL +xJApx4j1BBgWCAAmFiEE+7+sJg2Sg9HvI5fdPKZendbrMZ0FAmTSasQCGwIFCQeE +zgAAgQkQPKZendbrMZ12IAQZFggAHRYhBEK0YmsN4JpCoNWvKp5LZR/BVBjgBQJk +0mrEAAoJEJ5LZR/BVBjg6ogBAOcFh/S99L/aN6bQu9bYRPomakbNqypHA1YbodjG +1IQgAPwLj19BXNnQmTgYzY3bWmtcAc8lsGWTNkDDTZMRRTP+BSS1AP9qBuCeU/fj +2hpa17LiV6sjdRquxWQXjKxTlBRV8oKj1gD/WarlxiHt8nMn527FXuBrGZC+mZq2 +NvvoTb+uvZNliAq4OARk0mtEEgorBgEEAZdVAQUBAQdAkK0jBo/37NbRHMOYCal0 +9vGuK3KaxU3Cl9No+VbZDEYDAQgHiH4EGBYIACYWIQT7v6wmDZKD0e8jl908pl6d +1usxnQUCZNJrRAIbDAUJB4TOAAAKCRA8pl6d1usxnbaqAP9abTf+DibaAR6hdU9y +CEE5TD32EB+ySw/v45yCi28B8AEA5PcpwMD6emVrNQGeVChkOlwauwA3HkE6DDTO +yeebAwi4MwRk0mvNFgkrBgEEAdpHDwEBB0DSYGCNq15sOLj1wDJjoKoCRMGH8I/y +ARMUws7PQ4KPkYh+BBgWCAAmFiEE+7+sJg2Sg9HvI5fdPKZendbrMZ0FAmTSa80C +GyAFCQeEzgAACgkQPKZendbrMZ1HggEAxSBYuJ4BTr9GCl8e79HTSwg8iIIJx8Nc +REFvro0BrnEA/3AbyQYBQVAhqIwSSza5dr4+FiLbbVhPFcxU98TLBTQJ +=sA2V +-----END PGP PUBLIC KEY BLOCK----- diff --git a/keys/pgp/jonas.asc b/keys/pgp/jonas.asc deleted file mode 100644 index db77ff9..0000000 --- a/keys/pgp/jonas.asc +++ /dev/null @@ -1,77 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- - -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 -=Fs3l ------END PGP PUBLIC KEY BLOCK----- diff --git a/keys/ssh/frieder b/keys/ssh/frieder new file mode 100644 index 0000000..1e1228e --- /dev/null +++ b/keys/ssh/frieder @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH70IC7DaiGBYdftUhuOE9CatcdYj2L50eZfztQA+pVs fried@Frieders-Void-Laptop diff --git a/keys/ssh/jonasga b/keys/ssh/jonasga deleted file mode 100644 index 5081d1f..0000000 --- a/keys/ssh/jonasga +++ /dev/null @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDpOQuIl31BL16yXdLlbzSDCle6bjE3WNVXzOV9ibdzEC3PpUufJDTU7FMW3WCO9fnYJ5osPKbV9nou5/10mPuN0g+k1e0NWUZNHbG+5zRqS7QYGFmtDC8EUTx1xnri5zMBMn9jzjNE8BkqvsjGrHcVCtI2T51slwFjE60GFkloQ7izRDrNkge1iM57KhoXz5MeYJtolDqeOh5P7nfAUR4bGT/gGtYVd85oCvbsHcjF9vgDovAfNP+zQhUn51ZOXvGp8+1/MAJVtxLfjC9Ma3LRiiliD6w5zcsksG5cUGcj2Sk9i/7nTm7g5MGo4EKwgPMw/MRzSRzvlZ76oPSPSLKn jonas@T14s \ No newline at end of file diff --git a/modules/authentik/default.nix b/modules/authentik/default.nix new file mode 100644 index 0000000..eb65477 --- /dev/null +++ b/modules/authentik/default.nix @@ -0,0 +1,16 @@ +{ config, lib, ... }: +let + domain = "idm.${config.networking.domain}"; +in +{ + sops.secrets."authentik/env" = { }; + services.authentik = { + enable = true; + nginx = { + enable = true; + host = domain; + enableACME = true; + }; + environmentFile = config.sops.secrets."authentik/env".path; + }; +} diff --git a/modules/bacula.nix b/modules/bacula.nix deleted file mode 100644 index abb6c96..0000000 --- a/modules/bacula.nix +++ /dev/null @@ -1,78 +0,0 @@ -{ pkgs, config, lib, ... }: -with lib; - -let - # We write a custom config file because the upstream config has some flaws - fd_cfg = config.services.bacula-fd; - fd_conf = pkgs.writeText "bacula-fd.conf" '' - Client { - Name = ${fd_cfg.name} - FDPort = ${toString fd_cfg.port} - WorkingDirectory = /var/lib/bacula - Pid Directory = /run - ${fd_cfg.extraClientConfig} - } - - ${concatStringsSep "\n" (mapAttrsToList (name: value: '' - Director { - Name = ${name} - Password = ${value.password} - Monitor = ${value.monitor} - } - '') fd_cfg.director)} - - Messages { - Name = Standard; - syslog = all, !skipped, !restored - ${fd_cfg.extraMessagesConfig} - } - ''; - # AGDSN is running an outdated version that we have to comply to - bacula_package = (pkgs.bacula.overrideAttrs (old: rec { - version = "9.6.7"; - src = pkgs.fetchurl { - url = "mirror://sourceforge/bacula/${old.pname}-${version}.tar.gz"; - sha256 = "sha256-3w+FJezbo4DnS1N8pxrfO3WWWT8CGJtZqw6//IXMyN4="; - }; - })); -in -{ - sops.secrets = { - "bacula/password".owner = "bacula"; - "bacula/keypair".owner = "bacula"; - "bacula/masterkey".owner = "bacula"; - }; - networking.firewall.allowedTCPPorts = [ config.services.bacula-fd.port ]; - networking.firewall.allowedUDPPorts = [ config.services.bacula-fd.port ]; - services.bacula-fd = { - enable = true; - name = "ifsr-quitte"; - extraClientConfig = '' - Maximum Concurrent Jobs = 20 - FDAddress = 141.30.30.169 - PKI Signatures = Yes - PKI Encryption = Yes - PKI Keypair = ${config.sops.secrets."bacula/keypair".path} - PKI Master Key = ${config.sops.secrets."bacula/masterkey".path} - ''; - extraMessagesConfig = '' - director = abel-dir = all, !skipped, !restored - mailcommand = "${bacula_package}/bin/bsmtp -f \"Bacula \" -s \"Bacula report" %r" - mail = root+backup = all, !skipped - ''; - director."abel-dir".password = "@${config.sops.secrets."bacula/password".path}"; - }; - environment.etc."bacula/bconsole.conf".text = '' - Director { - Name = abel-dir - DIRport = 9101 - address = 10.144.0.11 - Password = @${config.sops.secrets."bacula/password".path} - } - Console { - Name = ifsr-quitte-console - Password = @${config.sops.secrets."bacula/password".path} - } - ''; - systemd.services.bacula-fd.serviceConfig.ExecStart = lib.mkForce "${bacula_package}/sbin/bacula-fd -f -u root -g bacula -c ${fd_conf}"; -} diff --git a/modules/core/bacula.nix b/modules/core/bacula.nix new file mode 100644 index 0000000..c28a7d2 --- /dev/null +++ b/modules/core/bacula.nix @@ -0,0 +1,47 @@ +{ pkgs, config, ... }: +{ + sops.secrets = { + "bacula/password".owner = "bacula"; + "bacula/keypair".owner = "bacula"; + "bacula/masterkey".owner = "bacula"; + }; + networking.firewall = { + extraInputRules = '' + ip saddr 10.144.0.11 tcp dport ${builtins.toString config.services.bacula-fd.port} accept comment "Only allow Bacula access from Abel" + ''; + }; + services.bacula-fd = { + enable = true; + name = "ifsr-quitte"; + extraClientConfig = '' + Comm Compression = no + Maximum Concurrent Jobs = 20 + FDAddress = 141.30.30.194 + PKI Signatures = Yes + PKI Encryption = Yes + PKI Keypair = ${config.sops.secrets."bacula/keypair".path} + PKI Master Key = ${config.sops.secrets."bacula/masterkey".path} + ''; + extraMessagesConfig = '' + director = abel-dir = all, !skipped, !restored + mailcommand = "${pkgs.bacula}/bin/bsmtp -f \"Bacula \" -s \"Bacula report" %r" + mail = root+backup = all, !skipped + ''; + director."abel-dir" = { + password = "@${config.sops.secrets."bacula/password".path}"; + tls.enable = false; + }; + }; + environment.etc."bacula/bconsole.conf".text = '' + Director { + Name = abel-dir + DIRport = 9101 + address = 10.144.0.11 + Password = @${config.sops.secrets."bacula/password".path} + } + Console { + Name = ifsr-quitte-console + Password = @${config.sops.secrets."bacula/password".path} + } + ''; +} diff --git a/modules/base.nix b/modules/core/base.nix similarity index 72% rename from modules/base.nix rename to modules/core/base.nix index a19083d..906aa65 100755 --- a/modules/base.nix +++ b/modules/core/base.nix @@ -1,6 +1,5 @@ { pkgs, config, ... }: { nix = { - package = pkgs.nixUnstable; # or versioned attributes like nix_2_4 extraOptions = '' experimental-features = nix-command flakes ''; @@ -11,10 +10,17 @@ echo System package diff: ${config.nix.package}/bin/nix store diff-closures /run/current-system $systemConfig || true fi + + NO_FORMAT="\033[0m" + F_BOLD="\033[1m" + C_RED="\033[38;5;9m" + ${pkgs.diffutils}/bin/cmp --silent \ + <(readlink /run/current-system/{kernel,kernel-modules}) \ + <(readlink $systemConfig/{kernel,kernel-modules}) \ + || echo -e "''${F_BOLD}''${C_RED}Kernel version changed, reboot is advised.''${NO_FORMAT}" ''; # Select internationalisation properties. - i18n.defaultLocale = "en_US.UTF-8"; console = { #font = "Lat2-Terminus16"; font = "${pkgs.terminus_font}/share/consolefonts/ter-u28n.psf.gz"; @@ -22,7 +28,17 @@ }; # Enable the OpenSSH daemon. - services.openssh.enable = true; + services.openssh = { + enable = true; + settings = { + PermitRootLogin = "yes"; + PasswordAuthentication = false; + }; + }; + programs.mosh.enable = true; + + # vs code server + services.vscode-server.enable = true; # set root ssh keys users.users.root.openssh.authorizedKeys = { @@ -40,32 +56,33 @@ # "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEXMHwy4AZ9B4pMRBa/P/rb7N3SCas9e7Lp89plTHdFS halcyon@eisvogel.moe" # "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAJ7qUGZUjiDhQ6Se+aXr9DbgRTG2tx69owqVMkd2bna simon@mayushii" "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLlITzcTVnSi8EpEW3leSuqYCDhbnJyoGCjFOtIJ0Dl5uRNm0UNXS7AbQtLLylEeI1+/qinQDEWAJ6cBDAaPfNw= rouven@thinkpad" - + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINJgYI2rXmw4uPXAMmOgqgJEwYfwj/IBExTCzs9Dgo+R w0lff" ]; keyFiles = [ - ../keys/ssh/marcus-sapphire - ../keys/ssh/schrader - ../keys/ssh/jannusch - ../keys/ssh/jannusch-arch - ../keys/ssh/tassilo - ../keys/ssh/jonasga - ../keys/ssh/rouven - ../keys/ssh/joachim + ../../keys/ssh/marcus-sapphire + ../../keys/ssh/schrader + ../../keys/ssh/jannusch + ../../keys/ssh/jannusch-arch + ../../keys/ssh/tassilo + ../../keys/ssh/rouven + ../../keys/ssh/joachim ]; }; time.timeZone = "Europe/Berlin"; # basic shell & editor + programs.vim.enable = true; programs.vim.defaultEditor = true; # List packages installed in system profile. To search, run: # $ nix search wget environment.systemPackages = with pkgs; [ atop + btop bat git - htop + htop-vim fd ripgrep tldr @@ -73,6 +90,7 @@ usbutils wget neovim + helix nmap tcpdump bat @@ -86,13 +104,17 @@ ltrace strace mtr + nix-output-monitor traceroute smartmontools sysstat tree whois - exa + eza zsh + unzip + yazi + imagemagick ]; } diff --git a/modules/core/default.nix b/modules/core/default.nix new file mode 100755 index 0000000..de763c0 --- /dev/null +++ b/modules/core/default.nix @@ -0,0 +1,15 @@ +{ ... }: { + imports = [ + ./base.nix + ./logging.nix + ./bacula.nix + ./fail2ban.nix + ./initrd-ssh.nix + ./mysql.nix + ./nginx.nix + ./podman.nix + ./postgres.nix + ./sssd.nix + ./zsh.nix + ]; +} diff --git a/modules/core/fail2ban.nix b/modules/core/fail2ban.nix new file mode 100644 index 0000000..5c08578 --- /dev/null +++ b/modules/core/fail2ban.nix @@ -0,0 +1,28 @@ +{ ... }: +{ + services.fail2ban = { + enable = true; + ignoreIP = [ + "141.30.0.0/16" + "141.76.0.0/16" + ]; + bantime-increment = { + enable = true; + }; + + jails = { + dovecot = '' + enabled = true + # aggressive mode to add blocking for aborted connections + filter = dovecot[mode=aggressive] + maxretry = 15 + ''; + postfix = '' + enabled = true + filter = postfix[mode=aggressive] + maxretry = 15 + ''; + sshd.settings.maxretry = 15; + }; + }; +} diff --git a/modules/core/initrd-ssh.nix b/modules/core/initrd-ssh.nix new file mode 100644 index 0000000..a244b21 --- /dev/null +++ b/modules/core/initrd-ssh.nix @@ -0,0 +1,29 @@ +# Find the required kernel module for the network adapter using `lspci -v` and add it to `boot.initrd.availableKernelModules`. +# Enable `networking.useDHCP` or set a static ip using the `ip=` kernel parameter. +# Generate another SSH host key for the machine: +# $ ssh-keygen -t ed25519 -N "" -f /etc/ssh/ssh_host_ed25519_key_initrd -C HOSTNAME-initrd +# Add the public key to your known_hosts and create an ssh config entry. +{ config, ... }: +{ + boot.initrd = { + availableKernelModules = [ "mlx5_core" ]; + systemd = { + enable = true; + network = { + enable = true; + networks."10-wired-default" = config.systemd.network.networks."10-wired-default"; + }; + users.root.shell = "/bin/systemd-tty-ask-password-agent"; + }; + network = { + enable = true; + ssh = { + enable = true; + port = 222; + hostKeys = [ "/etc/ssh/ssh_host_ed25519_key_initrd" ]; + # authorizedKeys option inherits root's authorizedKeys.keys, but not keyFiles + }; + }; + }; +} + diff --git a/modules/core/logging.nix b/modules/core/logging.nix new file mode 100644 index 0000000..75f482f --- /dev/null +++ b/modules/core/logging.nix @@ -0,0 +1,35 @@ +{ pkgs, ... }: +{ + services.rsyslogd = { + enable = true; + defaultConfig = '' + $FileCreateMode 0640 + :programname, isequal, "postfix" /var/log/postfix.log + :programname, isequal, "portunus" /var/log/portunus.log + + auth.* -/var/log/auth.log + ''; + }; + services.logrotate.configFile = pkgs.writeText "logrotate.conf" '' + weekly + missingok + notifempty + rotate 4 + "/var/log/postfix.log" { + compress + delaycompress + weekly + rotate 156 + } + "/var/log/nginx/*.log" { + compress + delaycompress + weekly + postrotate + [ ! -f /var/run/nginx/nginx.pid ] || kill -USR1 `cat /var/run/nginx/nginx.pid` + endscript + rotate 26 + su nginx nginx + } + ''; +} diff --git a/modules/core/mysql.nix b/modules/core/mysql.nix new file mode 100644 index 0000000..f35b278 --- /dev/null +++ b/modules/core/mysql.nix @@ -0,0 +1,19 @@ +{ pkgs, ... }: +{ + services.mysql = { + enable = true; + package = pkgs.mariadb; + settings.mysqld.bind_address = "127.0.0.1"; + }; + services.mysqlBackup = { + enable = true; + user = "mysql"; + location = "/var/lib/backup/mysql"; + databases = [ + "fsrewsp" + "nightline" + "wiki_ese" + "wiki_vernetzung" + ]; + }; +} diff --git a/modules/core/nginx.nix b/modules/core/nginx.nix new file mode 100644 index 0000000..36e596e --- /dev/null +++ b/modules/core/nginx.nix @@ -0,0 +1,64 @@ +{ lib, config, pkgs, ... }: +{ + # set default options for virtualHosts + options = with lib; { + services.nginx.virtualHosts = mkOption { + type = types.attrsOf (types.submodule + ({ name, ... }: { + enableACME = true; + forceSSL = true; + # enable http3 for all hosts + quic = true; + http3 = true; + # split up nginx access logs per vhost + extraConfig = '' + access_log /var/log/nginx/${name}_access.log; + error_log /var/log/nginx/${name}_error.log; + add_header Alt-Svc 'h3=":443"; ma=86400'; + ''; + }) + ); + }; + }; + + config = { + networking.firewall.allowedTCPPorts = [ 80 443 ]; + networking.firewall.allowedUDPPorts = [ 443 ]; + services.nginx = { + enable = true; + package = pkgs.nginxQuic; + additionalModules = [ pkgs.nginxModules.pam ]; + recommendedProxySettings = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedTlsSettings = true; + + # appendHttpConfig = '' + # map $remote_addr $remote_addr_anon { + # ~(?P\d+\.\d+\.\d+)\. $ip.0; + # ~(?P[^:]+:[^:]+): $ip::; + # # IP addresses to not anonymize + # 127.0.0.1 $remote_addr; + # ::1 $remote_addr; + # default 0.0.0.0; + # } + # log_format anon_ip '$remote_addr_anon - $remote_user [$time_local] "$request" ' + # '$status $body_bytes_sent "$http_referer" ' + # '"$http_user_agent" "$http_x_forwarded_for"'; + + # access_log /var/log/nginx/access.log anon_ip; + # ''; + }; + security.acme = { + acceptTerms = true; + defaults = { + #server = "https://acme-staging-v02.api.letsencrypt.org/directory"; + email = "root@${config.networking.domain}"; + }; + }; + security.pam.services.nginx.text = '' + auth required ${pkgs.nss_pam_ldapd}/lib/security/pam_ldap.so + account required ${pkgs.nss_pam_ldapd}/lib/security/pam_ldap.so + ''; + }; +} diff --git a/modules/core/podman.nix b/modules/core/podman.nix new file mode 100644 index 0000000..9927a43 --- /dev/null +++ b/modules/core/podman.nix @@ -0,0 +1,26 @@ +{ pkgs, ... }: +{ + # From: https://nixos.wiki/wiki/Podman + virtualisation.containers.enable = true; + virtualisation = { + podman = { + enable = true; + + # Create a `docker` alias for podman, to use it as a drop-in replacement + dockerCompat = true; + + # Required for containers under podman-compose to be able to talk to each other. + defaultNetwork.settings.dns_enabled = true; + }; + }; + virtualisation.oci-containers.backend = "podman"; + + + # Useful otherdevelopment tools + environment.systemPackages = with pkgs; [ + dive # look into docker image layers + podman-tui # status of containers in the terminal + #docker-compose # start group of containers for dev + #podman-compose # start group of containers for dev + ]; +} diff --git a/modules/postgres.nix b/modules/core/postgres.nix similarity index 73% rename from modules/postgres.nix rename to modules/core/postgres.nix index 331c24a..daf44ff 100644 --- a/modules/postgres.nix +++ b/modules/core/postgres.nix @@ -6,8 +6,10 @@ location = "/var/lib/backup/postgresql"; databases = [ "course-management" - "gitea" + "git" + "grafana" "hedgedoc" + "keycloak" "matrix-synapse" "mautrix-telegram" "mediawiki" @@ -16,7 +18,10 @@ "sogo" "vaultwarden" "mailman" - "mailmanweb" + "mailman-web" + "zammad" ]; }; + + services.postgresql.settings.max_connections = 1000; } diff --git a/modules/core/sssd.nix b/modules/core/sssd.nix new file mode 100644 index 0000000..a23a0bb --- /dev/null +++ b/modules/core/sssd.nix @@ -0,0 +1,41 @@ +{ config, ... }: +{ + sops.secrets = { + "sssd/env" = { }; + + }; + services.sssd = { + enable = true; + environmentFile = config.sops.secrets."sssd/env".path; + sshAuthorizedKeysIntegration = true; + config = '' + [sssd] + config_file_version = 2 + services = nss, pam, ssh + domains = ldap + + [ssh] + + [nss] + + [pam] + + [domain/ldap] + auth_provider = ldap + ldap_uri = ldaps://auth.ifsr.de + ldap_default_authtok_type = password + ldap_default_authtok = $SSSD_LDAP_DEFAULT_AUTHTOK + ldap_search_base = dc=ifsr,dc=de + id_provider = ldap + ldap_default_bind_dn = uid=search,ou=users,dc=ifsr,dc=de + cache_credentials = True + ldap_tls_cacert = /etc/ssl/certs/ca-bundle.crt + ldap_tls_reqcert = hard + ''; + + }; + security.pam.services = { + sshd.makeHomeDir = true; + login.makeHomeDir = true; + }; +} diff --git a/modules/core/zsh.nix b/modules/core/zsh.nix new file mode 100644 index 0000000..349f3dd --- /dev/null +++ b/modules/core/zsh.nix @@ -0,0 +1,35 @@ +{ lib, pkgs, ... }: +{ + users.users.root.shell = pkgs.zsh; + programs.command-not-found.enable = false; + programs.nix-index-database.comma.enable = true; + environment.systemPackages = with pkgs; [ + # fzf + bat + duf + ]; + programs.fzf = { + keybindings = true; + }; + programs.zsh = { + enable = true; + autosuggestions = { + enable = true; + highlightStyle = "fg=#00bbbb,bold"; + }; + + # don't override agdsn-zsh-config aliases + shellAliases = lib.mkForce { }; + + shellInit = '' + zsh-newuser-install () {} + ''; + interactiveShellInit = '' + source ${pkgs.zsh-fzf-tab}/share/fzf-tab/fzf-tab.plugin.zsh + HW_CONF_ALIASES_GIT_AUTHOR_REMINDER=0 + source ${pkgs.agdsn-zsh-config}/etc/zsh/zshrc + ''; + promptInit = ""; + }; +} + diff --git a/modules/course-management.nix b/modules/courses/default.nix similarity index 66% rename from modules/course-management.nix rename to modules/courses/default.nix index 88cbc3b..9b971fd 100644 --- a/modules/course-management.nix +++ b/modules/courses/default.nix @@ -38,15 +38,28 @@ in enable = lib.mkForce true; # upstream bacula config wants to disable it, so we need to force ensureUsers = [{ name = "course-management"; - ensurePermissions = { - "DATABASE \"course-management\"" = "ALL PRIVILEGES"; - }; + ensureDBOwnership = true; }]; ensureDatabases = [ "course-management" ]; }; services.nginx.virtualHosts.${hostName} = { - enableACME = true; - forceSSL = true; + # phil redirects + locations = + let + philDomain = "https://kurse-phil.ifsr.de"; + courses = [ "238" "239" "240" "241" "242" "243" ]; + subjects = [ + "ESE 2023 PHIL Campustour" + "ESE 2023 PHIL Bowlingabend" + "ESE 2023 PHIL Filmabend" + "ESE 2023 PHIL Wandern" + "ESE 2023 PHIL Spieleabend Pen and Paper" + ]; + in + { + "~ \"^/course/(${builtins.concatStringsSep "|" courses})/\"".return = "301 ${philDomain}/course/$1"; + "~ \"^/subject/(${builtins.concatStringsSep "|" subjects})/\"".return = "301 ${philDomain}/subject/$1"; + }; }; } diff --git a/modules/courses/phil.nix b/modules/courses/phil.nix new file mode 100644 index 0000000..7bd1b69 --- /dev/null +++ b/modules/courses/phil.nix @@ -0,0 +1,93 @@ +{ config, lib, course-management, ... }: +let + hostName = "kurse-phil.${config.networking.domain}"; +in +{ + services.nginx.virtualHosts."${hostName}" = { + locations."/".proxyPass = "http://127.0.0.1:8084"; + enableACME = true; + forceSSL = true; + }; + + sops.secrets = { + "course-management-phil/secret-key" = { }; + "course-management-phil/adminpass" = { }; + }; + containers."courses-phil" = { + autoStart = true; + extraFlags = [ + "--load-credential=course-secret-key:${config.sops.secrets."course-management-phil/secret-key".path}" + "--load-credential=course-adminpass:${config.sops.secrets."course-management-phil/adminpass".path}" + ]; + config = { config, ... }: { + system.stateVersion = "23.05"; + networking.domain = "ifsr.de"; + imports = [ + course-management.nixosModules.default + ]; + systemd.services.course-management = { + after = [ "postgresql.service" ]; + serviceConfig = { + LoadCredential = [ + "secret-key:course-secret-key" + "adminpass:course-adminpass" + ]; + }; + }; + services.course-management = { + inherit hostName; + enable = true; + listenPort = 5001; + + settings = { + secretKeyFile = "$CREDENTIALS_DIRECTORY/secret-key"; + adminPassFile = "$CREDENTIALS_DIRECTORY/adminpass"; + admins = [{ + name = "Root iFSR"; + email = "root@${config.networking.domain}"; + }]; + database = { + ENGINE = "django.db.backends.postgresql"; + NAME = "course-management"; + }; + email = lib.mkDefault { + fromEmail = "noreply@${config.networking.domain}"; + serverEmail = "root@${config.networking.domain}"; + }; + }; + }; + security.acme = { + acceptTerms = true; + defaults = { + email = "root@${config.networking.domain}"; + }; + }; + services.postgresql = { + enable = true; + enableTCPIP = lib.mkForce false; + ensureUsers = [{ + name = "course-management"; + ensureDBOwnership = true; + }]; + ensureDatabases = [ "course-management" ]; + }; + systemd.services.postgresql.serviceConfig.ExecStart = lib.mkForce "${config.services.postgresql.package}/bin/postgres -c listen_addresses=''"; + services.nginx = { + enable = true; + recommendedProxySettings = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedTlsSettings = true; + + + virtualHosts.${hostName} = { + listen = [{ + addr = "127.0.0.1"; + port = 8084; + }]; + }; + }; + + }; + }; +} diff --git a/modules/decisions.nix b/modules/decisions.nix new file mode 100644 index 0000000..c19085d --- /dev/null +++ b/modules/decisions.nix @@ -0,0 +1,46 @@ +{ config, ... }: +let + domain = "decisions.${config.networking.domain}"; +in +{ + sops.secrets."decisions_env" = { }; + virtualisation.oci-containers = { + containers.decisions = { + image = "ghcr.io/fsr/decisions"; + volumes = [ + "/var/lib/nextcloud/data/root/files/FSR/protokolle:/protokolle:ro" + ]; + extraOptions = [ "--network=host" ]; + environmentFiles = [ + config.sops.secrets."decisions_env".path + ]; + }; + }; + + services.nginx = { + virtualHosts."${domain}" = { + locations."/" = { + proxyPass = "http://127.0.0.1:5055"; + }; + }; + }; + + systemd.timers."decisions-to-db" = { + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = "01:11:00"; + Unit = "decisions-to-db.service"; + }; + }; + + # systemd.services."decisions-to-db" = { + # script = '' + # set -eu + # ${pkgs.podman}/bin/podman exec decisions python tex_to_db.py + # ''; + # serviceConfig = { + # Type = "oneshot"; + # User = "root"; + # }; + # }; +} diff --git a/modules/forgejo/actions.nix b/modules/forgejo/actions.nix new file mode 100644 index 0000000..16d6d24 --- /dev/null +++ b/modules/forgejo/actions.nix @@ -0,0 +1,30 @@ +{ config, pkgs, ... }: +{ + sops.secrets."forgejo/runner-token" = { }; + services.gitea-actions-runner = { + package = pkgs.forgejo-actions-runner; + instances."quitte" = { + enable = true; + labels = [ + # provide a debian base with nodejs for actions + "debian-latest:docker://node:18-bullseye" + # fake the ubuntu name, because node provides no ubuntu builds + "ubuntu-latest:docker://node:18-bullseye" + # provide native execution on the host + # "native:host" + ]; + tokenFile = config.sops.secrets."forgejo/runner-token".path; + url = "https://git.ifsr.de"; + name = "quitte"; + settings = { + container = { + # use podman's default network, otherwise dns was not working for some reason + network = "podman"; + # don't mount the docker socket into the build containers, + # this would basically mean root on the host... + docker_host = "-"; + }; + }; + }; + }; +} diff --git a/modules/gitea.nix b/modules/forgejo/default.nix similarity index 78% rename from modules/gitea.nix rename to modules/forgejo/default.nix index 9924f61..aee832d 100644 --- a/modules/gitea.nix +++ b/modules/forgejo/default.nix @@ -1,40 +1,46 @@ { config, lib, pkgs, ... }: let domain = "git.${config.networking.domain}"; - giteaUser = "git"; + gitUser = "git"; in { + imports = [ + ./actions.nix + ]; sops.secrets.gitea_ldap_search = { key = "portunus/search-password"; - owner = config.services.gitea.user; + owner = config.services.forgejo.user; }; - users.users.${giteaUser} = { + users.users.${gitUser} = { isSystemUser = true; - home = config.services.gitea.stateDir; - group = giteaUser; + home = config.services.forgejo.stateDir; + group = gitUser; useDefaultShell = true; }; - users.groups.${giteaUser} = { }; + users.groups.${gitUser} = { }; - services.gitea = { + services.forgejo = { enable = true; - package = pkgs.forgejo; # community fork - user = giteaUser; - group = giteaUser; - appName = "iFSR Git"; + user = gitUser; + group = gitUser; + package = pkgs.forgejo; lfs.enable = true; database = { type = "postgres"; + name = "git"; # legacy createDatabase = true; - user = giteaUser; + user = gitUser; }; # TODO: enable periodic dumps of the DB and repos, maybe use this for backups? # dump = { }; settings = { + DEFAULT = { + APP_NAME = "iFSR Git"; + }; server = { PROTOCOL = "http+unix"; DOMAIN = domain; @@ -42,6 +48,7 @@ in ROOT_URL = "https://${domain}"; OFFLINE_MODE = true; # disable use of CDNs }; + log.LEVEL = "Warn"; database.LOG_SQL = false; service = { DISABLE_REGISTRATION = true; @@ -63,12 +70,15 @@ in COOKIE_SECURE = true; PROVIDER = "db"; }; + actions.ENABLED = true; + # federation.ENABLED = true; + webhook.ALLOWED_HOST_LIST = "*.ifsr.de"; }; }; - systemd.services.gitea.preStart = + systemd.services.forgejo.preStart = let - exe = lib.getExe config.services.gitea.package; + exe = lib.getExe config.services.forgejo.package; portunus = config.services.portunus; basedn = "ou=users,${portunus.ldap.suffix}"; ldapConfigArgs = '' @@ -105,10 +115,8 @@ in ''; services.nginx.virtualHosts.${domain} = { - enableACME = true; - forceSSL = true; locations."/" = { - proxyPass = "http://unix:${config.services.gitea.settings.server.HTTP_ADDR}:/"; + proxyPass = "http://unix:${config.services.forgejo.settings.server.HTTP_ADDR}:/"; proxyWebsockets = true; }; locations."/api/v1/users/search".return = "403"; diff --git a/modules/ftp.nix b/modules/ftp.nix deleted file mode 100644 index 205ed7c..0000000 --- a/modules/ftp.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ config, pkgs, ... }: -let - domain = "ftp.${config.networking.domain}"; -in -{ - services.nginx.additionalModules = [ pkgs.nginxModules.fancyindex ]; - services.nginx.virtualHosts."${domain}" = { - enableACME = true; - forceSSL = true; - root = "/srv/ftp"; - extraConfig = '' - fancyindex on; - fancyindex_exact_size off; - ''; - locations."~/(klausuren|uebungen|skripte|abschlussarbeiten)".extraConfig = '' - allow 141.30.0.0/16; - allow 141.76.0.0/16; - allow 172.16.0.0/16; - deny all; - ''; - - }; -} diff --git a/modules/hedgedoc.nix b/modules/hedgedoc.nix index bbe2c47..244734a 100644 --- a/modules/hedgedoc.nix +++ b/modules/hedgedoc.nix @@ -14,9 +14,7 @@ in ensureUsers = [ { name = "hedgedoc"; - ensurePermissions = { - "DATABASE hedgedoc" = "ALL PRIVILEGES"; - }; + ensureDBOwnership = true; } ]; ensureDatabases = [ "hedgedoc" ]; @@ -51,6 +49,7 @@ in # allow anonymous editing, but not creation of pads allowAnonymous = false; allowAnonymousEdits = true; + allowAnonymousUploads = false; defaultPermission = "limited"; defaultNotePath = builtins.toString template; # ldap auth @@ -70,12 +69,16 @@ in recommendedProxySettings = true; virtualHosts = { "${domain}" = { - enableACME = true; - forceSSL = true; locations."/" = { proxyPass = "http://[::1]:${toString config.services.hedgedoc.settings.port}"; proxyWebsockets = true; }; + locations."/robots.txt" = { + extraConfig = '' + add_header Content-Type text/plain; + return 200 "User-agent: *\nDisallow: /\n"; + ''; + }; }; }; }; diff --git a/modules/hydra.nix b/modules/hydra.nix index 8a252d5..77c347e 100644 --- a/modules/hydra.nix +++ b/modules/hydra.nix @@ -4,6 +4,7 @@ let in { sops.secrets."hydra_ldap_search" = { owner = "hydra"; group = "hydra"; mode = "440"; }; + nix.settings.allowed-uris = [ "https://github.com/nix-community" ]; # whitelisted to fetch nix-index services.hydra = { enable = true; port = 4000; @@ -59,8 +60,6 @@ in }; services.nginx.virtualHosts."${domain}" = { - enableACME = true; - forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:${toString config.services.hydra.port}"; }; diff --git a/modules/kanboard.nix b/modules/kanboard.nix new file mode 100644 index 0000000..2416ed8 --- /dev/null +++ b/modules/kanboard.nix @@ -0,0 +1,34 @@ +{ config, ... }: +let + domain = "kanboard.${config.networking.domain}"; + domain_short = "kb.${config.networking.domain}"; +in +{ + sops.secrets."kanboard_env" = { }; + + virtualisation.oci-containers = { + containers.kanboard = { + image = "ghcr.io/kanboard/kanboard:v1.2.43"; + volumes = [ + "kanboard_data:/var/www/app/data" + "kanboard_plugins:/var/www/app/plugins" + ]; + ports = [ "127.0.0.1:8045:80" ]; + environmentFiles = [ + config.sops.secrets."kanboard_env".path + ]; + }; + }; + + services.nginx = { + virtualHosts."${domain_short}" = { + locations."/".return = "301 $scheme://${domain}$request_uri"; + }; + + virtualHosts."${domain}" = { + locations."/" = { + proxyPass = "http://127.0.0.1:8045"; + }; + }; + }; +} diff --git a/modules/keycloak/default.nix b/modules/keycloak/default.nix new file mode 100644 index 0000000..6aa1afb --- /dev/null +++ b/modules/keycloak/default.nix @@ -0,0 +1,39 @@ +{ config, pkgs, ... }: +let + domain = "sso.${config.networking.domain}"; +in +{ + sops.secrets."keycloak/db" = { }; + services.keycloak = { + enable = true; + # we use unstable as the release in stable is insecure + # package = nixpkgs-unstable.legacyPackages.x86_64-linux.keycloak; + settings = { + http-port = 8086; + https-port = 19000; + hostname = domain; + proxy-headers = "xforwarded"; + http-enabled = true; + hostname-strict-https = false; + }; + # The module requires a password for the DB and works best with its own DB config + # Does an automatic Postgresql configuration + database = { + passwordFile = config.sops.secrets."keycloak/db".path; + }; + initialAdminPassword = "plschangeme"; + themes = with pkgs ; { + ifsr = keycloak_ifsr_theme; + }; + }; + services.nginx.virtualHosts."${domain}" = { + locations."/" = { + proxyPass = "http://127.0.0.1:${toString config.services.keycloak.settings.http-port}"; + extraConfig = '' + proxy_buffer_size 128k; + proxy_buffers 4 256k; + proxy_busy_buffers_size 256k; + ''; + }; + }; +} diff --git a/modules/keycloak/theme.nix b/modules/keycloak/theme.nix new file mode 100644 index 0000000..0500e47 --- /dev/null +++ b/modules/keycloak/theme.nix @@ -0,0 +1,15 @@ +{ stdenv }: +stdenv.mkDerivation rec { + name = "keycloak_ifsr_theme"; + version = "1.1"; + + src = ./theme; + + nativeBuildInputs = [ ]; + buildInputs = [ ]; + + installPhase = '' + mkdir -p $out + cp -a login $out + ''; +} diff --git a/modules/keycloak/theme/login/resources/css/login.css b/modules/keycloak/theme/login/resources/css/login.css new file mode 100644 index 0000000..6314ff8 --- /dev/null +++ b/modules/keycloak/theme/login/resources/css/login.css @@ -0,0 +1,772 @@ +.login-pf { + background: none; +} + +.login-pf body { + background: url(../img/background.jpg) no-repeat center center fixed; + background-size: cover; + height: 100%; +} + +/*IE compatibility*/ +.pf-c-form-control { + font-size: 14px; + font-size: var(--pf-global--FontSize--sm); + border-width: 1px; + border-width: var(--pf-global--BorderWidth--sm);; + border-color: #EDEDED #EDEDED #8A8D90 #EDEDED; + border-color: var(--pf-global--BorderColor--300) var(--pf-global--BorderColor--300) var(--pf-global--BorderColor--200) var(--pf-global--BorderColor--300); + background-color: #FFFFFF; + background-color: var(--pf-global--BackgroundColor--100); + height: 36px; + height: calc(var(--pf-c-form-control--FontSize) * var(--pf-c-form-control--LineHeight) + var(--pf-c-form-control--BorderWidth) * 2 + var(--pf-c-form-control--PaddingTop) + var(--pf-c-form-control--PaddingBottom)); + padding: 5px 0.5rem; + padding: var(--pf-c-form-control--PaddingTop) var(--pf-c-form-control--PaddingRight) var(--pf-c-form-control--PaddingBottom) var(--pf-c-form-control--PaddingLeft); +} + +textarea.pf-c-form-control { + height: auto; +} + +.pf-c-form-control:hover, .pf-c-form-control:focus { + border-bottom-color: #0066CC; + border-bottom-color: var(--pf-global--primary-color--100); + border-bottom-width: 2px; + border-bottom-width: var(--pf-global--BorderWidth--md); +} + +.pf-c-form-control[aria-invalid=true] { + border-bottom-color: #C9190B; + border-bottom-color: var(--pf-global--danger-color--100); + border-bottom-width: 2px; + border-bottom-width: var(--pf-global--BorderWidth--md); +} + +.pf-c-check__label, .pf-c-radio__label { + font-size: 14px; + font-size: var(--pf-global--FontSize--sm); +} + +.pf-c-alert.pf-m-inline { + margin-bottom: 0.5rem; /* default - IE compatibility */ + margin-bottom: var(--pf-global--spacer--sm); + padding: 0.25rem; + padding: var(--pf-global--spacer--xs); + border: solid #ededed; + border: solid var(--pf-global--BorderColor--300); + border-width: 1px; + border-width: var(--pf-c-alert--m-inline--BorderTopWidth) var(--pf-c-alert--m-inline--BorderRightWidth) var(--pf-c-alert--m-inline--BorderBottomWidth) var(--pf-c-alert--m-inline--BorderLeftWidth); + display: -ms-flexbox; + display: grid; + -ms-grid-columns: max-content 1fr max-content; + grid-template-columns:max-content 1fr max-content; + grid-template-columns: var(--pf-c-alert--grid-template-columns); + grid-template-rows: 1fr auto; + grid-template-rows: var(--pf-c-alert--grid-template-rows); +} + +.pf-c-alert.pf-m-inline::before { + position: absolute; + top: -1px; + top: var(--pf-c-alert--m-inline--before--Top); + bottom: -1px; + bottom: var(--pf-c-alert--m-inline--before--Bottom); + left: 0; + width: 3px; + width: var(--pf-c-alert--m-inline--before--Width); + content: ; + background-color: #FFFFFF; + background-color: var(--pf-global--BackgroundColor--100); +} + +.pf-c-alert.pf-m-inline.pf-m-success::before { + background-color: #92D400; + background-color: var(--pf-global--success-color--100); +} + +.pf-c-alert.pf-m-inline.pf-m-danger::before { + background-color: #C9190B; + background-color: var(--pf-global--danger-color--100); +} + +.pf-c-alert.pf-m-inline.pf-m-warning::before { + background-color: #F0AB00; + background-color: var(--pf-global--warning-color--100); +} + +.pf-c-alert.pf-m-inline .pf-c-alert__icon { + padding: 1rem 0.5rem 1rem 1rem; + padding: var(--pf-c-alert--m-inline__icon--PaddingTop) var(--pf-c-alert--m-inline__icon--PaddingRight) var(--pf-c-alert--m-inline__icon--PaddingBottom) var(--pf-c-alert--m-inline__icon--PaddingLeft); + font-size: 16px; + font-size: var(--pf-c-alert--m-inline__icon--FontSize); +} + +.pf-c-alert.pf-m-success .pf-c-alert__icon { + color: #92D400; + color: var(--pf-global--success-color--100); +} + +.pf-c-alert.pf-m-success .pf-c-alert__title { + color: #486B00; + color: var(--pf-global--success-color--200); +} + +.pf-c-alert.pf-m-danger .pf-c-alert__icon { + color: #C9190B; + color: var(--pf-global--danger-color--100); +} + +.pf-c-alert.pf-m-danger .pf-c-alert__title { + color: #A30000; + color: var(--pf-global--danger-color--200); +} + +.pf-c-alert.pf-m-warning .pf-c-alert__icon { + color: #F0AB00; + color: var(--pf-global--warning-color--100); +} + +.pf-c-alert.pf-m-warning .pf-c-alert__title { + color: #795600; + color: var(--pf-global--warning-color--200); +} + +.pf-c-alert__title { + font-size: 14px; /* default - IE compatibility */ + font-size: var(--pf-global--FontSize--sm); + padding: 5px 8px; + padding: var(--pf-c-alert__title--PaddingTop) var(--pf-c-alert__title--PaddingRight) var(--pf-c-alert__title--PaddingBottom) var(--pf-c-alert__title--PaddingLeft); +} + +.pf-c-button{ + padding:0.375rem 1rem; + padding: var(--pf-global--spacer--form-element) var(--pf-global--spacer--md); +} + +/* default - IE compatibility */ +.pf-m-primary { + color: #FFFFFF; + background-color: #0066CC; + background-color: var(--pf-global--primary-color--100); +} + +/* default - IE compatibility */ +.pf-m-primary:hover { + background-color: #004080; + background-color: var(--pf-global--primary-color--200); +} + +/* default - IE compatibility */ +.pf-c-button.pf-m-control { + border: solid 1px; + border: solid var(--pf-global--BorderWidth--sm); + border-color: rgba(230, 230, 230, 0.5); +} +/*End of IE compatibility*/ +h1#kc-page-title { + margin-top: 10px; +} + +#kc-locale ul { + background-color: #FFF; + background-color: var(--pf-global--BackgroundColor--100); + display: none; + top: 20px; + min-width: 100px; + padding: 0; +} + +#kc-locale-dropdown{ + display: inline-block; +} + +#kc-locale-dropdown:hover ul { + display:block; +} + +/* IE compatibility */ +#kc-locale-dropdown a { + color: #6A6E73; + color: var(--pf-global--Color--200); + text-align: right; + font-size: 14px; + font-size: var(--pf-global--FontSize--sm); +} + +/* IE compatibility */ +a#kc-current-locale-link::after { + content: 2c5; + margin-left: 4px; + margin-left: var(--pf-global--spacer--xs) +} + +.login-pf .container { + padding-top: 40px; +} + +.login-pf a:hover { + color: #0099d3; +} + +#kc-logo { + width: 100%; +} + +div.kc-logo-text { + background-image: url(../img/agdsn_logo.png); + background-repeat: no-repeat; + background-size: auto; + position: relative; + top: 0%; + left: 25%; + width: 950px; + height: 250px; + + +} + +div.kc-logo-text span { + display: none; +} + +#kc-header { + color: #ededed; + overflow: visible; + white-space: nowrap; +} + +#kc-header-wrapper { + font-size: 29px; + text-transform: uppercase; + letter-spacing: 3px; + line-height: 1.2em; + padding: 62px 10px 20px; + white-space: normal; +} + +#kc-content { + width: 100%; +} + +#kc-attempted-username { + font-size: 20px; + font-family: inherit; + font-weight: normal; + padding-right: 10px; +} + +#kc-username { + text-align: center; + margin-bottom:-10px; +} + +#kc-webauthn-settings-form { + padding-top: 8px; +} + +#kc-form-webauthn .select-auth-box-parent { + pointer-events: none; +} + +#kc-form-webauthn .select-auth-box-desc { + color: var(--pf-global--palette--black-600); +} + +#kc-form-webauthn .select-auth-box-headline { + color: var(--pf-global--Color--300); +} + +#kc-form-webauthn .select-auth-box-icon { + flex: 0 0 3em; +} + +#kc-form-webauthn .select-auth-box-icon-properties { + margin-top: 10px; + font-size: 1.8em; +} + +#kc-form-webauthn .select-auth-box-icon-properties.unknown-transport-class { + margin-top: 3px; +} + +#kc-form-webauthn .pf-l-stack__item { + margin: -1px 0; +} + +#kc-content-wrapper { + margin-top: 20px; +} + +#kc-form-wrapper { + margin-top: 10px; +} + +#kc-info { + margin: 20px -40px -30px; +} + +#kc-info-wrapper { + font-size: 13px; + padding: 15px 35px; + background-color: #F0F0F0; +} + +#kc-form-options span { + display: block; +} + +#kc-form-options .checkbox { + margin-top: 0; + color: #72767b; +} + +#kc-terms-text { + margin-bottom: 20px; +} + +#kc-registration { + margin-bottom: 0; +} + +/* TOTP */ + +.subtitle { + text-align: right; + margin-top: 30px; + color: #909090; +} + +.required { + color: #A30000; /* default - IE compatibility */ + color: var(--pf-global--danger-color--200); +} + +ol#kc-totp-settings { + margin: 0; + padding-left: 20px; +} + +ul#kc-totp-supported-apps { + margin-bottom: 10px; +} + +#kc-totp-secret-qr-code { + max-width:150px; + max-height:150px; +} + +#kc-totp-secret-key { + background-color: #fff; + color: #333333; + font-size: 16px; + padding: 10px 0; +} + +/* OAuth */ + +#kc-oauth h3 { + margin-top: 0; +} + +#kc-oauth ul { + list-style: none; + padding: 0; + margin: 0; +} + +#kc-oauth ul li { + border-top: 1px solid rgba(255, 255, 255, 0.1); + font-size: 12px; + padding: 10px 0; +} + +#kc-oauth ul li:first-of-type { + border-top: 0; +} + +#kc-oauth .kc-role { + display: inline-block; + width: 50%; +} + +/* Code */ +#kc-code textarea { + width: 100%; + height: 8em; +} + +/* Social */ +.kc-social-links { + margin-top: 20px; +} + +.kc-social-provider-logo { + font-size: 23px; + width: 30px; + height: 25px; + float: left; +} + +.kc-social-gray { + color: #737679; /* default - IE compatibility */ + color: var(--pf-global--Color--200); +} + +.kc-social-item { + margin-bottom: 0.5rem; /* default - IE compatibility */ + margin-bottom: var(--pf-global--spacer--sm); + font-size: 15px; + text-align: center; +} + +.kc-social-provider-name { + position: relative; + top: 3px; +} + +.kc-social-icon-text { + left: -15px; +} + +.kc-social-grid { + display:grid; + grid-column-gap: 10px; + grid-row-gap: 5px; + grid-column-end: span 6; + --pf-l-grid__item--GridColumnEnd: span 6; +} + +.kc-social-grid .kc-social-icon-text { + left: -10px; +} + +.kc-login-tooltip { + position: relative; + display: inline-block; +} + +.kc-social-section { + text-align: center; +} + +.kc-social-section hr{ + margin-bottom: 10px +} + +.kc-login-tooltip .kc-tooltip-text{ + top:-3px; + left:160%; + background-color: black; + visibility: hidden; + color: #fff; + + min-width:130px; + text-align: center; + border-radius: 2px; + box-shadow:0 1px 8px rgba(0,0,0,0.6); + padding: 5px; + + position: absolute; + opacity:0; + transition:opacity 0.5s; +} + +/* Show tooltip */ +.kc-login-tooltip:hover .kc-tooltip-text { + visibility: visible; + opacity:0.7; +} + +/* Arrow for tooltip */ +.kc-login-tooltip .kc-tooltip-text::after { + content: ; + position: absolute; + top: 15px; + right: 100%; + margin-top: -5px; + border-width: 5px; + border-style: solid; + border-color: transparent black transparent transparent; +} + +@media (min-width: 768px) { + #kc-container-wrapper { + position: absolute; + width: 100%; + } + + .login-pf .container { + padding-right: 80px; + } + + #kc-locale { + position: relative; + text-align: right; + z-index: 9999; + } +} + +@media (max-width: 767px) { + + .login-pf body { + background: white; + } + + #kc-header { + padding-left: 15px; + padding-right: 15px; + float: none; + text-align: left; + } + + #kc-header-wrapper { + font-size: 16px; + font-weight: bold; + padding: 20px 60px 0 0; + color: #72767b; + letter-spacing: 0; + } + + div.kc-logo-text { + margin: 0; + width: 150px; + height: 32px; + background-size: 100%; + } + + #kc-form { + float: none; + } + + #kc-info-wrapper { + border-top: 1px solid rgba(255, 255, 255, 0.1); + background-color: transparent; + } + + .login-pf .container { + padding-top: 15px; + padding-bottom: 15px; + } + + #kc-locale { + position: absolute; + width: 200px; + top: 20px; + right: 20px; + text-align: right; + z-index: 9999; + } +} + +@media (min-height: 646px) { + #kc-container-wrapper { + bottom: 12%; + } +} + +@media (max-height: 645px) { + #kc-container-wrapper { + padding-top: 50px; + top: 20%; + } +} + +.card-pf form.form-actions .btn { + float: right; + margin-left: 10px; +} + +#kc-form-buttons { + margin-top: 20px; +} + +.login-pf-page .login-pf-brand { + margin-top: 20px; + max-width: 360px; + width: 40%; +} + +/* Internet Explorer 11 compatibility workaround for select-authenticator screen */ +@media all and (-ms-high-contrast: none), +(-ms-high-contrast: active) { + .select-auth-box-parent { + border-top: 1px solid #f0f0f0; + padding-top: 1rem; + padding-bottom: 1rem; + cursor: pointer; + } + + .select-auth-box-headline { + font-size: 16px; + color: #06c; + font-weight: bold; + } + + .select-auth-box-desc { + font-size: 14px; + } + + .pf-l-stack { + flex-basis: 100%; + } +} +/* End of IE11 workaround for select-authenticator screen */ + +.select-auth-box-arrow{ + display: flex; + align-items: center; + margin-right: 2rem; +} + +.select-auth-box-icon{ + display: flex; + flex: 0 0 2em; + justify-content: center; + margin-right: 1rem; + margin-left: 3rem; +} + +.select-auth-box-parent{ + border-top: 1px solid var(--pf-global--palette--black-200); + padding-top: 1rem; + padding-bottom: 1rem; + cursor: pointer; +} + +.select-auth-box-parent:hover{ + background-color: #f7f8f8; +} + +.select-auth-container { +} + +.select-auth-box-headline { + font-size: var(--pf-global--FontSize--md); + color: var(--pf-global--primary-color--100); + font-weight: bold; +} + +.select-auth-box-desc { + font-size: var(--pf-global--FontSize--sm); +} + +.select-auth-box-paragraph { + text-align: center; + font-size: var(--pf-global--FontSize--md); + margin-bottom: 5px; +} + +.card-pf { + margin: 0 auto; + box-shadow: var(--pf-global--BoxShadow--lg); + padding: 0 20px; + max-width: 500px; + border-top: 4px solid; + border-color: #0066CC; /* default - IE compatibility */ + border-color: var(--pf-global--primary-color--100); +} + +/*phone*/ +@media (max-width: 767px) { + .login-pf-page .card-pf { + max-width: none; + margin-left: 0; + margin-right: 0; + padding-top: 0; + border-top: 0; + box-shadow: 0 0; + } + + .kc-social-grid { + grid-column-end: 12; + --pf-l-grid__item--GridColumnEnd: span 12; + } + + .kc-social-grid .kc-social-icon-text { + left: -15px; + } +} + +.login-pf-page .login-pf-signup { + font-size: 15px; + color: #72767b; +} +#kc-content-wrapper .row { + margin-left: 0; + margin-right: 0; +} + +.login-pf-page.login-pf-page-accounts { + margin-left: auto; + margin-right: auto; +} + +.login-pf-page .btn-primary { + margin-top: 0; +} + +.login-pf-page .list-view-pf .list-group-item { + border-bottom: 1px solid #ededed; +} + +.login-pf-page .list-view-pf-description { + width: 100%; +} + +#kc-form-login div.form-group:last-of-type, +#kc-register-form div.form-group:last-of-type, +#kc-update-profile-form div.form-group:last-of-type { + margin-bottom: 0px; +} + +.no-bottom-margin { + margin-bottom: 0; +} + +#kc-back { + margin-top: 5px; +} + +/* Recovery codes */ +.kc-recovery-codes-warning { + margin-bottom: 32px; +} +.kc-recovery-codes-warning .pf-c-alert__description p { + font-size: 0.875rem; +} +.kc-recovery-codes-list { + list-style: none; + columns: 2; + margin: 16px 0; + padding: 16px 16px 8px 16px; + border: 1px solid #D2D2D2; +} +.kc-recovery-codes-list li { + margin-bottom: 8px; + font-size: 11px; +} +.kc-recovery-codes-list li span { + color: #6A6E73; + width: 16px; + text-align: right; + display: inline-block; + margin-right: 1px; +} + +.kc-recovery-codes-actions { + margin-bottom: 24px; +} +.kc-recovery-codes-actions button { + padding-left: 0; +} +.kc-recovery-codes-actions button i { + margin-right: 8px; +} + +.kc-recovery-codes-confirmation { + align-items: baseline; + margin-bottom: 16px; +} +/* End Recovery codes */ + + diff --git a/modules/keycloak/theme/login/resources/img/background.jpg b/modules/keycloak/theme/login/resources/img/background.jpg new file mode 100644 index 0000000..0a1a60d Binary files /dev/null and b/modules/keycloak/theme/login/resources/img/background.jpg differ diff --git a/modules/keycloak/theme/login/theme.properties b/modules/keycloak/theme/login/theme.properties new file mode 100644 index 0000000..c0d3ad2 --- /dev/null +++ b/modules/keycloak/theme/login/theme.properties @@ -0,0 +1,4 @@ +parent=keycloak +import=common/keycloak + +styles=css/login.css diff --git a/modules/ldap/0001-update-user-validation-regex.patch b/modules/ldap/0001-update-user-validation-regex.patch index 6ae40f9..ce78894 100644 --- a/modules/ldap/0001-update-user-validation-regex.patch +++ b/modules/ldap/0001-update-user-validation-regex.patch @@ -1,25 +1,35 @@ -From f5c68898be345fb0dca5ab7b596b9cbe674f5dfb Mon Sep 17 00:00:00 2001 -From: Rouven Seifert -Date: Tue, 4 Jul 2023 15:14:00 +0200 -Subject: [PATCH] update user validation regex - ---- - internal/core/validation.go | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/internal/core/validation.go b/internal/core/validation.go -index 3e168b5..10dfc0a 100644 ---- a/internal/core/validation.go -+++ b/internal/core/validation.go -@@ -30,7 +30,7 @@ import ( - ) - - //this regexp copied from useradd(8) manpage --const posixAccountNamePattern = `[a-z_][a-z0-9_-]*\$?` -+const posixAccountNamePattern = `[a-z_][a-z0-9._-]*\$?` +diff --git a/cmd/portunus-orchestrator/config.go b/cmd/portunus-orchestrator/config.go +index 4db19f2..290128a 100644 +--- a/cmd/portunus-orchestrator/config.go ++++ b/cmd/portunus-orchestrator/config.go +@@ -23,7 +23,7 @@ type valueCheck struct { + } var ( - errIsMissing = errors.New("is missing") --- -2.41.0 - +- userOrGroupPattern = `^[a-z_][a-z0-9_-]*\$?$` ++ userOrGroupPattern = `^[a-z_][a-z0-9._-]*\$?$` + envDefaults = map[string]string{ + //empty value = not optional + "PORTUNUS_DEBUG": "false", +diff --git a/internal/grammars/grammars.go b/internal/grammars/grammars.go +index 1253c05..e458fd0 100644 +--- a/internal/grammars/grammars.go ++++ b/internal/grammars/grammars.go +@@ -39,7 +39,7 @@ const ( + // This regex is based on the respective format description in the useradd(8) manpage. + // + // This is only shown for documentation purposes here; use func IsPOSIXAccountName instead. +- POSIXAccountNameRegex = `^[a-z_][a-z0-9_-]*\$?$` ++ POSIXAccountNameRegex = `^[a-z_][a-z0-9._-]*\$?$` + ) + + //TODO There is also some `import "regexp"` in cmd/orchestrator/ldap.go to render +@@ -159,7 +159,7 @@ func checkByteInPOSIXAccountName(idx, length int, b byte) bool { + switch { + case (b >= 'a' && b <= 'z') || b == '_': + return true +- case (b >= '0' && b <= '9') || b == '-': ++ case (b >= '0' && b <= '9') || b == '-' || b == '.': + return idx != 0 // not allowed at start + default: + return false diff --git a/modules/ldap/0002-both-ldap-and-ldaps.patch b/modules/ldap/0002-both-ldap-and-ldaps.patch index 9ae71a5..3ebda7e 100644 --- a/modules/ldap/0002-both-ldap-and-ldaps.patch +++ b/modules/ldap/0002-both-ldap-and-ldaps.patch @@ -1,8 +1,8 @@ -diff --git a/cmd/orchestrator/ldap.go b/cmd/orchestrator/ldap.go -index ed0d466..a672046 100644 ---- a/cmd/orchestrator/ldap.go -+++ b/cmd/orchestrator/ldap.go -@@ -130,7 +130,7 @@ func runLDAPServer(environment map[string]string) { +diff --git a/cmd/portunus-orchestrator/ldap.go b/cmd/portunus-orchestrator/ldap.go +index 9564c5e..40cd2d7 100644 +--- a/cmd/portunus-orchestrator/ldap.go ++++ b/cmd/portunus-orchestrator/ldap.go +@@ -134,7 +134,7 @@ func runLDAPServer(environment map[string]string) { bindURL := "ldap:///" if environment["PORTUNUS_SLAPD_TLS_CERTIFICATE"] != "" { diff --git a/modules/ldap/0003-gecos-ascii-escape.patch b/modules/ldap/0003-gecos-ascii-escape.patch index c3918cb..83650f4 100644 --- a/modules/ldap/0003-gecos-ascii-escape.patch +++ b/modules/ldap/0003-gecos-ascii-escape.patch @@ -1,24 +1,26 @@ -diff --git a/internal/core/user.go b/internal/core/user.go -index e74ccfe..291c75b 100644 ---- a/internal/core/user.go -+++ b/internal/core/user.go -@@ -8,6 +8,7 @@ package core +diff --git a/internal/ldap/object.go b/internal/ldap/object.go +index d4e5c6f..fcefec7 100644 +--- a/internal/ldap/object.go ++++ b/internal/ldap/object.go +@@ -8,6 +8,7 @@ package ldap import ( "fmt" -+ "strconv" - ) ++ "regexp" - // User represents a single user account. -@@ -86,9 +87,9 @@ func (u User) RenderToLDAP(suffix string, allGroups map[string]Group) LDAPObject + "github.com/majewsky/portunus/internal/core" + ) +@@ -94,10 +95,11 @@ func renderUser(u core.User, dnSuffix string, allGroups []core.Group) Object { + if u.POSIX.LoginShell != "" { obj.Attributes["loginShell"] = []string{u.POSIX.LoginShell} } ++ var nonASCII = regexp.MustCompile("[^\\x00-\\x7F]") if u.POSIX.GECOS == "" { - obj.Attributes["gecos"] = []string{u.FullName()} -+ obj.Attributes["gecos"] = []string{strconv.QuoteToASCII(u.FullName())} ++ obj.Attributes["gecos"] = []string{nonASCII.ReplaceAllString(u.FullName(), "")} } else { - obj.Attributes["gecos"] = []string{u.POSIX.GECOS} -+ obj.Attributes["gecos"] = []string{strconv.QuoteToASCII(u.POSIX.GECOS)} ++ obj.Attributes["gecos"] = []string{nonASCII.ReplaceAllString(u.POSIX.GECOS, "")} } obj.Attributes["objectClass"] = append(obj.Attributes["objectClass"], "posixAccount") } diff --git a/modules/ldap/0004-make-givenName-optional.patch b/modules/ldap/0004-make-givenName-optional.patch index 4131252..4b6ecf6 100644 --- a/modules/ldap/0004-make-givenName-optional.patch +++ b/modules/ldap/0004-make-givenName-optional.patch @@ -1,8 +1,20 @@ diff --git a/internal/core/user.go b/internal/core/user.go -index e74ccfe..ce03eeb 100644 +index f45fdf7..4f93b37 100644 --- a/internal/core/user.go +++ b/internal/core/user.go -@@ -64,7 +64,6 @@ func (u User) RenderToLDAP(suffix string, allGroups map[string]Group) LDAPObject +@@ -76,7 +76,6 @@ func (u User) validateLocal(cfg *ValidationConfig) (errs errext.ErrorSet) { + MustBePosixAccountNameIf(u.LoginName, u.POSIX != nil), + )) + errs.Add(ref.Field("given_name").WrapFirst( +- MustNotBeEmpty(u.GivenName), + MustNotHaveSurroundingSpaces(u.GivenName), + )) + errs.Add(ref.Field("family_name").WrapFirst( +diff --git a/internal/ldap/object.go b/internal/ldap/object.go +index d4e5c6f..1225084 100644 +--- a/internal/ldap/object.go ++++ b/internal/ldap/object.go +@@ -73,7 +73,6 @@ func renderUser(u core.User, dnSuffix string, allGroups []core.Group) Object { "uid": {u.LoginName}, "cn": {u.FullName()}, "sn": {u.FamilyName}, @@ -10,7 +22,7 @@ index e74ccfe..ce03eeb 100644 "userPassword": {u.PasswordHash}, "isMemberOf": memberOfGroupDNames, "objectClass": {"portunusPerson", "inetOrgPerson", "organizationalPerson", "person", "top"}, -@@ -74,6 +73,9 @@ func (u User) RenderToLDAP(suffix string, allGroups map[string]Group) LDAPObject +@@ -83,6 +82,9 @@ func renderUser(u core.User, dnSuffix string, allGroups []core.Group) Object { if u.EMailAddress != "" { obj.Attributes["mail"] = []string{u.EMailAddress} } @@ -20,15 +32,3 @@ index e74ccfe..ce03eeb 100644 if len(u.SSHPublicKeys) > 0 { obj.Attributes["sshPublicKey"] = u.SSHPublicKeys } -diff --git a/internal/frontend/users.go b/internal/frontend/users.go -index 225c5b3..1a961ca 100644 ---- a/internal/frontend/users.go -+++ b/internal/frontend/users.go -@@ -168,7 +168,6 @@ func buildUserMasterdataFieldset(e core.Engine, u *core.User, state *h.FormState - Name: "given_name", - Label: "Given name", - Rules: []h.ValidationRule{ -- core.MustNotBeEmpty, - core.MustNotHaveSurroundingSpaces, - }, - }, diff --git a/modules/ldap/default.nix b/modules/ldap/default.nix index 98274df..bdf3d3b 100644 --- a/modules/ldap/default.nix +++ b/modules/ldap/default.nix @@ -1,7 +1,7 @@ -{ config, lib, pkgs, ... }: +{ config, pkgs, ... }: let domain = "auth.${config.networking.domain}"; - seed = { + seedSettings = { groups = [ { name = "admins"; @@ -46,11 +46,6 @@ in sops.secrets = { "portunus/admin-password".owner = config.services.portunus.user; "portunus/search-password".owner = config.services.portunus.user; - "dex/environment".owner = config.systemd.services.dex.serviceConfig.User; - nslcd_ldap_search = { - key = "portunus/search-password"; - owner = config.systemd.services.nslcd.serviceConfig.User; - }; }; services.portunus = { @@ -62,13 +57,11 @@ in ./0003-gecos-ascii-escape.patch ./0004-make-givenName-optional.patch ]; + doCheck = false; # posix regex related tests break }); - inherit domain; + inherit domain seedSettings; port = 8681; - dex.enable = true; - seedPath = pkgs.writeText "portunus-seed.json" (builtins.toJSON seed); - ldap = { suffix = "dc=ifsr,dc=de"; searchUserName = "search"; @@ -79,46 +72,13 @@ in }; }; - services.dex.settings.oauth2.skipApprovalScreen = true; - - systemd.services.dex.serviceConfig = { - DynamicUser = lib.mkForce false; - EnvironmentFile = config.sops.secrets."dex/environment".path; - StateDirectory = "dex"; - User = "dex"; - }; - - users = { - users.dex = { - group = "dex"; - isSystemUser = true; - }; - groups.dex = { }; - - ldap = - let portunus = config.services.portunus; in - rec { - enable = true; - server = "ldap://localhost"; - base = "${portunus.ldap.suffix}"; - bind = { - distinguishedName = "uid=${portunus.ldap.searchUserName},ou=users,${base}"; - passwordFile = config.sops.secrets.nslcd_ldap_search.path; - }; - daemon.enable = true; - }; - }; - security.pam.services.sshd.makeHomeDir = true; services.nginx = { enable = true; virtualHosts."${config.services.portunus.domain}" = { - forceSSL = true; - enableACME = true; locations = { "/".proxyPass = "http://localhost:${toString config.services.portunus.port}"; - "/dex".proxyPass = "http://localhost:${toString config.services.portunus.dex.port}"; }; }; }; diff --git a/modules/mail/default.nix b/modules/mail/default.nix index 2be0e73..e6af452 100644 --- a/modules/mail/default.nix +++ b/modules/mail/default.nix @@ -1,298 +1,17 @@ -{ config, pkgs, ... }: +{ config, ... }: let hostname = "mail.${config.networking.domain}"; - domain = config.networking.domain; - rspamd-domain = "rspamd.${config.networking.domain}"; - dovecot-ldap-args = pkgs.writeText "ldap-args" '' - uris = ldap://localhost - dn = uid=search, ou=users, dc=ifsr, dc=de - auth_bind = yes - !include ${config.sops.secrets."dovecot_ldap_search".path} - - ldap_version = 3 - scope = subtree - base = dc=ifsr, dc=de - user_filter = (&(objectClass=posixAccount)(uid=%n)) - pass_filter = (&(objectClass=posixAccount)(uid=%n)) - ''; - # see https://www.kuketz-blog.de/e-mail-anbieter-ip-stripping-aus-datenschutzgruenden/ - header_cleanup = pkgs.writeText "header_cleanup_outgoing" '' - /^\s*(Received: from)[^\n]*(.*)/ REPLACE $1 127.0.0.1 (localhost [127.0.0.1])$2 - /^\s*User-Agent/ IGNORE - /^\s*X-Enigmail/ IGNORE - /^\s*X-Mailer/ IGNORE - /^\s*X-Originating-IP/ IGNORE - /^\s*Mime-Version/ IGNORE - ''; in { - sops.secrets."rspamd-password".owner = config.users.users.rspamd.name; - sops.secrets."dovecot_ldap_search".owner = config.services.dovecot2.user; - sops.secrets."postfix_ldap_aliases".owner = config.services.postfix.user; - - networking.firewall.allowedTCPPorts = [ - 25 # insecure SMTP - 143 - 465 - 587 # SMTP - 993 # IMAP - 4190 # sieve + imports = [ + ./postfix.nix + ./dovecot2.nix + ./rspamd.nix + ./sogo.nix + ./mailman.nix ]; - users.users.postfix.extraGroups = [ "opendkim" ]; - environment.etc = { - "dovecot/sieve-pipe/sa-learn-spam.sh" = { - text = '' - #!/bin/sh - ${pkgs.rspamd}/bin/rspamc learn_spam - ''; - mode = "0555"; - }; - "dovecot/sieve-pipe/sa-learn-ham.sh" = { - text = '' - #!/bin/sh - ${pkgs.rspamd}/bin/rspamc learn_ham - ''; - mode = "0555"; - }; - "dovecot/sieve/report-spam.sieve" = { - source = ./report-spam.sieve; - user = "dovecot2"; - group = "dovecot2"; - mode = "0544"; - }; - "dovecot/sieve/report-ham.sieve" = { - source = ./report-ham.sieve; - user = "dovecot2"; - group = "dovecot2"; - mode = "0544"; - }; - }; - services = { - postfix = { - enable = true; - enableSubmission = true; - enableSubmissions = true; - hostname = "${hostname}"; - domain = "${domain}"; - origin = "${domain}"; - destination = [ "${hostname}" "${domain}" "localhost" ]; - networksStyle = "host"; # localhost and own public IP - sslCert = "/var/lib/acme/${hostname}/fullchain.pem"; - sslKey = "/var/lib/acme/${hostname}/key.pem"; - relayDomains = [ "hash:/var/lib/mailman/data/postfix_domains" ]; - config = { - home_mailbox = "Maildir/"; - # hostname used in helo command. It is recommended to have this match the reverse dns entry - smtp_helo_name = config.networking.rDNS; - smtp_use_tls = true; - # smtp_tls_security_level = "encrypt"; - smtpd_use_tls = true; - # smtpd_tls_security_level = lib.mkForce "encrypt"; - # smtpd_tls_auth_only = true; - smtpd_tls_protocols = [ - "!SSLv2" - "!SSLv3" - "!TLSv1" - "!TLSv1.1" - ]; - # "reject_non_fqdn_hostname" - smtpd_recipient_restrictions = [ - "permit_sasl_authenticated" - "permit_mynetworks" - "reject_unauth_destination" - "reject_non_fqdn_sender" - "reject_non_fqdn_recipient" - "reject_unknown_sender_domain" - "reject_unknown_recipient_domain" - "reject_unauth_destination" - "reject_unauth_pipelining" - "reject_invalid_hostname" - "check_policy_service inet:localhost:12340" - ]; - smtpd_relay_restrictions = [ - "permit_sasl_authenticated" - "permit_mynetworks" - "reject_unauth_destination" - ]; - smtp_header_checks = "pcre:${header_cleanup}"; - # smtpd_sender_login_maps = [ "ldap:${ldap-senders}" ]; - alias_maps = [ "hash:/etc/aliases" ]; - alias_database = [ "hash:/etc/aliases" ]; - # alias_maps = [ "hash:/etc/aliases" "ldap:${ldap-aliases}" ]; - smtpd_milters = [ "local:/run/opendkim/opendkim.sock" ]; - non_smtpd_milters = [ "local:/var/run/opendkim/opendkim.sock" ]; - smtpd_sasl_auth_enable = true; - smtpd_sasl_path = "/var/lib/postfix/auth"; - smtpd_sasl_type = "dovecot"; - #mailman stuff - mailbox_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp"; - - transport_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ]; - virtual_alias_maps = [ "hash:/var/lib/mailman/data/postfix_vmap" ]; - local_recipient_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" "ldap:${config.sops.secrets."postfix_ldap_aliases".path}" "$alias_maps" ]; - }; - }; - dovecot2 = { - enable = true; - enableImap = true; - enableQuota = true; - quotaGlobalPerUser = "10G"; - enableLmtp = true; - mailLocation = "maildir:~/Maildir"; - sslServerCert = "/var/lib/acme/${hostname}/fullchain.pem"; - sslServerKey = "/var/lib/acme/${hostname}/key.pem"; - protocols = [ "imap" "sieve" ]; - mailPlugins = { - perProtocol = { - imap = { - enable = [ "imap_sieve" ]; - }; - lmtp = { - enable = [ "sieve" ]; - }; - }; - }; - mailboxes = { - Spam = { - auto = "subscribe"; - specialUse = "Junk"; - autoexpunge = "60d"; - }; - Sent = { - auto = "subscribe"; - specialUse = "Sent"; - }; - Drafts = { - auto = "subscribe"; - specialUse = "Drafts"; - }; - Trash = { - auto = "subscribe"; - specialUse = "Trash"; - }; - }; - modules = [ - pkgs.dovecot_pigeonhole - ]; - extraConfig = '' - auth_username_format = %Ln - passdb { - driver = ldap - args = ${dovecot-ldap-args} - } - userdb { - driver = ldap - args = ${dovecot-ldap-args} - } - service auth { - unix_listener /var/lib/postfix/auth { - group = postfix - mode = 0660 - user = postfix - } - } - service managesieve-login { - inet_listener sieve { - port = 4190 - } - service_count = 1 - } - - namespace inbox { - separator = / - inbox = yes - } - - service lmtp { - unix_listener dovecot-lmtp { - group = postfix - mode = 0600 - user = postfix - } - client_limit = 1 - } - - - mail_plugins = $mail_plugins listescape - plugin { - sieve_plugins = sieve_imapsieve sieve_extprograms - sieve_global_extensions = +vnd.dovecot.pipe - sieve_pipe_bin_dir = /etc/dovecot/sieve-pipe - - # Spam: From elsewhere to Spam folder or flag changed in Spam folder - imapsieve_mailbox1_name = Spam - imapsieve_mailbox1_causes = COPY APPEND FLAG - imapsieve_mailbox1_before = file:/etc/dovecot/sieve/report-spam.sieve - - # Ham: From Spam folder to elsewhere - imapsieve_mailbox2_name = * - imapsieve_mailbox2_from = Spam - imapsieve_mailbox2_causes = COPY - imapsieve_mailbox2_before = file:/etc/dovecot/sieve/report-ham.sieve - - # https://doc.dovecot.org/configuration_manual/plugins/listescape_plugin/ - listescape_char = "\\" - } - ''; - }; - opendkim = { - enable = true; - domains = "csl:${config.networking.domain}"; - selector = config.networking.hostName; - configFile = pkgs.writeText "opendkim-config" '' - UMask 0117 - ''; - }; - rspamd = { - enable = true; - postfix.enable = true; - locals = { - "worker-controller.inc".source = config.sops.secrets."rspamd-password".path; - "redis.conf".text = '' - read_servers = "127.0.0.1"; - write_servers = "127.0.0.1"; - ''; - # headers in spamassasin style to not break old sieve scripts - "worker-proxy.inc".text = '' - spam_header = "X-Spam-Flag"; - ''; - "milter_headers.conf".text = '' - use = ["x-spam-level", "x-spam-status"]; - ''; - }; - }; - redis = { - vmOverCommit = true; - servers.rspamd = { - enable = true; - port = 6379; - }; - }; - nginx = { - enable = true; - recommendedGzipSettings = true; - recommendedOptimisation = true; - recommendedProxySettings = true; - recommendedTlsSettings = true; - - virtualHosts."${hostname}" = { - forceSSL = true; - enableACME = true; - }; - virtualHosts."${rspamd-domain}" = { - forceSSL = true; - enableACME = true; - locations = { - "/" = { - proxyPass = "http://127.0.0.1:11334"; - proxyWebsockets = true; - }; - }; - }; - }; - }; - security.acme.certs."${domain}" = { + security.acme.certs."${hostname}" = { reloadServices = [ "postfix.service" "dovecot2.service" diff --git a/modules/mail/dovecot2.nix b/modules/mail/dovecot2.nix new file mode 100644 index 0000000..ef3bbcc --- /dev/null +++ b/modules/mail/dovecot2.nix @@ -0,0 +1,158 @@ +{ lib, config, pkgs, ... }: +let + hostname = "mail.${config.networking.domain}"; + dovecot-ldap-args = pkgs.writeText "ldap-args" '' + uris = ldap://localhost + dn = uid=search, ou=users, dc=ifsr, dc=de + auth_bind = yes + !include ${config.sops.secrets."dovecot_ldap_search".path} + + ldap_version = 3 + scope = subtree + base = dc=ifsr, dc=de + user_filter = (&(objectClass=posixAccount)(uid=%n)) + pass_filter = (&(objectClass=posixAccount)(uid=%n)) + ''; +in +{ + networking.firewall.allowedTCPPorts = [ + 993 # IMAPS + 4190 # Managesieve + ]; + sops.secrets."dovecot_ldap_search".owner = config.services.dovecot2.user; + services.dovecot2 = { + enable = true; + enableImap = true; + enableQuota = true; + quotaGlobalPerUser = "10G"; + enableLmtp = true; + enablePAM = false; + mailLocation = "maildir:~/Maildir"; + sslServerCert = "/var/lib/acme/${hostname}/fullchain.pem"; + sslServerKey = "/var/lib/acme/${hostname}/key.pem"; + protocols = [ "imap" "sieve" ]; + mailPlugins = { + globally.enable = [ "listescape" ]; + perProtocol = { + imap = { + enable = [ "imap_sieve" "imap_filter_sieve" ]; + }; + lmtp = { + enable = [ "sieve" ]; + }; + }; + }; + mailboxes = { + Spam = { + auto = "subscribe"; + specialUse = "Junk"; + autoexpunge = "60d"; + }; + Sent = { + auto = "subscribe"; + specialUse = "Sent"; + }; + Drafts = { + auto = "subscribe"; + specialUse = "Drafts"; + }; + Trash = { + auto = "subscribe"; + specialUse = "Trash"; + }; + Archive = { + auto = "no"; + specialUse = "Archive"; + }; + }; + modules = [ + pkgs.dovecot_pigeonhole + ]; + # set to satisfy the sieveScripts check, will be overridden by userdb lookups anyways + mailUser = "vmail"; + mailGroup = "vmail"; + sieve = { + # just pot something in here to prevent empty strings + extensions = [ "notify" ]; + pipeBins = map lib.getExe [ + (pkgs.writeShellScriptBin "learn-ham.sh" "exec ${pkgs.rspamd}/bin/rspamc learn_ham") + (pkgs.writeShellScriptBin "learn-spam.sh" "exec ${pkgs.rspamd}/bin/rspamc learn_spam") + ]; + plugins = [ + "sieve_imapsieve" + "sieve_extprograms" + ]; + scripts = { + before = pkgs.writeText "spam.sieve" '' + require "fileinto"; + + if anyof( + header :contains "x-spam-flag" "yes", + header :contains "X-Spam-Status" "Yes"){ + fileinto "Spam"; + } + ''; + }; + }; + imapsieve.mailbox = [ + { + # Spam: From elsewhere to Spam folder or flag changed in Spam folder + name = "Spam"; + causes = [ "COPY" "APPEND" "FLAG" ]; + before = ./report-spam.sieve; + + } + { + # From Junk folder to elsewhere + name = "*"; + from = "Spam"; + causes = [ "COPY" ]; + before = ./report-ham.sieve; + } + ]; + extraConfig = '' + auth_username_format = %Ln + passdb { + driver = ldap + args = ${dovecot-ldap-args} + } + userdb { + driver = ldap + args = ${dovecot-ldap-args} + } + service auth { + unix_listener /var/lib/postfix/auth { + group = postfix + mode = 0660 + user = postfix + } + } + service managesieve-login { + inet_listener sieve { + port = 4190 + } + service_count = 1 + } + + namespace inbox { + separator = / + inbox = yes + } + + service lmtp { + unix_listener dovecot-lmtp { + group = postfix + mode = 0600 + user = postfix + } + client_limit = 1 + } + + + plugin { + # https://doc.dovecot.org/configuration_manual/plugins/listescape_plugin/ + listescape_char = "\\" + } + ''; + }; +} diff --git a/modules/mailman.nix b/modules/mail/mailman.nix similarity index 59% rename from modules/mailman.nix rename to modules/mail/mailman.nix index efaee90..23d36a9 100644 --- a/modules/mailman.nix +++ b/modules/mail/mailman.nix @@ -20,8 +20,10 @@ webSettings = { DATABASES.default = { ENGINE = "django.db.backends.postgresql"; - NAME = "mailmanweb"; + NAME = "mailman-web"; }; + ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS = false; + ACCOUNT_PREVENT_ENUMERATION = false; }; ldap = { enable = true; @@ -40,26 +42,43 @@ superUserGroup = "cn=admins,ou=groups,dc=ifsr,dc=de"; }; }; + services.postfix = { + relayDomains = [ "hash:/var/lib/mailman/data/postfix_domains" ]; + config = { + mailbox_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp"; + transport_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ]; + virtual_alias_maps = [ "hash:/var/lib/mailman/data/postfix_vmap" ]; + local_recipient_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ]; + }; + }; services.postgresql = { enable = true; ensureUsers = [ { name = "mailman"; - ensurePermissions = { - "DATABASE mailman" = "ALL PRIVILEGES"; - }; + ensureDBOwnership = true; } { name = "mailman-web"; - ensurePermissions = { - "DATABASE mailmanweb" = "ALL PRIVILEGES"; - }; + ensureDBOwnership = true; } ]; - ensureDatabases = [ "mailman" "mailmanweb" ]; + ensureDatabases = [ "mailman" "mailman-web" ]; }; services.nginx.virtualHosts."lists.${config.networking.domain}" = { - enableACME = true; - forceSSL = true; + locations."/accounts/signup" = { + extraConfig = '' + allow 141.30.0.0/16; + allow 141.76.0.0/16; + deny all; + uwsgi_pass unix:/run/mailman-web.socket; + ''; + }; + locations."/robots.txt" = { + extraConfig = '' + add_header Content-Type text/plain; + return 200 "User-agent: *\nDisallow: /\n"; + ''; + }; }; } diff --git a/modules/mail/postfix.nix b/modules/mail/postfix.nix new file mode 100644 index 0000000..2ba240a --- /dev/null +++ b/modules/mail/postfix.nix @@ -0,0 +1,98 @@ +{ config, pkgs, ... }: +let + domain = config.networking.domain; + hostname = "mail.${config.networking.domain}"; + # see https://www.kuketz-blog.de/e-mail-anbieter-ip-stripping-aus-datenschutzgruenden/ + header_cleanup = pkgs.writeText "header_cleanup_outgoing" '' + /^\s*(Received: from)[^\n]*(.*)/ REPLACE $1 127.0.0.1 (localhost [127.0.0.1])$2 + /^\s*User-Agent/ IGNORE + /^\s*X-Enigmail/ IGNORE + /^\s*X-Mailer/ IGNORE + /^\s*X-Originating-IP/ IGNORE + /^\s*Mime-Version/ IGNORE + ''; + # https://unix.stackexchange.com/questions/294300/postfix-prevent-users-from-changing-the-real-e-mail-address + login_maps = pkgs.writeText "login_maps.pcre" '' + # basic username => username@ifsr.de + /^([^@+]*)(\+[^@]*)?@ifsr\.de$/ ''${1} + ''; +in +{ + sops.secrets."postfix_ldap_aliases".owner = config.services.postfix.user; + + networking.firewall.allowedTCPPorts = [ + 25 # SMTP + 465 # Submissions + 587 # Submission + ]; + services = { + postfix = { + enable = true; + enableSubmission = true; + enableSubmissions = true; + hostname = "${hostname}"; + domain = "${domain}"; + origin = "${domain}"; + destination = [ "${hostname}" "${domain}" "localhost" ]; + networksStyle = "host"; # localhost and own public IP + sslCert = "/var/lib/acme/${hostname}/fullchain.pem"; + sslKey = "/var/lib/acme/${hostname}/key.pem"; + config = { + home_mailbox = "Maildir/"; + # 25 MiB + message_size_limit = "26214400"; + # hostname used in helo command. It is recommended to have this match the reverse dns entry + smtp_helo_name = config.networking.rDNS; + smtpd_banner = "${config.networking.rDNS} ESMTP $mail_name"; + smtp_tls_security_level = "may"; + smtpd_tls_security_level = "may"; + smtpd_tls_auth_only = true; + smtpd_tls_protocols = [ + "!SSLv2" + "!SSLv3" + "!TLSv1" + "!TLSv1.1" + ]; + # "reject_non_fqdn_hostname" + smtpd_recipient_restrictions = [ + "permit_sasl_authenticated" + "permit_mynetworks" + "reject_unauth_destination" + "reject_non_fqdn_sender" + "reject_non_fqdn_recipient" + "reject_unknown_sender_domain" + "reject_unknown_recipient_domain" + "reject_unauth_destination" + "reject_unauth_pipelining" + "reject_invalid_hostname" + "check_policy_service inet:localhost:12340" + ]; + smtpd_relay_restrictions = [ + "permit_sasl_authenticated" + "permit_mynetworks" + "reject_unauth_destination" + ]; + # https://www.postfix.org/smtp-smuggling.html + smtpd_data_restrictions = [ + "reject_unauth_pipelining" + ]; + smtpd_sender_restrictions = [ + "reject_authenticated_sender_login_mismatch" + ]; + smtpd_sender_login_maps = [ + "pcre:/etc/special-aliases.pcre" + "pcre:${login_maps}" + ]; + smtp_header_checks = "pcre:${header_cleanup}"; + # smtpd_sender_login_maps = [ "ldap:${ldap-senders}" ]; + alias_maps = [ "hash:/etc/aliases" ]; + alias_database = [ "hash:/etc/aliases" ]; + # alias_maps = [ "hash:/etc/aliases" "ldap:${ldap-aliases}" ]; + smtpd_sasl_auth_enable = true; + smtpd_sasl_path = "/var/lib/postfix/auth"; + smtpd_sasl_type = "dovecot"; + local_recipient_maps = [ "ldap:${config.sops.secrets."postfix_ldap_aliases".path}" "$alias_maps" ]; + }; + }; + }; +} diff --git a/modules/mail/report-ham.sieve b/modules/mail/report-ham.sieve index a9d30cf..6217a90 100755 --- a/modules/mail/report-ham.sieve +++ b/modules/mail/report-ham.sieve @@ -12,4 +12,4 @@ if environment :matches "imap.user" "*" { set "username" "${1}"; } -pipe :copy "sa-learn-ham.sh" [ "${username}" ]; +pipe :copy "learn-ham.sh" [ "${username}" ]; diff --git a/modules/mail/report-spam.sieve b/modules/mail/report-spam.sieve index 4024b7a..9d4c74b 100755 --- a/modules/mail/report-spam.sieve +++ b/modules/mail/report-spam.sieve @@ -4,4 +4,4 @@ if environment :matches "imap.user" "*" { set "username" "${1}"; } -pipe :copy "sa-learn-spam.sh" [ "${username}" ]; \ No newline at end of file +pipe :copy "learn-spam.sh" [ "${username}" ]; diff --git a/modules/mail/rspamd.nix b/modules/mail/rspamd.nix new file mode 100644 index 0000000..cab3fd0 --- /dev/null +++ b/modules/mail/rspamd.nix @@ -0,0 +1,219 @@ +{ config, pkgs, ... }: +let + domain = "rspamd.${config.networking.domain}"; +in +{ + sops.secrets."rspamd-password".owner = config.users.users.rspamd.name; + users.users.rspamd.extraGroups = [ "redis-rspamd" ]; + services = { + rspamd = { + enable = true; + postfix.enable = true; + locals = { + "worker-controller.inc".source = config.sops.secrets."rspamd-password".path; + "redis.conf".text = '' + read_servers = "/run/redis-rspamd/redis.sock"; + write_servers = "/run/redis-rspamd/redis.sock"; + ''; + # headers in spamassasin style to not break old sieve scripts + "worker-proxy.inc".text = '' + spam_header = "X-Spam-Flag"; + ''; + "milter_headers.conf".text = '' + use = ["x-spam-level", "x-spam-status", "x-spamd-result", "authentication-results" ]; + ''; + "neural.conf".text = '' + servers = "/run/redis-rspamd/redis.sock"; + enabled = true; + ''; + "neural_group.conf".text = '' + symbols = { + "NEURAL_SPAM" { + weight = 0.5; # fairly low weight since we don't know how this will behave + description = "Neural network spam"; + } + "NEURAL_HAM" { + weight = -0.5; + description = "Neural network ham"; + } + } + ''; + "dmarc.conf".text = '' + reporting { + enabled = true; + email = 'noreply-dmarc@${config.networking.domain}'; + domain = '${config.networking.domain}'; + org_name = '${config.networking.domain}'; + from_name = 'DMARC Aggregate Report'; + } + ''; + "dkim_signing.conf".text = '' + selector = "quitte2024"; + allow_username_mismatch = true; + allow_hdrfrom_mismatch = true; + use_domain_sign_local = "ifsr.de"; + path = /var/lib/rspamd/dkim/$domain.$selector.key; + + ''; + "reputation.conf".text = '' + rules { + ip_reputation = { + selector "ip" { + } + backend "redis" { + servers = "/run/redis-rspamd/redis.sock"; + } + + symbol = "IP_REPUTATION"; + } + spf_reputation = { + selector "spf" { + } + backend "redis" { + servers = "/run/redis-rspamd/redis.sock"; + } + + symbol = "SPF_REPUTATION"; + } + dkim_reputation = { + selector "dkim" { + } + backend "redis" { + servers = "/run/redis-rspamd/redis.sock"; + } + + symbol = "DKIM_REPUTATION"; # Also adjusts scores for DKIM_ALLOW, DKIM_REJECT + } + generic_reputation = { + selector "generic" { + selector = "ip"; # see https://rspamd.com/doc/configuration/selectors.html + } + backend "redis" { + servers = "/run/redis-rspamd/redis.sock"; + } + + symbol = "GENERIC_REPUTATION"; + } + } + ''; + "groups.conf".text = '' + group "reputation" { + symbols = { + "IP_REPUTATION_HAM" { + weight = 1.0; + } + "IP_REPUTATION_SPAM" { + weight = 4.0; + } + + "DKIM_REPUTATION" { + weight = 1.0; + } + + "SPF_REPUTATION_HAM" { + weight = 1.0; + } + "SPF_REPUTATION_SPAM" { + weight = 2.0; + } + + "GENERIC_REPUTATION" { + weight = 1.0; + } + } + } + ''; + + "multimap.conf".text = + let + local_ips = pkgs.writeText "localhost.map" '' + ::1 + 127.0.0.1 + ''; + tud_ips = pkgs.writeText "tud.map" '' + 141.30.0.0/16 + 141.76.0.0/16 + ''; + in + '' + WHITELIST_SENDER_DOMAIN { + type = "from"; + filter = "email:domain"; + map = "/var/lib/rspamd/whitelist.sender.domain.map"; + action = "accept"; + regexp = true; + } + WHITELIST_SENDER_EMAIL { + type = "from"; + map = "/var/lib/rspamd/whitelist.sender.email.map"; + action = "accept"; + regexp = true; + } + BLACKLIST_SENDER_DOMAIN { + type = "from"; + filter = "email:domain"; + map = "/var/lib/rspamd/blacklist.sender.domain.map"; + action = "reject"; + regexp = true; + } + BLACKLIST_SENDER_EMAIL { + type = "from"; + map = "/var/lib/rspamd/blacklist.sender.email.map"; + action = "reject"; + regexp = true; + } + BLACKLIST_SUBJECT_KEYWORDS { + type = "header"; + header = "Subject" + map = "/var/lib/rspamd/blacklist.keyword.subject.map"; + action = "reject"; + regexp = true; + } + RECEIVED_LOCALHOST { + type = "ip"; + action = "accept"; + map = ${local_ips}; + } + RECEIVED_TU_NETWORKS { + type = "ip"; + map = ${tud_ips}; + } + ''; + }; + }; + redis = { + vmOverCommit = true; + servers.rspamd = { + port = 0; + enable = true; + }; + }; + nginx = { + virtualHosts."${domain}" = { + locations = { + "/" = { + proxyPass = "http://127.0.0.1:11334"; + proxyWebsockets = true; + extraConfig = '' + allow 141.30.0.0/16; + allow 141.76.0.0/16; + deny all; + ''; + }; + }; + }; + }; + }; + systemd = { + services.rspamd-dmarc-report = { + description = "rspamd dmarc reporter"; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.rspamd}/bin/rspamadm dmarc_report -v"; + User = "rspamd"; + Group = "rspamd"; + }; + startAt = "daily"; + }; + }; +} diff --git a/modules/sogo.nix b/modules/mail/sogo.nix similarity index 96% rename from modules/sogo.nix rename to modules/mail/sogo.nix index 8b2490b..4999dfd 100644 --- a/modules/sogo.nix +++ b/modules/mail/sogo.nix @@ -51,9 +51,7 @@ in ensureUsers = [ { name = "sogo"; - ensurePermissions = { - "DATABASE sogo" = "ALL PRIVILEGES"; - }; + ensureDBOwnership = true; } ]; ensureDatabases = [ "sogo" ]; @@ -67,11 +65,7 @@ in proxy_buffers 8 64k; proxy_buffer_size 64k; ''; - forceSSL = true; - enableACME = true; locations = { - - "^~/SOGo".extraConfig = lib.mkForce '' proxy_pass http://127.0.0.1:20000; proxy_redirect http://127.0.0.1:20000 default; diff --git a/modules/matrix.nix b/modules/matrix/default.nix similarity index 86% rename from modules/matrix.nix rename to modules/matrix/default.nix index 4162020..03d58e1 100644 --- a/modules/matrix.nix +++ b/modules/matrix/default.nix @@ -1,7 +1,7 @@ { config, pkgs, ... }: let - domainServer = "matrix.staging.${config.networking.domain}"; - domainClient = "chat.staging.${config.networking.domain}"; + domainServer = "matrix.${config.networking.domain}"; + domainClient = "chat.${config.networking.domain}"; clientConfig = { "m.homeserver" = { @@ -19,15 +19,17 @@ let return 200 '${builtins.toJSON data}'; ''; - # build ldap3 plugin from git because it's very outdated in nixpkgs - matrix-synapse-ldap3 = pkgs.python3.pkgs.callPackage ../pkgs/matrix-synapse-ldap3.nix { }; - # matrix-synapse-ldap3 = config.services.matrix-synapse.package.plugins.matrix-synapse-ldap3; + matrix-synapse-ldap3 = config.services.matrix-synapse.package.plugins.matrix-synapse-ldap3; in { + imports = [ ./mautrix-telegram.nix ]; sops.secrets.matrix_ldap_search = { key = "portunus/search-password"; owner = config.systemd.services.matrix-synapse.serviceConfig.User; }; + nixpkgs.config.permittedInsecurePackages = [ + "olm-3.2.16" + ]; services = { postgresql = { @@ -42,9 +44,6 @@ in virtualHosts = { # synapse "${domainServer}" = { - enableACME = true; - forceSSL = true; - # homeserver discovery locations."= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig; locations."= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig; @@ -59,12 +58,12 @@ in # element "${domainClient}" = { - enableACME = true; - forceSSL = true; - root = pkgs.element-web.override { conf = { - default_server_config = clientConfig; + default_server_config = { + inherit (clientConfig) "m.homeserver"; + "m.identity_server".base_url = ""; + }; disable_3pid_login = true; }; }; @@ -77,6 +76,10 @@ in plugins = [ matrix-synapse-ldap3 ]; + + log = { + root.level = "WARNING"; + }; settings = { server_name = domainServer; diff --git a/modules/mautrix-telegram.nix b/modules/matrix/mautrix-telegram.nix similarity index 93% rename from modules/mautrix-telegram.nix rename to modules/matrix/mautrix-telegram.nix index 2b96d14..270ccc7 100644 --- a/modules/mautrix-telegram.nix +++ b/modules/matrix/mautrix-telegram.nix @@ -10,9 +10,7 @@ in enable = true; ensureUsers = [{ name = "mautrix-telegram"; - ensurePermissions = { - "DATABASE \"mautrix-telegram\"" = "ALL PRIVILEGES"; - }; + ensureDBOwnership = true; }]; ensureDatabases = [ "mautrix-telegram" ]; }; @@ -46,12 +44,13 @@ in # Use postgresql instead of sqlite database = "postgresql:///mautrix-telegram?host=/run/postgresql"; port = 8082; - address = "localhost:${toString port}"; + address = "http://localhost:${toString port}"; }; bridge = { relaybot.authless_portals = false; permissions = { + # Add yourself here temporarily "@admin:${homeserverDomain}" = "admin"; }; relay_user_distinguishers = [ ]; diff --git a/modules/monitoring/default.nix b/modules/monitoring/default.nix new file mode 100644 index 0000000..4601db9 --- /dev/null +++ b/modules/monitoring/default.nix @@ -0,0 +1,97 @@ +{ config, ... }: +let + domain = "monitoring.${config.networking.domain}"; +in +{ + sops.secrets."grafana/oidc_secret" = { + owner = "grafana"; + }; + # grafana configuration + services.grafana = { + enable = true; + settings = { + server = { + inherit domain; + http_addr = "127.0.0.1"; + http_port = 2342; + root_url = "https://monitoring.ifsr.de"; + }; + database = { + type = "postgres"; + user = "grafana"; + host = "/run/postgresql"; + }; + "auth.generic_oauth" = { + enabled = true; + name = "iFSR"; + allow_sign_up = true; + client_id = "grafana"; + client_secret = "$__file{${config.sops.secrets."grafana/oidc_secret".path}}"; + scopes = "openid email profile offline_access roles"; + + email_attribute_path = "email"; + login_attribute_path = "username"; + name_attribute_path = "full_name"; + + auth_url = "https://sso.ifsr.de/realms/internal/protocol/openid-connect/auth"; + token_url = "https://sso.ifsr.de/realms/internal/protocol/openid-connect/token"; + api_url = "https://sso.ifsr.de/realms/internal/protocol/openid-connect/userinfo"; + role_attribute_path = "contains(roles[*], 'admin') && 'Admin' || contains(roles[*], 'editor') && 'Editor' || 'Viewer'"; + }; + }; + }; + + services.postgresql = { + enable = true; + ensureUsers = [ + { + name = "grafana"; + ensureDBOwnership = true; + } + ]; + ensureDatabases = [ "grafana" ]; + }; + + services.prometheus = { + enable = true; + port = 9001; + exporters = { + node = { + enable = true; + enabledCollectors = [ "systemd" ]; + port = 9002; + }; + }; + scrapeConfigs = [ + { + job_name = "node"; + static_configs = [{ + targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.node.port}" ]; + }]; + scrape_interval = "15s"; + } + { + job_name = "rspamd"; + static_configs = [{ + targets = [ "rspamd.ifsr.de:11334" ]; + }]; + scrape_interval = "15s"; + } + { + job_name = "fabric"; + static_configs = [{ + targets = [ "127.0.0.1:25585" ]; + }]; + scrape_interval = "60s"; + } + ]; + }; + + # nginx reverse proxy + services.nginx.virtualHosts.${domain} = { + locations."/" = { + proxyPass = "http://localhost:${toString config.services.grafana.settings.server.http_port}"; + proxyWebsockets = true; + }; + }; +} diff --git a/modules/nextcloud.nix b/modules/nextcloud.nix index 5c21be4..b2557cc 100644 --- a/modules/nextcloud.nix +++ b/modules/nextcloud.nix @@ -1,7 +1,6 @@ { config, pkgs, lib, ... }: let - domain = "nc.staging.${config.networking.domain}"; - legacy_domain = "oc.${config.networking.domain}"; + domain = "nc.${config.networking.domain}"; in { sops.secrets = { @@ -15,8 +14,8 @@ in services = { nextcloud = { enable = true; - package = pkgs.nextcloud25; - enableBrokenCiphersForSSE = false; # disable the openssl warning + configureRedis = true; + package = pkgs.nextcloud30; hostName = domain; https = true; # Use https for all urls phpExtraExtensions = all: [ @@ -29,17 +28,22 @@ in }; # postgres database is configured automatically database.createLocally = true; - }; - # Enable ACME and force SSL - nginx.virtualHosts.${domain} = { - enableACME = true; - forceSSL = true; - }; - nginx.virtualHosts.${legacy_domain} = { - enableACME = true; - forceSSL = true; - locations."/".return = "301 https://nc.ifsr.de"; + # enable HEIC image preview + settings.enabledPreviewProviders = [ + "OC\\Preview\\BMP" + "OC\\Preview\\GIF" + "OC\\Preview\\JPEG" + "OC\\Preview\\Krita" + "OC\\Preview\\MarkDown" + "OC\\Preview\\MP3" + "OC\\Preview\\OpenDocument" + "OC\\Preview\\PNG" + "OC\\Preview\\TXT" + "OC\\Preview\\XBitmap" + "OC\\Preview\\HEIC" + ]; + }; }; @@ -74,6 +78,9 @@ in preStart = pkgs.writeScript "nextcloud-preStart" '' # enable included LDAP app ${occ} app:enable user_ldap + ${occ} app:enable calendar + ${occ} app:enable tasks + ${occ} app:enable polls # set up new LDAP config if it does not exist if ! ${occ} ldap:show-config s01 > /dev/null; then diff --git a/modules/nginx.nix b/modules/nginx.nix deleted file mode 100644 index 45cb296..0000000 --- a/modules/nginx.nix +++ /dev/null @@ -1,39 +0,0 @@ -{ config, pkgs, ... }: -{ - services.nginx = { - - additionalModules = [ pkgs.nginxModules.pam ]; - enable = true; - recommendedProxySettings = true; - recommendedGzipSettings = true; - recommendedOptimisation = true; - recommendedTlsSettings = true; - - appendHttpConfig = '' - map $remote_addr $remote_addr_anon { - ~(?P\d+\.\d+\.\d+)\. $ip.0; - ~(?P[^:]+:[^:]+): $ip::; - # IP addresses to not anonymize - 127.0.0.1 $remote_addr; - ::1 $remote_addr; - default 0.0.0.0; - } - log_format anon_ip '$remote_addr_anon - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log /var/log/nginx/access.log anon_ip; - ''; - }; - security.acme = { - acceptTerms = true; - defaults = { - #server = "https://acme-staging-v02.api.letsencrypt.org/directory"; - email = "root@${config.networking.domain}"; - }; - }; - security.pam.services.nginx.text = '' - auth required ${pkgs.nss_pam_ldapd}/lib/security/pam_ldap.so - account required ${pkgs.nss_pam_ldapd}/lib/security/pam_ldap.so - ''; -} diff --git a/modules/nix-serve.nix b/modules/nix-serve.nix new file mode 100644 index 0000000..643ceb0 --- /dev/null +++ b/modules/nix-serve.nix @@ -0,0 +1,18 @@ +{ config, pkgs, ... }: +let + domain = "cache.${config.networking.domain}"; +in +{ + sops.secrets."nix-serve/key" = { }; + services.nix-serve = { + enable = true; + package = pkgs.nix-serve-ng; + secretKeyFile = config.sops.secrets."nix-serve/key".path; + port = 5002; + }; + services.nginx.virtualHosts."${domain}" = { + locations."/" = { + proxyPass = "http://127.0.0.1:${toString config.services.nix-serve.port}"; + }; + }; +} diff --git a/modules/padlist.nix b/modules/padlist.nix index 53b2557..c7ea438 100644 --- a/modules/padlist.nix +++ b/modules/padlist.nix @@ -24,13 +24,7 @@ in services.nginx = { virtualHosts.${domain} = { - root = pkgs.callPackage ../pkgs/padlist { }; - enableACME = true; - forceSSL = true; - extraConfig = '' - auth_pam "LDAP Authentication Required"; - auth_pam_service_name "nginx"; - ''; + root = "/srv/web/padlist"; locations = { "= /" = { extraConfig = '' @@ -41,13 +35,16 @@ in extraConfig = '' try_files $uri =404; fastcgi_pass unix:${config.services.phpfpm.pools.padlist.socket}; + fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_index index.php; include ${pkgs.nginx}/conf/fastcgi_params; include ${pkgs.nginx}/conf/fastcgi.conf; + fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; ''; }; + "/vendor".return = "403"; + "/.git".return = "403"; }; }; }; - } diff --git a/modules/sops.nix b/modules/sops.nix deleted file mode 100644 index d34979f..0000000 --- a/modules/sops.nix +++ /dev/null @@ -1,5 +0,0 @@ -{ ... }: -{ - sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; - sops.age.generateKey = false; -} diff --git a/modules/stream.nix b/modules/stream.nix index 3227e45..5d36501 100644 --- a/modules/stream.nix +++ b/modules/stream.nix @@ -1,15 +1,12 @@ { config, ... }: +let cfg = config.services.owncast; +in { services = { nginx = { virtualHosts = { "stream.${config.networking.domain}" = { - enableACME = true; - forceSSL = true; locations."/" = - let - cfg = config.services.owncast; - in { proxyPass = "http://${toString cfg.listen}:${toString cfg.port}"; proxyWebsockets = true; @@ -21,8 +18,12 @@ enable = true; port = 13142; listen = "[::ffff:127.0.0.1]"; - openFirewall = true; rtmp-port = 1935; }; }; + networking.firewall = { + extraInputRules = '' + ip saddr {141.30.0.0/16, 141.76.0.0/16} tcp dport ${toString cfg.rtmp-port} accept comment "Allow rtmp access from campus nets" + ''; + }; } diff --git a/modules/struktur-bot.nix b/modules/struktur-bot.nix new file mode 100644 index 0000000..9773474 --- /dev/null +++ b/modules/struktur-bot.nix @@ -0,0 +1,32 @@ +{ config, pkgs, ... }: +{ + sops.secrets."strukturbot_env" = { }; + # virtualisation.docker.daemon.settings.dns = [ "141.30.1.1" "141.76.14.1" ]; + virtualisation.oci-containers = { + containers.struktur-bot = { + image = "struktur-bot"; + environmentFiles = [ + config.sops.secrets."strukturbot_env".path + ]; + extraOptions = [ "--network=host" ]; + }; + }; + systemd.timers."overleaf-backup" = { + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = "02:22:00"; + Unit = "overleaf-backup.service"; + }; + }; + + systemd.services."overleaf-backup" = { + script = '' + set -eu + ${pkgs.docker}/bin/docker exec struktur-bot python3 backup.py + ''; + serviceConfig = { + Type = "oneshot"; + User = "root"; + }; + }; +} diff --git a/modules/vaultwarden.nix b/modules/vaultwarden.nix index 3ec5e09..a88a7ca 100644 --- a/modules/vaultwarden.nix +++ b/modules/vaultwarden.nix @@ -25,16 +25,12 @@ in ensureUsers = [ { name = "vaultwarden"; - ensurePermissions = { - "DATABASE vaultwarden" = "ALL PRIVILEGES"; - }; + ensureDBOwnership = true; } ]; ensureDatabases = [ "vaultwarden" ]; }; services.nginx.virtualHosts."${domain}" = { - enableACME = true; - forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:${toString config.services.vaultwarden.config.rocketPort}"; }; diff --git a/modules/web/default.nix b/modules/web/default.nix new file mode 100644 index 0000000..3be7efd --- /dev/null +++ b/modules/web/default.nix @@ -0,0 +1,17 @@ +{ ... }: +{ + imports = [ + ./ifsrde.nix + ./ese.nix + ./infoscreen.nix + ./kpp.nix + ./nightline.nix + ./fsrewsp.nix + ./manual.nix + ./sharepic.nix + ./userdir.nix + ./ftp.nix + ./hyperilo.nix + ./notenrechner.nix + ]; +} diff --git a/modules/web/ese.nix b/modules/web/ese.nix new file mode 100644 index 0000000..3929671 --- /dev/null +++ b/modules/web/ese.nix @@ -0,0 +1,33 @@ +{ config, pkgs, ... }: +let + domain = "ese.${config.networking.domain}"; + webRoot = "/srv/web/ese"; +in +{ + services.nginx = { + virtualHosts."${domain}" = { + locations."= /" = { + return = "302 /2025/"; + }; + locations."/" = { + root = webRoot; + tryFiles = "$uri $uri/ =404"; + }; + # cache static assets + locations."~* \.(?:css|svg|webp|jpg|jpeg|gif|png|ico|mp4|mp3|ogg|ogv|webm|ttf|woff2|woff)$" = { + root = webRoot; + extraConfig = '' + expires 1y; + ''; + }; + }; + }; + + users.users."ese-deploy" = { + isNormalUser = true; + openssh.authorizedKeys.keys = [ + ''command="${pkgs.rrsync}/bin/rrsync ${webRoot}",restrict ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEWGdTdobZN2oSLsTQmHOahdc9vqyuwUBS0PSk5IQhGV'' + ]; + }; + +} diff --git a/modules/web/fsrewsp.nix b/modules/web/fsrewsp.nix new file mode 100644 index 0000000..5fe4cd3 --- /dev/null +++ b/modules/web/fsrewsp.nix @@ -0,0 +1,73 @@ +{ pkgs, config, lib, ... }: +let + domain = "fsrewsp.de"; + user = "fsrewsp"; + group = "fsrewsp"; +in +{ + users.users.${user} = { + group = group; + isSystemUser = true; + }; + users.groups.${group} = { }; + users.users.nginx = { + extraGroups = [ group ]; + }; + + services.phpfpm.pools.fsrewsp = { + user = "fsrewsp"; + group = "fsrewsp"; + settings = { + "listen.owner" = config.services.nginx.user; + "pm" = "dynamic"; + "pm.max_children" = 32; + "pm.max_requests" = 500; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 5; + "php_admin_value[error_log]" = "stderr"; + "php_admin_flag[log_errors]" = true; + "catch_workers_output" = true; + }; + phpEnv."PATH" = lib.makeBinPath [ pkgs.php ]; + }; + + + + services.nginx.enable = true; + services.nginx = { + virtualHosts."www.${domain}" = { + locations."/".return = "301 $scheme://${domain}$request_uri"; + }; + virtualHosts."${domain}" = { + root = "/srv/web/fsrewsp"; + extraConfig = '' + index index.php index.html; + ''; + + locations = { + "/" = { + tryFiles = "$uri $uri/ /index.php?$args"; + }; + "~ \.php$" = { + extraConfig = '' + try_files $uri =404; + fastcgi_pass unix:${config.services.phpfpm.pools.fsrewsp.socket}; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_index index.php; + include ${pkgs.nginx}/conf/fastcgi_params; + include ${pkgs.nginx}/conf/fastcgi.conf; + fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; + fastcgi_param HTTP_HOST $host; + ''; + }; + "~ \.log$".return = "403"; + "~ ^/\.user\.ini".return = "403"; + "~* \.(js|css|png|jpg|jpeg|gif|ico)$".extraConfig = '' + expires max; + log_not_found off; + ''; + }; + }; + }; +} diff --git a/modules/web/ftp.nix b/modules/web/ftp.nix new file mode 100644 index 0000000..7529169 --- /dev/null +++ b/modules/web/ftp.nix @@ -0,0 +1,161 @@ +{ config, pkgs, ... }: +let + domain = "ftp.${config.networking.domain}"; +in +{ + services.nginx.additionalModules = [ pkgs.nginxModules.fancyindex ]; + services.nginx.virtualHosts."${domain}" = { + root = "/srv/ftp"; + extraConfig = '' + fancyindex on; + fancyindex_exact_size off; + error_page 403 /403.html; + fancyindex_localtime on; + charset utf-8; + ''; + locations."~/(klausuren|uebungen|skripte|abschlussarbeiten)".extraConfig = '' + allow 141.30.0.0/16; + allow 141.76.0.0/16; + deny all; + ''; + locations."~ /komplexpruef".extraConfig = '' + default_type text/plain; + ''; + locations."=/403.html" = { + root = pkgs.writeTextDir "403.html" '' + + + + + + 403 Forbidden - iFSR + + + +
+ +

403

+

Zugriff verweigert / Access Forbidden

+ +
+
+ 🇩🇪 Deutsch +
+

+ Dieser Ordner ist nur aus dem Uni-Netz zugänglich. +

+
    +
  • Stellen Sie sicher, dass Sie mit dem TUD-Netzwerk verbunden sind
  • +
  • Oder wählen Sie sich über VPN ein
  • +
+
+ +
+
+ 🇬🇧 English +
+

+ This directory is only accessible from the TUD network. +

+
    +
  • Make sure you are connected to the TUD network
  • +
  • Or connect via VPN
  • +
+
+
+ + + ''; + }; + }; +} diff --git a/modules/web/hyperilo.nix b/modules/web/hyperilo.nix new file mode 100644 index 0000000..fd46958 --- /dev/null +++ b/modules/web/hyperilo.nix @@ -0,0 +1,35 @@ +{ ... }: + +{ + # provide access to iLO of colocated server + # in case of questions, contact @bennofs + services.nginx.virtualHosts."hyperilo.deutschland.gmbh" = { + forceSSL = true; + locations."/".proxyPass = "https://192.168.0.120:443"; + locations."/".basicAuthFile = "/run/secrets/hyperilo_htaccess"; + locations."/".extraConfig = '' + proxy_ssl_verify off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade_capitalized; + proxy_set_header Authorization ""; # drop the basic auth headers, otherwise remote console doesn't work + ''; + }; + + # HP iLO requires uppercase Upgrade, not lowercase "upgrade" + services.nginx.commonHttpConfig = '' + map $http_upgrade $connection_upgrade_capitalized { + default Upgrade; + ''' close; + } + ''; + + systemd.network.networks."20-hyperilo" = { + matchConfig.Name = "eno8303"; + address = [ "192.168.0.1/24" ]; + networkConfig.LLDP = true; + networkConfig.EmitLLDP = "nearest-bridge"; + }; + + sops.secrets."hyperilo_htaccess".owner = "nginx"; +} diff --git a/modules/website.nix b/modules/web/ifsrde.nix similarity index 92% rename from modules/website.nix rename to modules/web/ifsrde.nix index d6e8339..84c4ad1 100644 --- a/modules/website.nix +++ b/modules/web/ifsrde.nix @@ -10,7 +10,9 @@ in isSystemUser = true; }; users.groups.${group} = { }; - + users.users.nginx = { + extraGroups = [ group ]; + }; services.phpfpm.pools.ifsrde = { user = user; group = group; @@ -32,14 +34,9 @@ in services.nginx = { virtualHosts."www.${config.networking.domain}" = { - enableACME = true; - forceSSL = true; locations."/".return = "301 $scheme://ifsr.de$request_uri"; - }; virtualHosts."${config.networking.domain}" = { - enableACME = true; - forceSSL = true; root = "/srv/web/ifsrde"; extraConfig = '' index index.html index.php; @@ -63,6 +60,8 @@ in "~ ^/cmd(/?[^\\n|\\r]*)$".return = "301 https://pad.ifsr.de$1"; "/bbb".return = "301 https://bbb.tu-dresden.de/b/fsr-58o-tmf-yy6"; "/kpp".return = "301 https://kpp.ifsr.de"; + "/mese".return = "301 https://ifsr.de/news/mese-and-welcome-back"; + "/sso".return = "301 https://sso.ifsr.de/realms/internal/account"; # security "~* /(\.git|cache|bin|logs|backup|tests)/.*$".return = "403"; # deny running scripts inside core system folders diff --git a/modules/web/infoscreen.nix b/modules/web/infoscreen.nix new file mode 100644 index 0000000..601d0e2 --- /dev/null +++ b/modules/web/infoscreen.nix @@ -0,0 +1,12 @@ +{ config, ... }: +let + domain = "infoscreen.${config.networking.domain}"; +in +{ + services.nginx = { + enable = true; + virtualHosts."${domain}" = { + root = "/srv/web/infoscreen/dist"; + }; + }; +} diff --git a/modules/kpp.nix b/modules/web/kpp.nix similarity index 59% rename from modules/kpp.nix rename to modules/web/kpp.nix index 262da76..bf30ec2 100644 --- a/modules/kpp.nix +++ b/modules/web/kpp.nix @@ -7,9 +7,4 @@ in enable = true; hostName = domain; }; - services.nginx.virtualHosts."${domain}" = { - enableACME = true; - forceSSL = true; - }; - } diff --git a/modules/web/manual.nix b/modules/web/manual.nix new file mode 100644 index 0000000..afcc154 --- /dev/null +++ b/modules/web/manual.nix @@ -0,0 +1,10 @@ +{ config, ... }: +let + domain = "manual.${config.networking.domain}"; +in +{ + services.ese-manual = { + enable = true; + hostName = domain; + }; +} diff --git a/modules/web/nightline.nix b/modules/web/nightline.nix new file mode 100644 index 0000000..8abd76d --- /dev/null +++ b/modules/web/nightline.nix @@ -0,0 +1,70 @@ +{ pkgs, config, lib, ... }: +let + domain = "nightline-dresden.de"; + user = "nightline"; + group = "nightline"; +in +{ + users.users.${user} = { + group = group; + isSystemUser = true; + }; + users.users.nginx = { + extraGroups = [ group ]; + }; + users.groups.${group} = { }; + + services.phpfpm.pools.nightline = { + user = "nightline"; + group = "nightline"; + settings = { + "listen.owner" = config.services.nginx.user; + "pm" = "dynamic"; + "pm.max_children" = 32; + "pm.max_requests" = 500; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 5; + "php_admin_value[error_log]" = "stderr"; + "php_admin_flag[log_errors]" = true; + "catch_workers_output" = true; + }; + phpEnv."PATH" = lib.makeBinPath [ pkgs.php ]; + }; + + services.nginx = { + virtualHosts."www.${domain}" = { + locations."/".return = "301 $scheme://${domain}$request_uri"; + }; + virtualHosts."${domain}" = { + root = "/srv/web/nightline"; + extraConfig = '' + index index.php index.html; + ''; + + locations = { + "/" = { + tryFiles = "$uri $uri/ /index.php?$args"; + }; + "~ \.php$" = { + extraConfig = '' + try_files $uri =404; + fastcgi_pass unix:${config.services.phpfpm.pools.nightline.socket}; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_index index.php; + include ${pkgs.nginx}/conf/fastcgi_params; + include ${pkgs.nginx}/conf/fastcgi.conf; + fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; + fastcgi_param HTTP_HOST $host; + ''; + }; + "~ \.log$".return = "403"; + "~ ^/\.user\.ini".return = "403"; + "~* \.(js|css|png|jpg|jpeg|gif|ico)$".extraConfig = '' + expires max; + log_not_found off; + ''; + }; + }; + }; +} diff --git a/modules/web/notenrechner.nix b/modules/web/notenrechner.nix new file mode 100644 index 0000000..06d4d05 --- /dev/null +++ b/modules/web/notenrechner.nix @@ -0,0 +1,9 @@ +{ config, specialArgs, ... }: +let + domain = "notenrechner.${config.networking.domain}"; +in +{ + services.nginx.virtualHosts."${domain}" = { + root = specialArgs.notenrechner.packages."x86_64-linux".default; + }; +} diff --git a/modules/web/sharepic.nix b/modules/web/sharepic.nix new file mode 100644 index 0000000..6c9e597 --- /dev/null +++ b/modules/web/sharepic.nix @@ -0,0 +1,14 @@ +{ pkgs, config, ... }: +let + domain = "sharepic.${config.networking.domain}"; +in +{ + services.nginx.virtualHosts."${domain}" = { + root = pkgs.fetchFromGitHub { + owner = "jannikmenzel"; + repo = "iFSR-Sharepicgenerator"; + rev = "ac721d5fff2dba1f046939a6d6532b1a8cfceba8"; + hash = "sha256-of+N58TDt2BcbDVEriKn6rjQVl0GdV4ZMEblrdUutZk="; + }; + }; +} diff --git a/modules/userdir.nix b/modules/web/userdir.nix similarity index 63% rename from modules/userdir.nix rename to modules/web/userdir.nix index 16a8d27..25f5bfa 100644 --- a/modules/userdir.nix +++ b/modules/web/userdir.nix @@ -1,4 +1,4 @@ -{ config, ... }: +{ config, pkgs, ... }: let domain = "users.${config.networking.domain}"; port = 8083; @@ -18,18 +18,21 @@ in mkdir -p $HOME/public_html # public_html dir: apache and $USER have rwx on everything inside - setfacl -m u:${apacheUser}:rwx,d:u:${apacheUser}:rwx,d:u:$USER:rwx $HOME/public_html + setfacl -m u:${apacheUser}:rwx,d:u:${apacheUser}:rwx,d:u:''${USER}:rwx $HOME/public_html fi ''; services.httpd = { enable = true; enablePHP = true; + maxClients = 10; + mpm = "prefork"; + extraModules = [ "userdir" ]; virtualHosts.${domain} = { - enableUserDir = true; extraConfig = '' - UserDir /home/users/*/public_html + UserDir disabled root + UserDir /home/users/*/public_html/ Options -Indexes +MultiViews +SymLinksIfOwnerMatch +IncludesNoExec DirectoryIndex index.php index.html @@ -47,14 +50,33 @@ in inherit port; }]; }; + + phpPackage = pkgs.php.buildEnv { + extraConfig = '' + display_errors=0 + post_max_size = 40M + upload_max_filesize = 40M + extension=sysvsem.so + ''; + }; }; services.nginx.virtualHosts.${domain} = { - enableACME = true; - forceSSL = true; - locations."/" = { proxyPass = "http://localhost:${toString port}"; + extraConfig = '' + proxy_intercept_errors on; + error_page 403 404 =404 /404.html; + client_max_body_size 40M; + ''; }; + + locations."/robots.txt" = { + extraConfig = '' + add_header Content-Type text/plain; + return 200 "User-agent: *\nDisallow: /\n"; + ''; + }; + }; } diff --git a/modules/wiki/default.nix b/modules/wiki/default.nix new file mode 100644 index 0000000..372553e --- /dev/null +++ b/modules/wiki/default.nix @@ -0,0 +1,8 @@ +{ ... }: +{ + imports = [ + ./fsr.nix + ./vernetzung.nix + ./ese.nix + ]; +} diff --git a/modules/wiki/ese.nix b/modules/wiki/ese.nix new file mode 100644 index 0000000..4125198 --- /dev/null +++ b/modules/wiki/ese.nix @@ -0,0 +1,86 @@ +{ config, lib, pkgs, ... }: +let + domain = "wiki.ese.${config.networking.domain}"; + user = "wiki-ese"; + group = "wiki-ese"; +in +{ + + system.activationScripts.hacky-mediawiki-convert = '' + cp ${pkgs.imagemagick}/bin/convert /srv/web/wiki.ese/convert + ''; + users.users.${user} = { + group = group; + isSystemUser = true; + }; + users.groups.${group} = { }; + services.phpfpm.pools.wiki-ese = { + user = user; + group = group; + settings = { + "listen.owner" = config.services.nginx.user; + "pm" = "dynamic"; + "pm.max_children" = 32; + "pm.max_requests" = 500; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 5; + "php_admin_value[error_log]" = "stderr"; + "php_admin_flag[log_errors]" = true; + "catch_workers_output" = true; + }; + phpEnv."PATH" = lib.makeBinPath [ pkgs.php ]; + }; + services.nginx = { + virtualHosts."${domain}" = { + root = "/srv/web/wiki.ese"; + extraConfig = '' + index index.php; + ''; + locations = { + "/" = { + tryFiles = "$uri $uri/ @rewrite"; + }; + "@rewrite".extraConfig = '' + rewrite ^/(.*)$ /index.php?title=$1&$args; + ''; + "^~ /maintenance/".return = "403"; + "~ \.php$" = { + extraConfig = '' + fastcgi_pass unix:${config.services.phpfpm.pools.wiki-ese.socket}; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_index index.php; + include ${pkgs.nginx}/conf/fastcgi_params; + include ${pkgs.nginx}/conf/fastcgi.conf; + fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; + ''; + }; + "/rest.php" = { + tryFiles = "$uri $uri/ /rest.php?$args"; + }; + "~* \.(js|css|png|jpg|jpeg|gif|ico)$" = { + tryFiles = "$uri /index.php"; + extraConfig = '' + expires max; + log_not_found off; + ''; + }; + "/_.gif" = { + extraConfig = '' + expires max; + empty_gif; + ''; + }; + "^~ /cache/".extraConfig = '' + deny all; + ''; + "/dumps" = { + root = "/srv/web/wiki-ese/local"; + extraConfig = '' + autoindex on; + ''; + }; + }; + }; + }; +} diff --git a/modules/wiki.nix b/modules/wiki/fsr.nix similarity index 70% rename from modules/wiki.nix rename to modules/wiki/fsr.nix index 1c82037..ac16e41 100644 --- a/modules/wiki.nix +++ b/modules/wiki/fsr.nix @@ -38,6 +38,7 @@ in }; extraConfig = '' + wfLoadSkin( 'MinervaNeue' ); $wgSitename = "FSR Wiki"; $wgArticlePath = '/$1'; @@ -57,49 +58,54 @@ in $wgUseAjax = true; $wgEnableMWSuggest = true; $wgDefaultSkin = 'timeless'; + $wgDefaultMobileSkin = 'minerva'; //TODO what about $wgUpgradeKey ? # Auth # https://www.mediawiki.org/wiki/Extension:PluggableAuth # https://www.mediawiki.org/wiki/Extension:OpenID_Connect - $wgPluggableAuth_EnableLocalLogin = true; + $wgOpenIDConnect_MigrateUsersByEmail = true; + //$wgOpenIDConnect_MigrateUsersByUserName = true; + $wgPluggableAuth_EnableLocalLogin = false; $wgPluggableAuth_Config["iFSR Login"] = [ "plugin" => "OpenIDConnect", "data" => [ - "providerURL" => "${config.services.portunus.domain}/dex", + "providerURL" => "https://sso.ifsr.de/realms/internal", "clientID" => "wiki", "clientsecret" => file_get_contents('${config.sops.secrets."mediawiki/oidc_secret".path}'), ], ]; ''; - extensions = { + # some extensions are included and can enabled by passing null + VisualEditor = null; + # the dir in the mediawiki-1.42.3.tar.gz inside of the extension folder is called "SyntaxHighlight_GeSHi" not "SyntaxHighlight" + SyntaxHighlight_GeSHi = null; + MobileFrontend = pkgs.fetchzip { + url = "https://extdist.wmflabs.org/dist/extensions/MobileFrontend-REL1_43-3b4cac8.tar.gz"; + hash = "sha256-aJOArZl+oO/ADjxIhlFVGS8hGmpSp6nsgC7XkKEk1Ks="; + }; PluggableAuth = pkgs.fetchzip { - url = "https://web.archive.org/web/20230615112924/https://extdist.wmflabs.org/dist/extensions/PluggableAuth-REL1_39-068be5d.tar.gz"; - hash = "sha256-kmdSPMQNaO0qgEzb8j0+eLlsNQLmfJfo0Ls4yvYgOFI="; + url = "https://extdist.wmflabs.org/dist/extensions/PluggableAuth-REL1_42-1da98f4.tar.gz"; + hash = "sha256-5uBUy7lrr86ApASYPWgF6Wa09mxxP0o+lXLt1gVswlA="; }; OpenIDConnect = pkgs.fetchzip { - url = "https://web.archive.org/web/20230615113527/https://extdist.wmflabs.org/dist/extensions/OpenIDConnect-REL1_39-42e4d75.tar.gz"; - hash = "sha256-VN0G0Crjlx0DTLeDvaSFtMmYsfB7VzgYkSNDS+nkIyQ="; - }; - VisualEditor = pkgs.fetchzip { - url = "https://web.archive.org/web/20230723212424/https://extdist.wmflabs.org/dist/extensions/VisualEditor-REL1_39-b1204c9.tar.gz"; - hash = "sha256-g/ATW3xkecHynwbwLbmYgawNW+LCVTth0ZlhY7A3N5U="; + url = "https://extdist.wmflabs.org/dist/extensions/OpenIDConnect-REL1_42-6c28c16.tar.gz"; + hash = "sha256-X5kUuvxINbuXaLMKRcLOl2L3qbnMT72lg2NA3A9Daj8="; }; }; }; - portunus.dex.oidcClients = [{ - id = "wiki"; - callbackURL = "https://${domain}/Spezial:PluggableAuthLogin"; - }]; - nginx = { recommendedProxySettings = true; virtualHosts.${domain} = { - enableACME = true; - forceSSL = true; + locations."/robots.txt" = { + extraConfig = '' + add_header Content-Type text/plain; + return 200 "User-agent: *\nDisallow: /\n"; + ''; + }; locations."/" = { proxyPass = "http://127.0.0.1:${toString listenPort}"; proxyWebsockets = true; diff --git a/modules/wiki/vernetzung.nix b/modules/wiki/vernetzung.nix new file mode 100644 index 0000000..bd1a4a9 --- /dev/null +++ b/modules/wiki/vernetzung.nix @@ -0,0 +1,83 @@ +{ config, lib, pkgs, ... }: +let + domain = "vernetzung.${config.networking.domain}"; + user = "vernetzung"; + group = "vernetzung"; +in +{ + + users.users.${user} = { + group = group; + isSystemUser = true; + }; + users.groups.${group} = { }; + services.phpfpm.pools.vernetzung = { + user = user; + group = group; + settings = { + "listen.owner" = config.services.nginx.user; + "pm" = "dynamic"; + "pm.max_children" = 32; + "pm.max_requests" = 500; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 5; + "php_admin_value[error_log]" = "stderr"; + "php_admin_flag[log_errors]" = true; + "catch_workers_output" = true; + }; + phpEnv."PATH" = lib.makeBinPath [ pkgs.php ]; + }; + services.nginx = { + virtualHosts."${domain}" = { + root = "/srv/web/vernetzung"; + extraConfig = '' + index index.php; + ''; + locations = { + "/" = { + tryFiles = "$uri $uri/ @rewrite"; + }; + "@rewrite".extraConfig = '' + rewrite ^/(.*)$ /index.php?title=$1&$args; + ''; + "^~ /maintenance/".return = "403"; + "~ \.php$" = { + extraConfig = '' + fastcgi_pass unix:${config.services.phpfpm.pools.vernetzung.socket}; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_index index.php; + include ${pkgs.nginx}/conf/fastcgi_params; + include ${pkgs.nginx}/conf/fastcgi.conf; + fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; + ''; + }; + "/rest.php" = { + tryFiles = "$uri $uri/ /rest.php?$args"; + }; + "~* \.(js|css|png|jpg|jpeg|gif|ico)$" = { + tryFiles = "$uri /index.php"; + extraConfig = '' + expires max; + log_not_found off; + ''; + }; + "/_.gif" = { + extraConfig = '' + expires max; + empty_gif; + ''; + }; + "^~ /cache/".extraConfig = '' + deny all; + ''; + "/dumps" = { + root = "/srv/web/vernetzung/local"; + extraConfig = '' + autoindex on; + ''; + }; + }; + }; + }; +} diff --git a/modules/zammad.nix b/modules/zammad.nix new file mode 100644 index 0000000..cbff484 --- /dev/null +++ b/modules/zammad.nix @@ -0,0 +1,40 @@ +{ config, lib, ... }: +let + domain = "tickets.${config.networking.domain}"; +in +{ + services.zammad = { + enable = true; + database = { + createLocally = true; + type = "PostgreSQL"; + }; + redis.port = 6380; + port = 8085; + secretKeyBaseFile = config.sops.secrets."zammad_secret".path; + }; + + + services.redis = { + servers.zammad = { + port = lib.mkForce 6380; + enable = true; + }; + }; + # disably spammy logs + systemd.services.zammad-web.preStart = '' + sed -i -e "s|debug|warn|" ./config/environments/production.rb + ''; + + services.nginx.virtualHosts.${domain} = { + locations."/" = { + proxyPass = "http://localhost:${toString config.services.zammad.port}"; + }; + locations."/ws" = { + proxyPass = "http://localhost:${toString config.services.zammad.websocketPort}"; + proxyWebsockets = true; + }; + }; + + sops.secrets."zammad_secret".owner = "zammad"; +} diff --git a/modules/zsh.nix b/modules/zsh.nix deleted file mode 100644 index bb3ac04..0000000 --- a/modules/zsh.nix +++ /dev/null @@ -1,36 +0,0 @@ -{ pkgs, ... }: -{ - environment.systemPackages = with pkgs; [ - # fzf - bat - duf - ]; - users.defaultUserShell = pkgs.zsh; - programs.fzf = { - fuzzyCompletion = true; - keybindings = true; - }; - programs.zsh = { - enable = true; - shellAliases = { - l = "ls -l"; - ll = "ls -la"; - la = "ls -a"; - less = "bat"; - }; - histSize = 100000; - histFile = "~/.local/share/zsh/history"; - autosuggestions = { - enable = true; - highlightStyle = "fg=#00bbbb,bold"; - }; - - shellInit = - '' - source ${pkgs.zsh-fzf-tab}/share/fzf-tab/fzf-tab.plugin.zsh - - zsh-newuser-install () {} - ''; - }; -} - diff --git a/modules/options.nix b/options/default.nix similarity index 100% rename from modules/options.nix rename to options/default.nix diff --git a/overlays/default.nix b/overlays/default.nix new file mode 100644 index 0000000..3d7b533 --- /dev/null +++ b/overlays/default.nix @@ -0,0 +1,44 @@ +_final: prev: +let + inherit (prev) fetchurl; + inherit (prev) fetchpatch; + inherit (prev) callPackage; +in +{ + # AGDSN is running an outdated version that we have to comply to + bacula = (prev.bacula.overrideAttrs (old: rec { + version = "9.6.7"; + src = fetchurl { + url = "mirror://sourceforge/bacula/${old.pname}-${version}.tar.gz"; + sha256 = "sha256-3w+FJezbo4DnS1N8pxrfO3WWWT8CGJtZqw6//IXMyN4="; + }; + })); + # Mailman internal server error fix + # https://gitlab.com/mailman/mailman/-/issues/1137 + # https://github.com/NixOS/nixpkgs/pull/321136 + pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [ + (_python-final: python-prev: { + readme-renderer = python-prev.readme-renderer.overridePythonAttrs (_oldAttrs: { + propagatedBuildInputs = [ python-prev.cmarkgfm ]; + }); + }) + ]; + + keycloak_ifsr_theme = callPackage ../modules/keycloak/theme.nix { }; + portunus = callPackage ./portunus.nix { }; + mediawiki = (prev.mediawiki.overrideAttrs (_old: rec { + version = "1.43.0"; + + src = fetchurl { + url = "https://releases.wikimedia.org/mediawiki/${prev.lib.versions.majorMinor version}/mediawiki-${version}.tar.gz"; + hash = "sha256-VuCn/i/3jlC5yHs9WJ8tjfW8qwAY5FSypKI5yFhr2O4="; + }; + + })); + + hedgedoc = prev.hedgedoc.overrideAttrs ({ patches ? [ ], ... }: { + patches = patches ++ [ + ./hedgedoc/0001-anonymous-uploads.patch + ]; + }); +} diff --git a/overlays/hedgedoc/0001-anonymous-uploads.patch b/overlays/hedgedoc/0001-anonymous-uploads.patch new file mode 100644 index 0000000..83eead2 --- /dev/null +++ b/overlays/hedgedoc/0001-anonymous-uploads.patch @@ -0,0 +1,62 @@ +diff --git a/app.js b/app.js +index d41dbfbd7..faf686cfa 100644 +--- a/app.js ++++ b/app.js +@@ -203,6 +203,7 @@ app.locals.serverURL = config.serverURL + app.locals.sourceURL = config.sourceURL + app.locals.allowAnonymous = config.allowAnonymous + app.locals.allowAnonymousEdits = config.allowAnonymousEdits ++app.locals.allowAnonymousUploads = config.allowAnonymousUploads + app.locals.disableNoteCreation = config.disableNoteCreation + app.locals.authProviders = { + facebook: config.isFacebookEnable, +diff --git a/lib/config/default.js b/lib/config/default.js +index d038e5311..9ab9a6bb1 100644 +--- a/lib/config/default.js ++++ b/lib/config/default.js +@@ -33,6 +33,7 @@ module.exports = { + protocolUseSSL: false, + allowAnonymous: true, + allowAnonymousEdits: false, ++ allowAnonymousUploads: false, + allowFreeURL: false, + requireFreeURLAuthentication: false, + disableNoteCreation: false, +diff --git a/lib/config/environment.js b/lib/config/environment.js +index da50a660d..b74d122f4 100644 +--- a/lib/config/environment.js ++++ b/lib/config/environment.js +@@ -31,6 +31,7 @@ module.exports = { + allowOrigin: toArrayConfig(process.env.CMD_ALLOW_ORIGIN), + allowAnonymous: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS), + allowAnonymousEdits: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS_EDITS), ++ allowAnonymousUploads: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS_UPLOADS), + allowFreeURL: toBooleanConfig(process.env.CMD_ALLOW_FREEURL), + requireFreeURLAuthentication: toBooleanConfig(process.env.CMD_REQUIRE_FREEURL_AUTHENTICATION), + disableNoteCreation: toBooleanConfig(process.env.CMD_DISABLE_NOTE_CREATION), +diff --git a/lib/config/hackmdEnvironment.js b/lib/config/hackmdEnvironment.js +index c40ffc961..20c2da83b 100644 +--- a/lib/config/hackmdEnvironment.js ++++ b/lib/config/hackmdEnvironment.js +@@ -22,6 +22,7 @@ module.exports = { + allowOrigin: toArrayConfig(process.env.HMD_ALLOW_ORIGIN), + allowAnonymous: toBooleanConfig(process.env.HMD_ALLOW_ANONYMOUS), + allowAnonymousEdits: toBooleanConfig(process.env.HMD_ALLOW_ANONYMOUS_EDITS), ++ allowAnonymousUploads: toBooleanConfig(process.env.HMD_ALLOW_ANONYMOUS_UPLOADS), + allowFreeURL: toBooleanConfig(process.env.HMD_ALLOW_FREEURL), + defaultPermission: process.env.HMD_DEFAULT_PERMISSION, + dbURL: process.env.HMD_DB_URL, +diff --git a/lib/web/imageRouter/index.js b/lib/web/imageRouter/index.js +index d9964827b..7321bc805 100644 +--- a/lib/web/imageRouter/index.js ++++ b/lib/web/imageRouter/index.js +@@ -59,8 +59,7 @@ async function checkUploadType (filePath) { + imageRouter.post('/uploadimage', function (req, res) { + if ( + !req.isAuthenticated() && +- !config.allowAnonymous && +- !config.allowAnonymousEdits ++ !config.allowAnonymousUploads + ) { + logger.error( + 'Image upload error: Anonymous edits and therefore uploads are not allowed' diff --git a/overlays/portunus.nix b/overlays/portunus.nix new file mode 100644 index 0000000..ac09a9b --- /dev/null +++ b/overlays/portunus.nix @@ -0,0 +1,32 @@ +{ lib +, buildGoModule +, fetchFromGitHub +, libxcrypt-legacy +, nixosTests +}: + +buildGoModule rec { + pname = "portunus"; + version = "2.1.1"; + + src = fetchFromGitHub { + owner = "majewsky"; + repo = "portunus"; + rev = "v${version}"; + sha256 = "sha256-+pMMIutj+OWKZmOYH5NuA4a7aS5CD+33vAEC9bJmyfM="; + }; + + buildInputs = [ libxcrypt-legacy ]; + + vendorHash = null; + + passthru.tests = { inherit (nixosTests) portunus; }; + + meta = with lib; { + description = "Self-contained user/group management and authentication service"; + homepage = "https://github.com/majewsky/portunus"; + license = licenses.gpl3Plus; + platforms = platforms.linux; + maintainers = with maintainers; [ majewsky ] ++ teams.c3d2.members; + }; +} diff --git a/overlays/prometheus-postfix-exporter/0001-cleanup-also-catch-milter-reject.patch b/overlays/prometheus-postfix-exporter/0001-cleanup-also-catch-milter-reject.patch new file mode 100644 index 0000000..2b60316 --- /dev/null +++ b/overlays/prometheus-postfix-exporter/0001-cleanup-also-catch-milter-reject.patch @@ -0,0 +1,25 @@ +From f4c5dd5628c873981b2d6d6b8f3bbf036b9fd724 Mon Sep 17 00:00:00 2001 +From: Rouven Seifert +Date: Thu, 2 May 2024 11:20:27 +0200 +Subject: [PATCH] cleanup: also catch milter-reject + +--- + postfix_exporter.go | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/postfix_exporter.go b/postfix_exporter.go +index f20d99c..676d767 100644 +--- a/postfix_exporter.go ++++ b/postfix_exporter.go +@@ -335,6 +335,8 @@ func (e *PostfixExporter) CollectFromLogLine(line string) { + e.cleanupProcesses.Inc() + } else if strings.Contains(remainder, ": reject: ") { + e.cleanupRejects.Inc() ++ } else if strings.Contains(remainder, ": milter-reject: ") { ++ e.cleanupRejects.Inc() + } else { + e.addToUnsupportedLine(line, subprocess, level) + } +-- +2.44.0 + diff --git a/pkgs/matrix-synapse-ldap3.nix b/pkgs/matrix-synapse-ldap3.nix deleted file mode 100644 index 0635ab0..0000000 --- a/pkgs/matrix-synapse-ldap3.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ isPy3k, buildPythonPackage, pkgs, service-identity, ldap3, twisted, ldaptor, mock }: - -buildPythonPackage rec { - pname = "matrix-synapse-ldap3"; - version = "0.2.2"; - - format = "pyproject"; - - src = pkgs.fetchFromGitHub { - owner = "matrix-org"; - repo = "matrix-synapse-ldap3"; - rev = "2584736204165f16c176567183f9c350ee253f74"; - sha256 = "gMsC5FpC2zt5hypPdGgPbWT/Rwz38EoQz3tj5dQ9BQ8="; - }; - - propagatedBuildInputs = [ service-identity ldap3 twisted ]; - - # ldaptor is not ready for py3 yet - doCheck = !isPy3k; - checkInputs = [ ldaptor mock ]; -} diff --git a/pkgs/padlist/default.nix b/pkgs/padlist/default.nix deleted file mode 100644 index e3f4640..0000000 --- a/pkgs/padlist/default.nix +++ /dev/null @@ -1,10 +0,0 @@ -{ stdenvNoCC, ... }: -stdenvNoCC.mkDerivation { - name = "padlister"; - src = ./.; - phases = [ "unpackPhase" "installPhase" ]; - installPhase = '' - mkdir -p $out - cp -r $src/index.php $out - ''; -} diff --git a/pkgs/padlist/index.php b/pkgs/padlist/index.php deleted file mode 100644 index 60bf364..0000000 --- a/pkgs/padlist/index.php +++ /dev/null @@ -1,79 +0,0 @@ -getMessage(); - die(); -} - -$query = 'SELECT "Notes".title, "Notes"."updatedAt", "Notes"."shortid", "Users".profile FROM "Notes" JOIN "Users" ON "Notes"."ownerId" = "Users".id WHERE (permission = \'freely\' OR permission = \'editable\' OR permission = \'limited\') AND strpos(content, \'tags: listed\')>0 ORDER BY "Notes"."updatedAt" DESC'; -try { - $stmt = $dbh->query($query); - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); -} catch (PDOException $e) { - echo "Error: " . $e->getMessage(); - die(); -} - -function formatDateString($stringDate) -{ - $datetime = DateTime::createFromFormat('Y-m-d H:i:s.uP', $stringDate); - $formattedDate = $datetime->format('d.m.Y H:i'); - return $formattedDate; -} -?> - - - - - - - - - Pad lister - - - - - -
-

- - - - - - - - - - - - - - - -
TitelOwnerLast edit
- - - username ?> - - -
-

-
- - - diff --git a/secrets/admin.yaml b/secrets/admin.yaml index 7f6d4f3..576f3a8 100644 --- a/secrets/admin.yaml +++ b/secrets/admin.yaml @@ -1,135 +1,147 @@ -cachix_password: ENC[AES256_GCM,data:7SleCWYfyhlde2vuIr6hGtAwuSbiz5W8PpUHd8TIh4I=,iv:mAr67t4jvLc7cUn7WQaY/oU3AN1w28tCBJBI1ZfeS3U=,tag:Dodk7V+nnswtSuEH6R5LGw==,type:str] +cachix_password: ENC[AES256_GCM,data:SjzpKHIFRvXDARjidS03eA0EmzXtsNjfkSnPTsafNhc=,iv:mAr67t4jvLc7cUn7WQaY/oU3AN1w28tCBJBI1ZfeS3U=,tag:VSPF158J1iP5x6qkytGeGA==,type:str] sops: kms: [] gcp_kms: [] azure_kv: [] hc_vault: [] age: [] - lastmodified: "2023-08-14T09:08:46Z" - mac: ENC[AES256_GCM,data:Vb5iZpE0D0kQrhrtm18y4WQj7W4c8oT+oFeFPgQBCJ1EJyHemREgn2RskCZeevad896qjWAR3xtk2uGc9SOEqFhWX4OkyhTGAo5h66YygNw3LbCsarfUcYQ7Jthdw2rnozLLIOEZ0yykeaayWEULbdHZjgaJwI+DIwOyTkBgmK8=,iv:96/Ph7+HDjT8su+vmtUB7d24OVY4h4BmfiTudwW+7DQ=,tag:F9JfGnSZOMN3GHdMXCVRPg==,type:str] + lastmodified: "2023-12-26T17:03:43Z" + mac: ENC[AES256_GCM,data:RJ1qczvz9tRPf0krPFbSDURZJSx5Bx/K7Pz3urNYn8wt4/M1B9EJI0nlHMuun/QjCDYMmiOzvvJMEdOBI/OeRZaQrp9+9LBB+9r4jOhU8BIP5czzKaGpDpZ9o/6avZf38SfrjR0M8NHVuTRGW8vzstu92KyeXaIRqfJ1JX+ucbo=,iv:93dkoIJHFVQaGqNBW/9/QxobRLiv+hd73lsV2ZXJHX4=,tag:H7IJVW+c4EaMPdmJDr+7oA==,type:str] pgp: - - created_at: "2023-08-14T09:08:12Z" - enc: | + - created_at: "2024-02-29T15:23:18Z" + enc: |- -----BEGIN PGP MESSAGE----- - hF4DntlvaG5T7wcSAQdASuJ50zZbRm83JgWvBkhhqb9CYA7I5b4erFYEG4YAugMw - r0nWOEVjWhMiYuvgQkNbD2QLioNbmYrElL7zRpLW66HhXX0F+SSF07SGxBY3DFX5 - 0l4BqOepz3eG9yUO3rWewZZmdFmtgSSgutCqHSA3Z/3dmNupSoScGUl2qVTFTZ0n - pZqfDRnLrrRLGdqQ8ChgyzkaD4g6wQULApScmewit/QlRi4s84JBvqVcro6OXXof - =8TRl + hF4DntlvaG5T7wcSAQdAnAE456PXzGekxSnrumXHqeCY5tm0/20vrPDDidjy3Wcw + k4WIu4Sglhukn5LrQkzzcskoFpGHrPj5tN84jilNDjMz8nVR1zniAlrKTP59C/fQ + 0l4BIQYlqkqkEDc+kuWzy2O0mteKrlo86Byv6NryvY5DseXUFd6pVde8n8ns5tSZ + /jSh5Fo3/xkmJ+aS2SturNqUixHYbGBHUpfQ/IakxriSfLdtkf3N82M8e5jJUWB3 + =ZaVg -----END PGP MESSAGE----- fp: B8E1727497FC48AA14158BDF947F769D7B95EC2B - - created_at: "2023-08-14T09:08:12Z" - enc: | + - created_at: "2024-02-29T15:23:18Z" + enc: |- -----BEGIN PGP MESSAGE----- - hQIMA/YLzOYaRIJJAQ//aIBDcdbJwRjT0xgiRjmMIpiM9ZXfipl/UGP6N3y9Xndx - IaVp4trITGXIIvChYo0WylCvPPrXdnUdwthu7sR7P7yjF/ZyDorYnSGB856/bUaV - nX6to+zNnk6Zo7VBXW9HIqH+nG1JQW2kv8uF7hZSIvXVTYuuS2FfZMV3Vye1eQJ+ - 5hbraPc0ioJFZe+sz9vLICGGdS7aY73lGrWllgpOgmtKc+S6OAHSH6zSkJ0rGzxq - AhkaVytNeB6Wc9QZw0YETwRv5ZKEZNCuMLDsB6OvP11T5Bod+SK59uFk4qFyHk40 - AcZ/FpdVPyH38rpBEjR68ARypLCXQqcTCUcVMtqW3+xm+msOF5Oax7psqBFLd1C3 - C1X7MnXNWIcUiqm0Cl/d8DQUB4SNoKLwKMFGH9voPmpcht/1aqudMuloiSJrR8ia - B7out4PhQh4UGtdqilbEsntWmoiDmftvYKQiK+iA2PaNZPvFaDET6a21L9Ezk4mW - XVZ8AiSxyQRH2c7l2jVPZZ3KZa40EOvdP1lIiCvlrp2KBlj+r+lqduFR/qG7vr/E - avRT2qxqR4y+wVlXGcPONyTrb9qGZrn1bnwkZ5at4O0QYYyiOt2PTe16WBgEhOyd - WDT2dnb7lG7fDSiY6iVzhYmnywEOREDEZ7ZoGzfGpgz9fDwrVvfpWgWkfLayHDLS - XgEGvE2F1rGyAQVrAaLWNH01WL/7waZd8C/M3R0tbvyNVl+cEWnVmtz/LhRQuji1 - qVXKzZSkc/YKuDLoJnIl4x9pVoi42AWf23YGltdk8osyq5b4eOMmoExhsdXItLg= - =dCdG + hQIMA/YLzOYaRIJJAQ/9F9PE1/Dpehh2HvyzkbBMxar0ZrWItB9UpMN4VJjipI7x + 8cMU7iIp3gDrVfwEzdARzXOUGugoxYPttJMe4ZRrIHtjnQBWf+e0TcDy4eqdHqYH + COAWRBctYAWqSU7n4Gq/mqtNGe1VDY9Q5rhpDqhPc01KWO72AgLUwH6zoyGM4YBN + 7u7eF0vqcaZGQyzo4IjasnYlPjgIDehVzdl8Zpy/yYOFNozLFBV7HLqItEl7vdEq + DPGzz7vKAK1pHK0Qie5MBTbEMJ2yIBiGIJ/rZv5h9RvAuVu0uqjFbehis5yK2N4s + hEBVaECXfvuvc0wP7EIgxdUoDeh+o4OUL6OneQRXeMqdlsw+oq8WnKywi4bf8dDl + 1gNs7PLa0ROQKyOiB/LAZn4GmnNLSD2KnlTYoyrt3s8tgfRCHOhoWxGmBGfV3Z2C + KjbucxT0Wz0gSSBr6ht0lL0DD0UFQ9WJbz2Dns82CCr5T+ehHk5YVGQPSSxPaDlz + qnNdS+OvrgbofKAk7JcR9Po/ajoOAEvv6GfA0ujFi3FxyjwgaPS6Je4fC2gUVrwb + 2z7OCzmpp3vGrFB0BvKSwrCQLIeffWl8M4bOoCDKM+XyMEUML7TsTrFkoQ+wzvqN + V53askywgCRfSkfBsEWV1Aoms4QmPnvkuoD0N4F40MRtD2HmhxrgqwmSh3Iu9qPS + XgGkJ/TnuWJ0KkBePo8xBqokVTfbhiGufYXXz6B80tHl6Xrmd5rcz8km0tCc/GUZ + R8yygpt4uFujJEQzaCdT7Y8kt+WRXaNq7pZ0lsQF7lYtpusZhPBv3pDkb4/6ALs= + =nVIs -----END PGP MESSAGE----- fp: 91EBE87016391323642A6803B966009D57E69CC6 - - created_at: "2023-08-14T09:08:12Z" - enc: | + - created_at: "2024-02-29T15:23:18Z" + enc: |- -----BEGIN PGP MESSAGE----- - hQIMA8uqUsBLHj6XAQ//b1bA73WQ0H2rYX/scP68fDjnkeIRq227YW6sY3Fm/ob1 - 4vmllEgZBTlzQwZb84fc0FBIP2xBzHXgKCmzt/+EEb0VUAc0KvNyJwa65apOV1MV - juzNYzL1rPph+rlk0NVkWQvop6OTGZ1rsq8GgJoffm3dYUAZysoyKJFwn+zy2sh6 - Q9kbWCsX8O/6ImLp6WgJXGUGt2MkkXUkMTdIvWHQntNuQtgh2E4Fz/HCdSW5TT3z - FoV/FaVNPMP1JiG3ym+q4p9zRQTynWb8JqGlWgt86vKdyqf/sBDMZHpjbZeX5O4m - RKiTpjAgDoJJYCB7WrnHhHJkVo2E0vi8bM86BJ0G4rubWTYhYlpLOMNIl+iVo1j5 - H11vtJ/dphat1/8006dpeyA7xlw6Woq09Org6dRGV43sBK2oiNNznbigt6BCKylw - m2sUY/VyAEqkd2knYsfkfiVUy6R/yHkgGUJo94QUtfEs7Yw0VMwx8U/N7Gwrx5zB - 8CUxxOnCNeynDPP3sPsei61RXretbJ0wXxoOv8P1GHIPYhAbEX9Oi3u81FnAmykJ - NxM+Ip9RbeS9lRvuasMJSFawqJU10v7XLp6EjB+Ed+vNDzxPBnhbUYNKJRE/Gq4k - Phx/ySn900r+MX/1097TvL0GQH5TDK94R/Pip6K+iAeZPoFQFbhh0r4aYlARTpnU - aAEJAhCiPLz6o+/CDSsM7HQuATjywPk487/2PZ7SVYXNl1mXPgTfQJaDvOHjlinU - yPO2XNwDkKQwtq72AY1oSEODJvFQyTLHSNNCt3Wbfm7LNbzp3UAarQ8g8dFOfCuY - p6vOQwd0oQ4B - =ZwoK + hQIMA8uqUsBLHj6XAQ/+Ofo4GZUZEca+ThmZmF8g5OlPOfgPxRUHuTHoiOthXTuS + IO7BSCYPHdZlnDqNMELdQfKZHRFirehibMIFedfoiKEuhJaQ1p9go0CnIhcX7tzA + aNaBbbJBmAYxUfPdExkJK9SqDxV7aXC8OHzXHwcZqCc/G38E4fOMVsvUVdD+Nymf + lEXmgXpU1ib5vRaH1oCOf8d1C6LFFC+peBBbyzwhNgFgVYP8NrXWkeIiRSiKpFpx + 3lsLODLIYXteoO0DkkuT2z/0G86EYo+bmSx5Ubi0waxfO3sLdUnDaIIC/6pJqbS8 + QM3HtEL1kQaAFure/r+K7Ck8l0eTKbfnd52jLoMFK+1g5587KjV70fpx4QBvyq0X + d0xJAfJSRptkIlMOS5+tYOXd2SOtoG7XwprrUs+lleE/Z4SaOjyGWkLE0L1D+Qhp + /8jw0cU46O69ig0p47H1klvJ5TkZkSroCkarVRUS4AHhpnLLnDMYDkuVoZeKM+rz + tOF8Sj/ySF3PA0W5cGf8dK8u8EXgIlApLbo4ZOBHff9yJJvuDJjt2b3hWPZh/uHF + ASxPF26cz6+ysGLl8COvWLRlxDD22aP27P2A7+9LYi9p1csNL+wuYwfnF7/rrrLx + Suv2InJqsUV5JkLlhoTYnv6kIwrz0oVSnTOFIBgQ3dex3T0DUn/eEdFO1BHY7BfU + aAEJAhDp5eds7PB2IJhFuHuYcsYquRDlwlQ6CY0fWTR3cI3bzNTLAe+ITv19CBUV + eGi9XUc05QDgUapvUewGXZXlFxo7iDDw1H7S1exSeRY/sbmeDE1G8beZxEqD2Rbq + Rlwq7HypFnxX + =M/ss -----END PGP MESSAGE----- fp: F8634A1CFF7D61608503A70B24363525EA0E8A99 - - created_at: "2023-08-14T09:08:12Z" + - created_at: "2024-02-29T15:23:18Z" enc: |- -----BEGIN PGP MESSAGE----- - wcFMAzUXo8ZPJwGLAQ//YGciouPJhSuo1gEi8A31dsuXM0ka9INVTCtOP1kcZmAT - 4ov/00GfaCd0XkoX43ZEV7lZrpQ8zW1iBFNi2Ojknu3HRJrmiRtTj2wv6ZOtsyvz - 2Ac2ADp91AMaACibt+XzEPGtnU9FitVEl0MM7pbllcu6jqcV/sa8CNf2564OTTQ0 - 6Fy1NsvbpAwJ5lyk5fXxsUlR/SGN8HWJRjytal0DLwyhgQZpnbZro+pMfM771x6U - 5JztJVTILMGhfomSa5Tjotkncfilymjhg4eVGoD2MVbc9pjmze+pLzH2cjP8NyyA - 4zrp7UgNT/EQM8RNgYg1KxIPGYYIEa+83253bjfCexR2gh0xlyVqc5o0Ql2xBUVY - LckLYVFAowgxuTOFDLIEgs5t0qFotHbLxQsfy1grFShhp/4p+vPRq8UgAHBjTzTJ - NKw69yaJySeZ47hR7p+AUODTfjyZ0UrdFraI8qT16LRa9xPH7S8+F50dj8aeeEU+ - ss+3g1ionuNGztLWJOK7yIm3ZHh/RIP6DyLp7r+PAII9jyWQLOOWZ1+Ugo8irevb - xGBMxt7FhqWAxzGMBL+x7qSOGAh+hDv4aIP2692nBjSOwmao5LF5A5jsLk7JbJ3e - 6DJz435wCdbNklHu09oSn6hoD5LuTFNP1K/q+FmOd8GZKhaqR6SXJuTN6RfPwyHS - UQHZexhIfUx4aUQFzY/PbFxjI6QnHoW8PgaZ8vrL598Mpb5Sqd8Dx+NSnN8ifEXz - ophXLjNmlamF0wyx8z9bEitGwZvckt5rSdu+KxkF+duVAQ== - =QRWO + hQIMAzUXo8ZPJwGLAQ/+Jbtq6OyOcXYHWj6T74BDA1hcilHrP7yp5w3Za7DwKWpp + sLTcXo1ZywokwSBH8lm1zmhnho5BN968YTbwqb/y4FMX2MJP/VIgjgpkl9KoiZHM + py818xRsVttggsqoTnN6mtOYIEOu9lQCtA8zXgc5BIr1xDpRlVmz8VyeG70a32vI + PaG6BAmOoIQXNikNqhzyinSKkHHzDFGyxfdYGR2bMuGNSbpIr42DHOHVKWd7mzHW + Wm3BOaFHe76aYUByXujBPJ1oXm3PYLAPxXVudc4GCj23V3fj7oczCU74ggmmFLGk + PJkRRIRHHqAjb3C6LZ2V1sF2+eazlpSLcvf/KVRc12wFMzoPSpEb+Ft3MHYEhBn6 + o+7+BC94RhGUzu7OI2dK0oMUMZaeByLqFLHH0iZ171TuD3Tqr3NnsUBTJWT7hPw+ + FN/yFsf0ZbRiShv4Vvxyib3NRZZfZ3VTG11qlV1xEBEsBnA3QzUr+J923FxPwOkj + jBzxv9EJX/imXCj965R3vevCbc/6xf8Hy4x4GlqtTTFsw8uKwaQgoqL9eSejEcpU + TXrMaKN4zUEgT/ZPI76teU7HKBxNfS+1yocznaZ6dr3SN5IwX0tX9q3k9Y7D0DyR + LI1U0Wrx7JmbXQa/6ArKzp3fuwNFVkfQNbjvNFh7ghBTWQ8rWXtOU920KzAKwL/S + XgHlxl1gj7/YMrifU01zjSOerzzLetDRBtBQkl0DKeTUXwIjM82Hd8CP2yFaTAFx + AqjVgiJBB5ffCnKLz2wB8QP7BX0IzbVaNAgxwM+dx1tBH5riSXuzCIgrPnuEq8c= + =0rd1 -----END PGP MESSAGE----- fp: 116987A8DD3F78FF8601BF4DB95E8FE6B11C4D09 - - created_at: "2023-08-14T09:08:12Z" - enc: | - -----BEGIN PGP MESSAGE----- - - hQIMA30JDs8MiK29AQ//bWhIT9dYWez0pXeu/NGoMFBa2OxsxxRiJh4Yz0FPTpBl - meDjRhVgg5avcGQT30bFzN8YAxFjoLns0/eWTZvoXWA2boSIwGbH9Yi5tmXp2OKD - mKxtxOQzBsDnzCR5wdUYNbgDX7ebgeRL4dodDpG3MSzWaydSLogCvhDgCE6Spfyc - N/ZvdN4pFzeylQUMgtMinfuAnqSplU1mgkE6Fpzi/BG1mUZyqDEIwlEzJ8uxQqMj - DbiE0aZkt7tOoYaSaX6X/wCkncToIjoVBm3Vvy4nVD/U3HwJMWW+xxZKHEyg3bwm - jySJ8bSoj3u9B0OVn3x/CQpRbGfYvWleCgSR/AbB8x7ccL49x+n5U72q3zsijSGJ - NmS8HZfEvYCEP82Zp7pCZOphrjZg1TKgHB3MXkRdo6tmy/jtznnMbQyobYkj6lFB - NsLg9wcGwG9nK5PK0kB3YrBTi+wSsu8ExxD0MaNpOm12v9ygMbNU0n+bNyUyEseI - KZLapICHWSLSRuQWbbk682CadXmqLlzzzF/FP+4mhx1z+S7f6nuzbariK+ccI4XY - JeeIE9M0vX1foO782WBYI3TvGUAA/MCWdrze3j304RgTxSOl6m3IKq7e89HCt0xo - PUQyfD/e7lsC46dxhuqI62ikKrTgtadVEjTCSUqRlVkJ4DGCkGae5BPsPcF7GpvS - XgHm3czu9w4jda9Qhqv3aqNZhletlYeyJEbY8/7V+mSDvvgjRTZxrxfDcPslraLm - WqqT1IAZRL339pJnPXtPnvAZyjxU6INTzGQfV8j0AAZbIzCGqMU6xkuaStugASY= - =vPdd - -----END PGP MESSAGE----- - fp: BF37903AE6FD294C4C674EE24472A20091BFA792 - - created_at: "2023-08-14T09:08:12Z" + - created_at: "2024-02-29T15:23:18Z" enc: |- -----BEGIN PGP MESSAGE----- - wV4DNffZWjBmO5ASAQdAKSKcjuQ4oCCz1foAgnTSXiRz5FRTE8kGfFMVnZxOpF0w - FCTf4e/KeNBkkHs3fU8KikPirMmbO57MxU+w578efXrM8LRgJFvvkkxLr6tMpfkh - 0lEB6rCNiRb0PzqkowhMZqL6vwqBA7TF0hog1BGkdQPjac7V52oIVdqMyMJU1le2 - lb6NWDgi4mqYlrX/6+cTHnXC9Mub75r5iYzKV935PmUb3JA= - =U9Xi + hQIMA30JDs8MiK29ARAAvPwNXd3KkiVXNtNsOg1udXh08URE59ZJJUPBbe/XOHZI + aUlrU5kwfswTcpmbHok1Faw8ppw9u9HMmL5HoUQ3LpdYBoZFDUmnu2AAhWjEilMB + EoQ/Er+Nq+EfZ1XDufZT3DkHydPVHEIPrau3U+Lf92xzOi6Gqcdx655orHrZSyXl + Z7xRUZi/Py43olmJm3jaLhhju3nVTOPJWAr/im+lVEtTL0jEw/OuSo+63GFmkILi + bESz682YVL4ZtrPwQKZpdoIzsqwTGUSEO4yjuLEshM5QDL1HFE2E9whtehBAfOt+ + 4wTt756hHFpaweQDUm9e+Ce3sA7lifTVjX/h4ZJ55etW53EPP59bTW327mk4Sxxj + X85wo2kD7CaUxwrk01QBkAptuSdUf9d03cw6t3EH/uXYER2mc0BNPdlJB44eYtXE + mwUIk1UZ5rZ2tUPKIdUj0xFNywbTJPN+FKgW44y7k1/PcEKQpwndK1Xoi45HemY7 + cMxMptNSldv1DAQank0CG3xYdCLfkLXfixOrI64Cqx8owTPLvUCic29e7Rw3+vAw + LOR6+mSpF2bGMt1NvpZAP0nHTijWWuGg4V8eMyJcdQ6eHnhFjVaq+EVqQlYas9ym + gPHLZ+eQ2Zy39nutaV/CgmgeniXS45l/H1K6QFhJahg7bpa4Z/qWRAkF/jaUfBbS + XgFhjoVIe3SO2E8YUh+Z0pFyHo5GlKkgENBeO7KJbiOYzwLoIpvpO1baIhHGPyrj + Th/Qj0uYyPYknrwgNivl/c+1nZbkNU4Btsp22+bw+4vq8c8jHKgtvMCwKsNbU4Y= + =beaI -----END PGP MESSAGE----- - fp: B1A16011B86BACB56ADB713DB712039D23133661 - - created_at: "2023-08-14T09:08:12Z" - enc: | + fp: BF37903AE6FD294C4C674EE24472A20091BFA792 + - created_at: "2024-02-29T15:23:18Z" + enc: |- -----BEGIN PGP MESSAGE----- - hQIMA6MARpDCLIz2AQ/7Bvm+qrO0UdHN3goHTwAcy2TKmthBOrknBjTN12ZVPV0L - 21fmywd1MAJrARYnshhUkaaZrjd/hkeRfk2GfRAM58sHQi7J16xVxhvurqErVTTF - 3vOyDeZ1VkscmB9kWYpg9B6dkffs87Yq17N6wTPh/bxStYImRuHx1TmzhdsEZ+9k - QmBeOY1nEGeaHYcXsVLNrfHwcL+VX8kCG9f5W0voR5wOcoJwOEQzz8URzKlzgV8L - uRAhtEt6zWmXv7BiVW39r1JnWNgTjVwp9PhJI6knghiIfibXndGc9pDhJRuWnSQK - d9SrCEPmtWfQxzhdAlFobLI3XkagrZvSj1fIyYbT1dwEiR+4p+FoOp4YuN87xs0I - WeDPUoEMABVpYG6PoICWxCvaFU1cv9yqAc7TKhM8vDFQn1tJ4Ante4U9dLZ+iEbw - LxFr2XdQXLiqYUOI4dtEWO8IQqjyxva3AxU92clN7LIi3CeCDoEJZcg3l4eCtwyP - NUOXozZjnEixw4Q+1EVZZACCTPyAb5Gd994JqtjYmb5575xApWWiQNXf4hGo/WGn - zV0ZIfvohRBKxpWvgv3KUZwwHzz13AbWlBjrPIextRDdnQRZWv9jU6xRUFLM99XO - PlYbAPp5amaYRmwvG86opjcqmPuUTT/W+ss/aK8ddU69KYM+YI7OzqUXC0zPg4bS - XgGpDo6bqCP2YYkSzLYwKzMUHgHz9Ml0IyL5DQw3DMvu54IGL9nkgEd3DyIHdvsn - roJxHvGw18eBhHT0mXuWi9iK0vVMJW8tPw7CVZVSKuLFFsm+3LgkC1UftLvT2yY= - =NSHU + hF4DNffZWjBmO5ASAQdAluq9PmE0yZUumm/G4UtwQpohy8vpNzAh8D1EWVj2KgIw + CkO+UYwhgB0Sl4rqYYgyGI1FK0aVQQYEV8jlvVpzWvaKga2bm3yT7kAp1o8b5Nv4 + 1GgBCQIQp3OqASoqHK2MGQURJr/NY3aHQVBltEe2bkgXj4FgBXu9a1L5hwxow9Ze + YMDBVLkDaH8oCBBwvQVdqBmQe+LEwyr5eb/r0PtTksOfuQQ1TV3kX1Gj1XN31ilQ + LHXyhm6gI7zslw== + =zVpt -----END PGP MESSAGE----- - fp: A4F92BC7B792108A463995827C1F2DA2BC929412 + fp: B1A16011B86BACB56ADB713DB712039D23133661 + - created_at: "2024-02-29T15:23:18Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA1tId/HHLgxAARAAkoe0CqLnz2Nythjm3wnMVrwv+U/ZeaVGemBJCaS9MWXd + inmKUj9fmGdrbqoIhxwgbMBjuHFWrHWO10ahMjQ+X8qOH22SJEDYhZ7H3I+KkuFa + dBrubZizjI7STYSC4vsLftcgNkVtaIWNhc34t4Gv5Dk5rjSXuM3WORm9xrIvJ0N1 + KXBUP6JF9LF0JZTwn86EWeb7Fa3QDKuQ3T7tM+8kypqyh40gd7sKLx7onXLRacbq + U6fcls4Z3m2N+NayNyi+EoKDCUOkDJfms49I21acq7wiigGE/pIDA6MFhL2X5N82 + lj1V3SySHNXfm3QeHi0HvWiNtLp5W7yDoN/T2kLf76gIsiXlrnSR9BnvY0LrnYTR + wY+j9q+942eG3QL0g9gG7L0mM8wZ8QcvdVmbgw3WpbValHSEXwfg4kSuCroZH38e + XEzSgqbuBMrEprGnH8/+gp2VxxDcOnpUQApe6tvrSk0d3GmGxoIriIQonrvEPnNJ + B/25jIns9X3DK3FxL2tYzUSIXv00plLLuy5P0Sl1fvD3/J3faTJ1uX8xB0z4c9Nv + /GG88hE4Al+2da5XRdDhgrS8L5YX0gxKPvwFcALO58v4YU9UxNjp12kEnteqbfPh + 0X57Tin/2cvPdH3e3g7CDi1RPHK7mcxqpcshmuiPNVhou7I7tTh7BGJpP6vpJB7S + XgHwQVfKx/rmB//dUZ3ZcZ6IXActfAxm+F1uXjhRi3hbctLV4GlMAV2/ijLX92Ob + WZv+zdCH1fioicsObmRgYuyk6gPlpMyAA9u915MH12o0G/AwZaquIfocmRlDwuU= + =zv+X + -----END PGP MESSAGE----- + fp: FB44F0746DF25F0B24A2EAE586C8A257C3EC82AB + - created_at: "2024-02-29T15:23:18Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4Da5T//DC6DJkSAQdAtDsm8pgrR36jWw5qeWr2Ezxa0Y/feoC5R2rDatrPySsw + rXez9HoJLmHPJf5iFMxpEhgO8LAeRkSOUVDoMQAKnwP76CRAI+Y6uDa9qlWvWFDQ + 0l4Byo0ib5MviXkFCy0ZslKpwAL5NR4VllC87HhndwkynizQgRevmB+ITU4QeNZo + +eNJaGphJdn0CuAO1F4vOw/qTHSzVxrLaux9J7Ovy1oM/jbFcAbUIelfkLZc13xR + =5kVn + -----END PGP MESSAGE----- + fp: FBBFAC260D9283D1EF2397DD3CA65E9DD6EB319D unencrypted_suffix: _unencrypted version: 3.7.3 diff --git a/secrets/quitte.yaml b/secrets/quitte.yaml index aee5279..108a8ea 100644 --- a/secrets/quitte.yaml +++ b/secrets/quitte.yaml @@ -1,167 +1,173 @@ -nextcloud_adminpass: ENC[AES256_GCM,data:AJHISi8zIVXOMPZAghgBhEsIYS9NT4XogmyCC5TI33k=,iv:sb09G5T+7UdUumbaz20XFHuOR2tC8rQIqQP9/wOT77c=,tag:uju5DqwJtFtC7Tn5J5Xmqw==,type:str] -hedgedoc_session_secret: ENC[AES256_GCM,data:l5a9sd731MDjNRu85XNOWJcGmNkMLsyW1jHbucn9fGg=,iv:SZhcy7IWD0pwCnL03QH5VKHsIvvAL/Ex7zFiSp2JQ60=,tag:chWdf27vLwb4W4SQl/Y7Ug==,type:str] -wg-fsr: ENC[AES256_GCM,data:g4h7yCox7rLhJOVkvEPJi0g8pVMf6OduI5LpcmXBOrQHEbnyj6OajD3nbO0=,iv:WWyvftIoWwUv7MmcnVobcyFYyLdpbK5zDhj17j30VQk=,tag:ZxSkrRGfSL119/E4eNcntA==,type:str] -dex: - environment: ENC[AES256_GCM,data:98xqoRjGZX40f2+gqTiLITuj3285sa359gapa2XurQQD6zg0mqmDTxgcU2dj0Q6k9GE0l5xF5bkguA1eVofylTY9mbidWy5BThisqb1Krv6/gdfybY8Vft/x/A8Y5S71iAzyQkSeLj9Dyoh2Jjro5eSpiA5GnAgTnFL3q3mhy8herANRNMSP6s2A5Exzsw0qzTC22KGlmAycGP2jlm3OU9cqwLYWR0WItJBE/2hYaRSaow/VVuQLTY2zdqrs6cp8SmOiMDdJ5teu910/FLi13jah9148jNKZqLtKx3gxiHweBKjjFglj+jZMTQu3O9aGF7CR3y/EuzAAnqMR5dahONURu06w/0KSXCHX14DxfFU=,iv:meB+u6JhU24aqOHJLmxH37k7DOuuDc61V7R3rMm/qic=,tag:eAzSueiRa3EfSnpZxxGiXw==,type:str] +nextcloud_adminpass: ENC[AES256_GCM,data:v6FYsO/RklPSz5uf6aYQDhdudHb0962I1WxJM3VGc0af6s/fEz2j+UTu,iv:WzS+jU7qmNQbd1RWDempdu4nv0ytWeybF/PKoc4mvTc=,tag:1CF3ZnQNDLv11j7UoyYsjg==,type:str] +hedgedoc_session_secret: ENC[AES256_GCM,data:WO3j/Sp0LHyNC51jdzChKB46KLU7l57TBVNL3v92sjs=,iv:HVizKMCd+d9cTQEzRncRpv9scldg5Nn2fBRz0D58OOg=,tag:8HZttVgZs4Ah8JWTDaTySA==,type:str] +nix-serve: + key: ENC[AES256_GCM,data:GptsUgeXOOrwJctoMZ+mWXcw9DwJ0f0LOlLyMlH/877N4uA5/NtNKIaFHl3z2GWPRBnDLBzDEO1Q6EDuWbakr+Uq4zTJm2MOV6Qf4kM0BlNpXGIdjvh7tD2La7GV4ID+CT8U6p0E,iv:3A/Yy4PHsq9VdhW4SKIYdpd1enQ5cDiKLk5S9VrH0b4=,tag:WZzbct7LZmOhEvx9KVQ8WA==,type:str] +keycloak: + db: ENC[AES256_GCM,data:DVf/pVCHHUed2cQleECk0paBTZ/6Q3NE,iv:j3sWWNL0dqPJBLUx10+jJ7QvdAHvGM55KKDwG2aQEs0=,tag:6VTeE+Prsm+LPemzbEtVYg==,type:str] portunus: - admin-password: ENC[AES256_GCM,data:9EglcINrzDw1d4VaZALOFy3KddlwAvaWRuUZvXXCmE8=,iv:Z33gf3BqmtvSTNadrAQl0LgU1fZ8fReyO4fFBvy+vlw=,tag:zPTvOeEsc+MvqigesaBMkw==,type:str] - search-password: ENC[AES256_GCM,data:Rf69jCganUJJxyR44mbEgB475SitvvqGCmsMXHH5VAw=,iv:ilOVy1r+HAY3t26yJiO6jExtrl7kll8Mi6fqzBcjYRQ=,tag:KyZCbPhlLSkgkxGT2Du5AQ==,type:str] -dovecot_ldap_search: ENC[AES256_GCM,data:e19xmqOra7xJPPVnW7FtCV6q1JfTDnzgtvEpAY3SFuxCJ8Ucnt/6c/ZlJEM=,iv:XlYw6XpvENraLCnoGpEnqa2pg7VIuU0WyFZJRqjusmc=,tag:UaPkh/Vtv61kRaW3s1dznw==,type:str] -hydra_ldap_search: ENC[AES256_GCM,data:TkaLjcnB1M8/6PiKqzKb2kiv+ix8k5Jn6msV6xQcfcWDA91LUrLlHpIP,iv:N2KSltfWhbn2Csg8chi6DfO6UcIsP8dA+BDQQ7mGPUM=,tag:FyNtOl2WkQ6mi+5gDnjftw==,type:str] -rspamd-password: ENC[AES256_GCM,data:mn8UWBlXKG1s7cP/sLW6DWiqbAydEbv8q1rJzX5zNaZEMjpYAxrGj54Md5XmwQ==,iv:C9vvICgL7GbsOsWx5FyFktospIomfZK4qPh8qMqCELo=,tag:stOGL8UmHocAGWjjjRNZVw==,type:str] + admin-password: ENC[AES256_GCM,data:fESE6vrKhtslQO6ZJGv0T9t+leOSrgkY291orkwY+HPnOh26g2PSMX3j,iv:qmbCmjg0WsbOzfv6LsKcY3S1ssVXmaRB3lE6ZWzKSww=,tag:t8cP8XRTtto3EnNLEdz0yw==,type:str] + search-password: ENC[AES256_GCM,data:xtbWS98IkQbnBu67sN413VNHZLg6eedbStE2uZ2pljS30uoM3coO2d32,iv:lKMTNnQJJfjAG7aX+G0eNnL36Cxmn+cWMRAlTovMJ4Y=,tag:FQGRBqsmY2c9VVIdBvGwCw==,type:str] +forgejo: + runner-token: ENC[AES256_GCM,data:6m2iTuIffqWqVnyD3lo8EazKU4NnKsqvafLF3CpN5qgLshG5ouseaf2RJaX0og==,iv:Nou0N5Z4k4+R9ZdFlTKRBmEJSlIGIPlCQ6E/6i1vdts=,tag:otDe67Hwccoxz1dGmnIqAw==,type:str] +sssd: + env: ENC[AES256_GCM,data:ng189+ulH79xCZKOn9N5kN3KqED9dWqLM8dErukJH3a3ivxhUjyy3Tpa+uSnJDh8tAyOesT1j71mlTgKQKb3phylVEdL,iv:i8NEGR+eQ42q5be4gJdNMf/9DCCcjr3gwkEW/+hrgxs=,tag:16EvtkTu+0M5bIlgxC2j9Q==,type:str] +dovecot_ldap_search: ENC[AES256_GCM,data:xip5KREy8oqH+58DOtw9QLcVdDlO5Nr0IHki8X0i9J1rrI/BreH2tVPC8aRTDHFPRgpBxiL6,iv:98PSXajEis7sSJ4+IkPuBC05y8w7/XRYQVFH1cripEU=,tag:LcId5rlzz3JjjZIHwoh+AA==,type:str] +rspamd-password: ENC[AES256_GCM,data:Dd6lTyDh3FFqOTeipY0o5uJz5/Mh6FsVahbI5M1njn5S690avzQ4+8YISrwkuA==,iv:OAuA+t2KzGDvURng2RWFAoMNfw+RNLtM1hLEniuzz9c=,tag:RBN41BmsrvgXKEOa8gCDfw==,type:str] +authentik: + env: ENC[AES256_GCM,data:7Mcqe2/ny5oghO8kfV1b5LksxxmNGTn6u0LCDH1Q8kwkidOD6MXyMbyzN9LRU4ovDXwXy+ztwnNHBZPvGSGMKUMczIn5hhiA5ri93kk9G8Wy4rGjjt+0Z+JKsZV33rlrYgIr6eGy6Ps=,iv:gkzjx9yQQj31g5fBdAVKzAslpTUjPp1yWnOWQyotYy4=,tag:uOSU653xBYUai6DOF1ddYA==,type:str] +grafana: + oidc_secret: ENC[AES256_GCM,data:oH+VCL4e4wve6RyVwlTXPSmirbf+STD5FxUj9OjGDLs=,iv:PhVVCy5JyRa+fOrYAsnjDL+97zYASmKcBzB8t9ZVWIU=,tag:JzGO/FeKem4vd7ApvZ2Zcg==,type:str] mediawiki: - initial_admin: ENC[AES256_GCM,data:osX7QwHPfmFAJHGuXHY/td7Z+JNzHicixZRvWNLfG+o=,iv:SuKTItyOipoVqx/39+UTDg8npsp0jDaK94k9rPfYdkA=,tag:emNMythpZGwm3Rp8Nx5xCw==,type:str] - oidc_secret: ENC[AES256_GCM,data:2JRvHObJ5xB3A0XduUwdF9a7zzeEPz1nElLEzWC6Hz4=,iv:1tKMlme1bR5JcEk07Xpq99+OHxdtCxjc4xHNlBxq7X0=,tag:cyhstQYvEmjI5Zjj2GWtFQ==,type:str] -mautrix-telegram_env: ENC[AES256_GCM,data:cuQLaLyZ/hSQsN0DnyuBSsIuoZGTUrDsV0lNq6Ky/1pgd5Ull9OYJu5bsgMWauki6lOprxqBE+32TSoWPb8WFUT9/NO7U9b+aoaCs/R8HeePxnaIyiBiGv881YY54Ze8jLXFU3XAxj4VHESSCNSEktApTvJvd1VXJjJGoV3iFWZhl1VbLsE+lQSHSiDLU6JqUyXa6k1BGUepGrkwObGoKyLVFODF3uahXsXtcfgbMQ4UfqZevh44dj+kDDtohXje,iv:jmcWTyVkqu9nDc1ws2NxkMKrHPZ13i3jqDkk4Y0kejw=,tag:h7llbDCz8PmvfxLzrQlrCA==,type:str] -postfix_ldap_aliases: ENC[AES256_GCM,data:11ARqAOq4bXWFGZqFKqUOGulV6rBOZ4375WXdiAD/khToVYyCdJ30ThCQuTk4q9D3L1CT1RcbQf0nQwJfAz9zODpqhrucFAIWhfreHSPeLxgWIPXVKqEISDHsM80f8cZHoTyh+hr2lNhecum4XgdUYy/keLlmzQrwNWxKQcN6fXRyEhnyIiLMEuClAfpL4vvW1pFka9txPnWFtwjPZecwCNn9pD9VpEhIukETtjVM2oCU1WRT0w6fAeFQnpHqBq/E7lPc32rn71gSpMmmbpGB5qPuGJ051Mr/QLdADX0+f8bebzGCtFudyBK5BrTeW1J2iScmXnPNYphA3Zr+Uq2Ss8=,iv:dQM6LNmIwrwJLF1pGuoHZhoJulfVhgC0HWdZXZS4pxQ=,tag:vyH8Zbh7eSQhIQ4bhwnLOw==,type:str] -vaultwarden_env: ENC[AES256_GCM,data:lGDemdGgYemaaWhWBPEMuP4yie5Ceum5ZZ0hKRLz8TJENrBNuTGGnG9cQ+L5m0uC4c0+GmRYHZZFAbWxz2JAjx8rR3lGQkSzbynTWKPuVMMulsjMO1DLVcRv5MzLRNAKgZnqiNYGXOMVhGNyTq+qNgp02TEpDJytfP5U1ZzQcjaPKmCUkEUSH0I=,iv:foByTYQw1KnB1MmwSQqmwza9PJJmdYdZbIHKrZ9vog4=,tag:OoqJ5kIjNaJZYyno31x5rA==,type:str] + initial_admin: ENC[AES256_GCM,data:JzW2rgXQHXxj1e3vFhkXVkWSgrA3Y88KWlQ81hqUHw2UvnBH4GWtMXbZ,iv:zqKUyEaIOa/7hpwzjJPwk5gfqbEYJrE7Oc1Zqcqm3vo=,tag:T1gObIGtI4uVdpONvIXofA==,type:str] + oidc_secret: ENC[AES256_GCM,data:XNbpKd42PLV+orXY/HqnYKOpt+HD4EmVMtAR+lRw+x8=,iv:XtmVdArhYmp0E1xL5lD1LMjJt+vyQPv/lG3g6fnsD00=,tag:onxncWUsG3QuvUebgVpLnQ==,type:str] +mautrix-telegram_env: ENC[AES256_GCM,data:FyMtJChtir8Ip8S7zlBSvKccjt+7Hl0StHzxmKO7VdwNNA650HHfni9o7akIY52+r86tvP3D/bqHaBZqkq61ZNICnFJuYIkROvt1035uej1cdjlHeCrZBttI2w3ZkkKT/RZq5BOLt52o/fnw5Jlt+3yr6Kzd5mvcz6a2e5V96kFjaib6mMdg/Y6axiXvOSeFOHCjs6Js+ab7MDe90KUM3aLtBezXx9YTeU7RiqEiZl21dxzPIwilj8bhEB0RRIb1,iv:1ojF2NyQfaZbKwlHQND7LEOLWT1SWCpGPQTm2+0Y+xo=,tag:RavBAv49Ldm4rH+2DDGstQ==,type:str] +postfix_ldap_aliases: ENC[AES256_GCM,data:beJTXpJYlAz4vyv2rAyuMtU2gkwf4JNnsFAG0oKLWuKQZnX/EyqyGTFK7hOs12qye26H9Ysl5vP12iDyVXU4cyYmBOMSOiIS4opPVs7yjp/FH0u6DXHExzd8qs5vwa+D+c9j05kLVZ85EGneDma4ITNBjo/JMjyXCHB0e8EZTFyfR8+fq+qvuyOUmLBfJSO5BK96u370DJ7EmIPLDiCUSO2MCD86yfFEq5J++ljeuKLxUtisqFWDPNeNq3YGjz0EHUgcqqDwzLwEEXyvn5FEI00nR0qBgSBTSWRDrndo5O2k3JMfZWW9UhXXS4kPwCYEkQSM240cwLNV/Rb9XceH2wxzL8PcfTNiy2vd,iv:lb9u3ryu1+G95OIizX17ft+fGK2CA2xt9DhYhtKda1c=,tag:CsS2Q32AgAyS5eZ7Z/Kf8g==,type:str] +vaultwarden_env: ENC[AES256_GCM,data:JFySiTHahlUFsM+FcuSJPnGYMijphrnZpFFdoNe7DYxWjIgPRWdfH9WC/a5GsK2xCJXllXAASHNxgkYRrdPw2KaCiUR/QhAjtUmyv2NsIBcMYStafDUEK9emddR+ACedScsgS0FtP8f3cz1enTBi+DkYgL8lMAoCw5p8vMRyE9mVOLpTUDOO7T4=,iv:992REuXzHAxxhy2BbeCGNhTZkn8eSi8N2RyBXqqy7U0=,tag:iP5AFQqzoR66AkTGfYAUZg==,type:str] +kanboard_env: ENC[AES256_GCM,data:AQ3jU78hi8YGzfWXTo2wnS9Q9hucgtKBrB/xiIyrZl/j6QpQmr/HS6gEizgY7Du8ZhkRmRTZ8ks99EOpPUdN0LXhegZB0loCWEozkPCn+N0UZXqKDVAz2UsyQu04Eu4FPRqw9VMIS30qJarqZGjvAJmBWNd8znW9ggtg8bMxqwWuErdyMhCCbXeAsw4O8XasGR27e4SGRJNWR5QH7VX7GqOb0Q2AFr9BQhNyO9MgczmqwldqirqaIACIaSVvOOByh56M+rbWyiaAL2O7BqcHS0dtV+XG2uVpxb02b456iArRyKco41bVC1sSRfi2ewCNLma+yNgR7t1WYZeA8537gMX9LaU5ORnn+L0toM8j2yUnfW9RYA3dqp50Yt2UKH/jjLwW5wKLrOF1G2Pb5TAl12ghPLfTfJiuv1SLgahLK5lP/I/x3dJ/n3gm7/lqu2EPDnaPtPDotV0VWfBLwQoXAjSFvSZVfxwYIon/ErxsACtxgT1Ss4L88Ggc33ae1BFyURX7p7738eizsqUV8WWqa74Jt+uT32nU45B2DyyzFQWfy4mGsgBssuZzgFbzLyYDiXfcq500K16950cWPH9s5Sx1XooCcHeTJYyVHklCJ/0r3Iz2g1TtKktpr5XW7EEcCLKQ86UqpKwg9PwEHVnYgFKe8IuSeAAGzZczeUFvERrRJs8qZqPE1IaufozSr5bGBh4eRdv/kVDFyh7wJ62xStVb7IV+sXogA13m/emfxdy1RBWftHcsgZ03r4pdp7mHzNqRvYYscx4UzB237GNzG82PJ/zLk73XGRCv4iE11KWZs9oyoOI4RFFvGwNS8jV3wWh4I7Is3SWO0cy+41qeuL0oNeRVseVENZ5zqxC1sPIP+z16XiTlGWUefTYinFjKmjojF2+uSS6bGZteB70iynB28FUUEqU4Wa0RwGDOck21cw8PnIMpiP+LWdnaH6sKS+EMl9IXcraH31wNK76dcUy3dPqU257bp1e1OJ0Y/fO/1ZTT4Usm7CrXCon0gcDWFAB+c57c+omfYW3kZ4F99Y2ht5QZEvjK20rEXLQb5e1SqIC0ssjP+7vpc+SfNQ6jQ6B6Vye9cyaNkgzGoWZFwHME7cgehs+2FkCOVgPlJ8hDupSTc1BgFzT3JJtejsflbMeoa13nvTYWZopW5M6Ym81TQGv/awPimMh17sDx9r38bU+kiVs5Y6MVuSQZIRICOtg6cxh5Q+fDzTyirsrctVGdcI96WyW90IwBL2wYI7ntWdNwaAPoTu8OFw0kKW2+JsaNHeXQfGmWZfUtKWIJetnUn22SLAe86J71hFBveVlokehQ7Fcg0MFt2r9mlR0/eP1aWyrN54tyEv5uOekmKE00FN/8PpzgH7qasvRPuuXkotj1gazJYk7Tz0oO9OTM4M/yplrL8fLOwP75Uc5PGGVu3pHmwkfrjhh72V993Su0V3us4p+whv2ItZ/A4O0np9CSvFEJXOS4esCmsXLqr4BbBy2veoxnIiF3MEmEqbkMtgkslnVwM1RVNPCKESxFzu0oU5phyWn0a4JW46g5lx1tm/GWXlHQWa4=,iv:x3+PuXdpZ+SEuqHo7icQVyzGEI3IdEyYjjOFkKbzq2o=,tag:pWoe2PC/tEODmz7o6wcVPQ==,type:str] course-management: - secret-key: ENC[AES256_GCM,data:wWzoUGt/5Yusy1s/RPhZbDJFdTCjxHiRODKhDnOUUik=,iv:svN+pmwBXlL7ghOiF4y04Tnivv9Zr6ZoVWrCVFzs/gY=,tag:+gTxfipVNLGuYZM8KDsoIg==,type:str] - adminpass: ENC[AES256_GCM,data:Y2/WTOCGme1C8jbKla+I0dzNWbf3JtACtZD9pd9V3w0=,iv:zXAtduU460I7E4dQjyln71Icq9PYGP40qxqRfv85WIQ=,tag:dMz5jlyy1S04/sMt2xLb+A==,type:str] + secret-key: ENC[AES256_GCM,data:zMoIj8gjNmLdSbQmFo8n1pDIKaUUMzPfVoKkPlqNtm4=,iv:AM5wwvAFXKVss4N2/lK6bKYHV/4Bv5EOz2MVTxAPF1w=,tag:ARzQUVVjz+HhUT+JAISHkA==,type:str] + adminpass: ENC[AES256_GCM,data:EariUHHtWirIXuRARj7lEneAOlKcjca9T+J0oH2xPv99w4ac1cRrvEVD,iv:cjC/+AnZdwWXkJOIAE36Hk/if4fqofVFf0H8WkHkRY8=,tag:M+s4hPzSp8eR76M/7TKXPg==,type:str] bacula: - password: ENC[AES256_GCM,data:je85cIfdDrRl5mkOujiZM57xFG7HrtLyfsDNVab6tBAXMZ6TvcaZrrmzjfKDOYrT,iv:lfPpWXz2h8iSyECaPVJzi8sdks7fxPHewHagaKCBHY0=,tag:1WcE5wRA/q7IB7Y1TgjtvA==,type:str] - keypair: ENC[AES256_GCM,data:lYDS3U7+++aXowGA2DLWGs4/pBxzjk9VXivEqqvEcMOLvgPwPiVKuXqHShw4NkH6qcoLzOqqjDpEt9aW5sYcVkIR7gNTiBcGLrVe88ZPHYNa1/mnwZbNVKGutM/S6wuyf8J33mrfbQ0ujkavSIE5zOqFyaHx4kU0wHdxjIl3q8RqUL+6s3+vwOoxubKndBzV7NhfvCZBZ7JRJK5bORuOrbgQMgwrACTysR4gRVyiu39ku/AlHXGCmrl+GBHTAm3EOJyrIBBoZSLNyGkFv5ay82Oe/CvRxzkR5lK2xHi7tdBUtoOOrqT1KNRKZxsXpKUP0N8ctCD5/4pAVYbhDE7KQDGfwWioT6xSJJvHF2IYAnxV+A63SkrgSSMWG/xj4ZtvMqbngJZ6KqGDqS8qmjupB4fS7mMp/lsOFcL4w8w+isAHM637Yb4/Sfw704+oBMViBFGFJ+o4V5BbjGHygIgUQXHabeOk4u17e+4V6CVxEIlrzafRcYPDAwQE1qvJ388dq9z6wws94dQnTgEaW1O6/ye8uAvtvuUzwgfnT5CU4ypqn0OylOzthNqJfr7KfX3/+Nu8tiAZEkzCvCDGDnyla0fzpm+BZwpLcAmhMv47vS5NwUghJ5iCGjssmdEDncclwolwi/vvmtYdPchbUKuKn+ro/R/ZkMDOGvQHvC9fmbn7lEJFUesCQLwtxHNsj6NqR6tYqJJRPIFOtSeak70DKak9/2NCInVwrbZ8Z12Lp6xGgc19RYDDVQ302cGhWkYfcXMoM7Vgxl5Ta57TALDbs0aZnvtlUxmWpUUwF43+t5gxKW6nEbJwHfD60G5Je8tiik0fuO0D/XsV56/ih9yKgqxhTqaMNrWgYoTjqmqg9dfhVwe8AhpXdlUR9R71TKAmkkmNJUHJmRNk4rp5ZIlVu193eybA9WyPPTWojMaKV8GQVdhkRKCUSeIyhttGZov1Xg5xIvpQ/l+TDYVpnF9ol/RR8zqCKguU+D8i1Bju28kCbmmogzlmS4Q3QoMJk5pn0wqX8NytE62mmE+sbmqSt+vK2xXIUvxUQSOvzka/Cyj6lyd0+9W1YiaTK1xe2no4QswJuTVZ7PRMZLQL2O3eGOrAR+BbVnIhsfi4fFNcQ1pxmtqCT+wvulaLd+CH1xUTBjkc30YbMpN+ElLFZBuhXv48RP82iizUSs6FumBNG53QHN+Ucv0u3wpqQwjlGlv9euARxJZVxqA65clXc7f2VzJNHBYXB97LG4eOTykVYUWsUS5fIurCZseGgyVAMCAo/YO2jMXrqcEJiyLs4EKCRo4Yin7wNyf34qhZ3ilpofADhKtSU17vXL8HQwKn0fpt6RI2hSc8xTalOAFF9B4J08a8f/6Mx5jy8FHKSEbu91usKDy9bGi/Cq/f09vBymwjoe0cvPdllOZT0Ik7WO1gl8UU8sXxDkjM0mekslQSE3vzlQpZ2JcjRHSxVsC0u+500jap979aShw63OJTa2sQ8KCQ/EJrw7P/xQJ8STtMxd5JBl/fX1e0AM7tKhb7h2JpwqrR221iQtG8FdJD8JUT6hTOQKMW5L3SZj3//GF4XrmsowP6eEbFJUhCXGUoSHWeVF2RZVALDHm8HC9cWUASIyiNCBJmV0mE1LgrAvSd7jkZE+P0DQcMOjjnMn44xYqnrQgplgI/glTt0QQqdyMfAgGrv8dfwQGn8TafY4rPjMU3L768Y3mvSCfE2//lKued4B88LAG4zBfxh8iF2wEAptU4xHy8cf3Y1cJWUPwg0xBVsslA0FKpxHKQ95LGIU0vq3EYvSOk+9eQ3BBmql9vflfhjlSlS7DUcwLJ6iGurTksapczu5kQu5vDuyc4OFUz21+rSPUph1LaOUj0PgF1B4NGRyevW4/LKIyYFxKj9ibYVWEfNrDvRXJnpXT/ffwT2t68OIMwyBIygNwLKaa2mg5RK6Il6T/F85CSxbNs0XMZnempZfbCDR1THtIY2B8WyPXH1WIEqDlEzxuAq/ldl+LOyql0R9Coos8+wVx6ehCLODsQLq+mwJIxbBc6Y91r54Pmjtk+Y4FNysLOvS1uvgRvuNJ+vz7ZJ5IB4wtFPUKGBFdUue7x9ov4GR67wHWnRARvnpgKGuvoA4ktupLXAsF6zzfgI2z/+aN6cxtUYR7yrGnxABPAA0LlWZnl6NCaGrOTNo/e8chbD+uoayVHUhQY0t4xbFedwHIEeB1c98i56SRbCqc07TpPKOV1w+DmmUvHWunUWfWMSAZs5hu5CipKSyvawnCLaHoEcvpx1nynffspzikgMeYdacxGKzR0UshySv7XWyV8ruPgjjCv7hc7hu/+ixAFKZql36Gl/uObNfSzIWjJ0qKWxzHiCQEfpkT37x9EBpLDZn426GsHix+UCH6Zucyoby4UveM+q24mi/JgBaokGcyItQHuJiTuD5fot+6bEowu4bm98R05aDjfDf3vdO3/W/31J4yYKPMvTf1z67A+pBRIfzNjDBpI8i5zXZoo5Y/urRGt6FdxT1ww1NzpkL5ebz9kbEpRqnJuHYs2JMqrsTPlQdJ25O6sPgHrU+XJPmehN1bKu09v6ThbUelVEn2+TROvzyemoPRzqjmE5BLfMjFrffnnTX4M09rNI2UhXivdDTmnFHZ5hdpZfVjhYFnPJaHwfNOSa9TQ/6zPwii1WcuxelD3JldTnZxx2k6BFsSo3g2qNefcpHBJTS9Nddu1qHAdbJLlHusc+go/yZ93h5mQdzSnO2NfNAv+cX7Liz4PP1Vj9SJiBmlNbowJxyoYF4ji0EQ/OxDvt/iLoQsdDXb5qN7YDecfdsULXY5uTdjmDlwkhvAYrCs0VHTEfPG7o8GxZna0GAK3dIFUzxMhL+ZjagMyq+YUrDe+nRzHOzGQqX87Oxv8/7WW8+uSY3URRQR0P3/gL7YyK2HsHrYR3ENMXg76a3M/pLFB6y95q7u57pJrceNed3W9j7cR5JTci34cNsfQ0VOnW8JcEjrKvve4wA97AedTUBPAjo2Uz7n6UWswbC3hv8Ffzld7SsAEdJW54uqQvUharR1vyp48RLrIv8Y51xtoQ0nfY+i65Ii09zm6LC5WR+/YV2i3Os3VKgDmBjuT/btDvi0tP82288vffR77Q5OToVRLUXfpXDd4FXzct79h4ZhXuy3tIlxPc+U1Oe6Ly6R6cKWRG58jTM+Epql2Dy79tpU+LCJon7A3UhglHlpJlT3tfVGbFyncm+Vfb4e9lTqhDRhqVo5CyWeRrMBhyHKAmBvzjeQp7Qur5c2Gsr9gYibiVTGnYijMAL5iigyndDt2tZoXolOmy908k9PfOWd4TAnXdTcYssoT4bI4C6jiIyZlf+WyxrjdvEBRxZ47+qkj49/wV3fYlpsgE1pzfPwvLDOMIeTr6sw6b22Wtir9LZUVY9OA46NZ7yzqMRDaolYIeH2MMEK1QwIrCVZrQi5NBi4Wy+ghVs4s6x0/W7gimFK7PV/Vjo2bhA2nNLcnrHvddey/k2JD0aG0TvNRYKuzr4fsXb4I92d08VNJ83zfcxeZJgzt2FOvbwLj66R56Rdy/ITKpAUNzYQXBSGyVdPiEPv5Lz8YvyAFIB+BySjXerb6jtdFsqbGRgXOn61kAlBZtADzAbi9en7mB1O0fBcFBW9En/rZ+dUkzd2pOokdXWDT7dKK604QFdcALFCnwEGlSljypU253yKMGoSYaD7E5vtjuhPxLXggq8ZP4yx0mll57VCHEgYjO/z5HzpoXbUzOtaBHsSFyEiecbHdHjlJGDHPh3sz20YyFu7bZLs6p8uKXD0wo3+wm+afkOm1zTH4sGCS1PwdekdknHLCK6PlPZRQ83n2ra6dLPvK66b1zPPvOwqrpf7OE1ieNg/WKRqmfUjViBNnaftpYnQ+wNq6Q0I75r/UfwarBoru3Xm59xRLupCGTRLqJSYEVRsyUOYBfOjhb3fAKvZJS1HSgexvQCD4b4kwCNToTdmpGBAYoPBsDJw1yZpto6eyXLO1Ad5sKmHUvlUFZHxL1tQghNCcSEVP9k/LLAwnHAV/XNPpFlvOGHtFolYSuI9t2s+EVioXLD7X+tlJHVQ+hrnGrJprvSVhjR+JJ/N1jPr6eBhbYzp55GG6C0svmhoxXDqFsG4LRhqTgHCxuajsMHOJc0uWuKKRjVWm5miIOx5qe140OgJ5mXYJv+3VJjrm4XnjppRhNeKM46Om2ovlgkqoJCMRxI4ct+AZtBCnF4NGLg40kYJpKZOSaOyuj2A6gB3G+sCOi2dKOPr6u5WseLFfy9u5fg01Z3G1MiXZIM5E7Ny0Ecos63ofyGYbSm0VXYknBsQt5XuKsgMLHlHcNZaaOpni7sn63hNI7JDsvCdQw191stL01hEL3VtmNOtfKPZXlOdaP6V2M2p933eApLCpV2VJ3eMDpB5z1WTVp0XQxDOD9IThDLKnt/AbhMC81ROklyp3sxTZY+AjHITkWdDGOFmY/zwjs9M2UuwEt8eo/4HkIqKDfK4u0y1jKf5NHzwf25hn7xAo8uvZR8ZSOpO1YNi3ecp9qUgesyY0acxY2Y5F0+Kyx9Mhfc4YetYL1Wtkr83SaFCxMjsMx5VOVNrb2q0IPJTYDY3iy2ElWlrDLKH1HNzUz3QsyH1h8csmblz2PbReHR4lUbwqfkNixNMkh752xNd4qA8CSKjK3shHle4vW44ewJQyaOLfevF9/+JkVrjbWjqdm5N4dCBQhNlfD43EHUuGTQVisbmokikapHE7lZZM1WXjT6hnvR2pnivV09GfaKxyruvFu40UZfIeD+ChXzDMcjom5knRLmB5njjpizlXiZw8cZoXy8QFNu0CtSxkP3b0VkJ8vrq5tJXfIOYO7Uc4FSIQKPig2LyYMXXuaOPPOkkwXxqo16ZFgdpBbqe3/uRciVgaxvYNrhdU0YZZj0DGsZlWgS3ClpRqO7Ka3AIZzzWJaSt5uh/YdXQtNqN9zUuSmfJkjLZ9s+Ojdw6BvJbC5y+Ia/MWOSfqxLTYZUMD5r2S0YLzF6nBGeIbZtzUKIdJ6X0Nq9N1l+2UdUJ9yvmFHfUBjUddRZWiVzIAQQ4rk0WFayHfA36dyr34wp1O8mD6rex+BHDRHPc2wwKEk3wBb2QwtLAJ21tANH//ZRhB4MM8lBLMxO5Ya90r4zXgp+buYuj0lFKz6/IowjvHY9M+fBpAVkrQi6AEPq5z6YtTC8HU1kcJ4Cmts8sacl9fsv8jvexuA0x6c0YTJq68oDgESfrcbEdDXkU1m/XxMUSVPxHGAxyhksELbfRsWRXrgOMUEGSlGC7gf0XnK25M3VdEAlKhKVIo5Qbg1Z0UllwrlAfG0IM+Br3VAghzIQJFDuycdNAjuArIo61U7iBd1veOBBch7g7nzwdbYqOhvPqmTz84pzRp/3yuEWYLkcCwph7YiAaBUh7yRwumxJQkDTk3qBIVh5M04PAXfFDFN0wekGEZ7qzv9JbNKxPl59al+hxrMnfGvvyuhVo9PvPKHa5xJCU22BNfB7LfKWo/OxxhKDVWDruNivz46/cSJcM5iaNPlwyU1hl8s8OXLJMzHSmZajkEDJWk+G677zHD0/2G+bdArdTHchQG2iE/EMq1mbD/so/Yf2T7U25Histn9DPnsi1/4Hq4/tUaPAUK8kEwTQSaWAtF+uf6hZtxoqtCtyGzpPcnxJX/yIthkJDqkhMA8YYPbbX7Uk1FrLEK4UiP758bu6lvuCRD6Y6u5e5HjODFV/RjGpoODKIVPIlVTNGXu9boaK/0wTmhS8LtXlUJfSZt5F/LDGzfDl7o9w7u3otf24DsQAEvvMBRKl7DqknUSuR0rjadxrnwzi2rbrOmMQ7VWGhcTaV8LnKh7owpAAeDdxH8X/Kg7BIvez9rjKiVQYSAV1SqEwUdOrEkaOnqIV2xnwYCETfuykoeNDJQ1M/GaVr2eNgYB0fAjHJdTYtVMEFLXJMJyxSYk95/RHNDMr862I+dHnhSJg5u13fACXricKsHZOg0gxMHgTs9pfieBGxQtG9+2JVK1ws8W73aKjVL2WYTysE7eh4j/J01nPjayRt6rNdkYePf2qhDi6mLc0Z1L7m6LlA5opzDpX3Fh/586k9XdEgizZ6OIC+/emHAdNteSzwBv6P73tXqZk9PsekA2/MYIKZoRVbBOi8C270WJNPA6lRBItyGrIUz/QZiyMTFg73NcX5lskk5AbiO2+0LfR2UCKVxM5dvzE4dYPLk0if6Zvl4uHBI0ayIVN9hi6IZIExsrER+91DqzalZM/AHSa6pl44qtk7o8+yGSJJG8i5TjgdPn7sq+LrXkJ7QJfa1YHGB7y2Q8bIvm+A4MdqDx535vWgNRQ+iYeRtdq0jtxQdJZspFas0ceaOJKYNByPLRIBXB7rBwusEmEdkAN0xMUAN/iO1T0B/A2WL4XZxbmaaEa03CJHf26gyJS/ARnDJLVgfP13EIwXVjD6vMrqC6x2dCpBEkcn48cLyd9wEskylfklEDAi6TLdwTyO/VGxvimdF42MkF5sdly4Ui/4xbjIHY3tNyXmagjJVvtKJnTlwEQT+tiHo1i83z84q9tgwnkL+3BAk+G66xcRmTAHBNfYhu8kBpb/gMeVIt/z2Gpe3tqlUCFyKvlebC+a0+7V1pRhBAgbFb1NmM++EPjEC8fFbilLbgbq9HKDm0Fqcrz3qewh8bAy93ZuAVQusnakUGKherN+tgw9WEcgfLI7lvbdAz37m4fyabustXMK+Zb6PYpF+X6P3n9hf1cZalh9RNytC22TFIksG6j2ZcbBKLF2wf6d8Y083BNceeE0ADW0vc5lEFmgx5AuaZHOUHzKIDX5Y8OXfevibnnmhlCtNjuRVPx1oR+ZD8LYhjv7KWlz+wiLkkKZnB0Hvy+GspSaFsMG6pO6m6vWZ8T14l3mkhe6oV8EO95Rxe2s5kIkq/hCzrKefc2K+GvXJ/aEmwU9OtN1YBS89QICIq8t/OMvx2CjN/Nd5aewc47mZBW2ashKiLute+2/0dJt/8JKG+SxGWHxtkDa7EPSwc4ZZjpoPF0MhXMB3PgbvoZWARegOihW7c6BvHFsxLQS+AjqYVxAYvcnx2NE2y8KS4EkTn/pKaIryG6mAvrAolpnXjVPBFTQU9PaYFlMJ1tQc1ZrUH3Yev4GP,iv:DEzZocX7nChUd6L9v3iqEeMcxWCZY+kbUnDLbikBVe8=,tag:ya/g5UxFYI7LJuiqbc7wPQ==,type:str] - masterkey: ENC[AES256_GCM,data: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,iv:G85YO9nGE6ABZS5LPEBhyaiU/Zei19H3ImERCjk8hQY=,tag:k7docmRD/3anaMDrzKuSpw==,type:str] + password: ENC[AES256_GCM,data:MrmA++fEUNNJojl9xAHlaWjhMrpAWjqi2X+6x2dWd1NZU7gDpLR16hDwyj3cfTsK,iv:iVN0pOx4/VrlcUxeHtMuavM/Z0/iZSGE+oY3idCKjtU=,tag:QiWT1xT8ntcyAjOU5SQLGA==,type:str] + keypair: ENC[AES256_GCM,data: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,iv:pxhCdbDA0jZLRFLg/2cXy9j18nvWOgIHMHrgkAfYSbo=,tag:4Z73qrehEkiLca2HO1MhKA==,type:str] + masterkey: ENC[AES256_GCM,data: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,iv:TZrIcQKmo2UtO0MdBSWJZmn0nIZ0cjStD0SZLoiHkT0=,tag:D0qeJLtY0cwA2yDdCP3UYA==,type:str] +zammad_secret: ENC[AES256_GCM,data:Ok01cE+lgNaN0+wLZuBD6k2gsyTWDFVXEPprEvdwlIAQvwqYu2nou0GiCEcm/NF2cgsxERH2rYxxS/lPXIQxXjvHHLfovLSMH+Kd1F/T+qWZioDz7tzDV3GBom52c92kZ4XO2F3udku8IQLGsR7J6eA/xY7yj1g2CF7Vt37BMkg=,iv:5cdEBtgjXoJCve8PJDUcLQvXwe7sn/mgZIOUhzJtr/c=,tag:4fLmvfG6Ujcb5J3YGjP7Hg==,type:str] +hyperilo_htaccess: ENC[AES256_GCM,data:FuHR9S6FhVyraJ6w9j6RTUryCqgVrhpfQg9y2OdnaqMFNcIR239OBmvqn+WlgFxcMqJtpIKe8ixBZq67pjxbSl2p,iv:zKMyhEJ160MN3+54csuurMXvIAFfWG95bv/cIH3hqJo=,tag:Nr0G7qx8cdpNoW3t5P1CBA==,type:str] sops: - kms: [] - gcp_kms: [] - azure_kv: [] - hc_vault: [] age: + - recipient: age1x76ajqw8w4l5vlkwt5s3flz5a5jq5qlxv7uppmnf8ckj9egh9ekqjclzt6 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwcEFnOE93NGtwWGdlY1dB + Ti9ZQjVSc0VyY05DbE9iZkQ3bGVCQ1FlSEN3CjF3NUZHR01Lbm90SC9qWmFUMjBM + TTNoWGtlYnZMOHZRMEhEbVQ3d3pINTQKLS0tIHZnN2REdnlmTWI0aGc1K29jaTNW + b2NHTjV3b2xjOUxIam55WGFMM1N4WkEKibrW+oTxXWEkdWLcQA71u4zW0I42MV8V + IoQTPOJ0sfnKL1d9LflQ5aClC0sdXe97MZKoq5HV7ZPeL3IIYPuW6Q== + -----END AGE ENCRYPTED FILE----- - recipient: age1wvdnprpnq2rcc4se3zpx2p267n0apxg2jucvlm93e3pfj439ephqh2506t enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVUXlpV1lkOHd4bGs4MHZv - VzhCSmEra1h2ZnhFRElqdU5UMUJ4QkNoMHpFCjB5aFBvcGVWN1BFMS8xVHFsUTk2 - cWZza2p3ZmRRSCtWdHhEOUZSSC9JSmcKLS0tIEpBdGplUngzcnNBdHB3M2pBaXls - dFpScGZzYlFQZWMyUEErOVhVVjc4SlkK3KUct/NJwDdeGeWrqbZ5eAIb/G8f/ZCI - T4gO0Y/fznXkNf1fm5d3JHwTC8yAzxmSSGu2f/LLzKx1oNeAw0Ll4Q== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRdTBXa2wyZWIzQkMxQVg5 + MjRLVWZwNzVXRGg0cU5lcjlWbllqdWtjdnpNCk1SYnlCcUNKampzYU12ZlE0MHRQ + WHYvcForelFWMGVXWXJaOEFmY3I3cUkKLS0tIGlJaHR0STMzRklDbVE2THVlczBr + MWM0M3FvbjUzL3p3ZU1zUG94ckV3ZTAKUOAkZ8nlvT36cyPy5USyDzoIG569N818 + tMM5aQsEQ9vTOaUoK4gtBEXBva7VerMprdcTRYLcSJ/9L1vXdlVT/g== -----END AGE ENCRYPTED FILE----- - lastmodified: "2023-09-04T06:55:01Z" - mac: ENC[AES256_GCM,data:CvdFvN0usYbFG+W6gTXEfoX3vOhKbXkAC0gy9k26zaywPeVNcUaCpkItAp32PL/9r60ZOUplrsUWd0HlOsCvYplS9wrSmSQomkoUjAw5vJFNUT+9Ci6r4T1dRAJnijNvSr5flCv0+Gu6KLBuDuVeS3zXj5HHOOtibrrt+1j7EhM=,iv:bwL9mW23jwfp4jcnuhT2iG4qyCNyfS42B2P3uuX2U0U=,tag:AdxTPlUAPSND9+ysG8O7Mw==,type:str] + lastmodified: "2025-04-15T12:57:41Z" + mac: ENC[AES256_GCM,data:NKpGBhz9WFt9xbcbIZ+S8fkgbhfOk4g+5vhXSYPz5tVF/uLDjI4+T1nzy1yKVJA+9MGgQ5OHXgQ7kszrXHgn8fm+sG++MUEXJILcX840Poo9wRBhvDxtNL/oLFbSHsQ0FDe9oCcx+/T8Rmg7vYWARlokKDsXZ7wsTYjF9GkBivQ=,iv:SKVBvdyT3cRTfXuenLDEgk0yJJltwIBShZOkrDfnI10=,tag:58eNQ5k5hTUBTr/nwJULug==,type:str] pgp: - - created_at: "2023-08-14T09:07:55Z" - enc: | + - created_at: "2025-03-07T23:03:16Z" + enc: |- -----BEGIN PGP MESSAGE----- - hF4DntlvaG5T7wcSAQdAd35Nytx4deWRNHb5IOjf+DRVCvYq4C1PsINL6snAk2Qw - C24cIS+h7nBFCy0zOiXsFbbKBdIdqUXWTOF+8GLXUlKQpbcWodlWKVxQidw4S3CJ - 0l4B2ycQM2NFEEVaPbi6urnjw5qTAo8UNXNHXrZThVURihhdh+Bi5mjyiKXaXj3B - lrgbuCdYstsnewRCP0BIFcwjKZ5Ou+bmp98nwxorN4VMv2q13R+2pEc8f7Vi0s4b - =Ldji + hF4DntlvaG5T7wcSAQdAoaGQG1W4yMq0MxUwvYIrxwdzKKBHJgv9hLCPvSyJwBEw + f177FgAT9PQW69wM2x3QZm4+HsozWqs3k7SlMRsRy0he0fAtdkGUr0EL0DCFi5ml + 0lwBJxkI/R2CI08fRqkS0GuM+6HiV6BRypVy15C1oXEhxlE/MhnCYlP/0MeHbQ7H + MkStwmbVqvOm8aizboD0EePZpHC0M+61ULgMt9HnzWzQ/ue/YepI1dPfEWBQ1g== + =etd/ -----END PGP MESSAGE----- fp: B8E1727497FC48AA14158BDF947F769D7B95EC2B - - created_at: "2023-08-14T09:07:55Z" - enc: | + - created_at: "2025-03-07T23:03:16Z" + enc: |- -----BEGIN PGP MESSAGE----- - hQIMA/YLzOYaRIJJARAA1WiV3O66jKhz2CpOq/uow4ywrQmQ318d1CFHUrz5KPy6 - eH9V8Ry93UF1NlLOLTGCoUcqF5k9E3Et8P3asn7rg8YeB0y25FmqmjBGL1nEmnFR - KTtHYgdGpy8SKds4HhWVZBagL6NRW9oQ9Tjcw3bAVNL+QnKDqoTZ74l9FH8KHHj3 - 66/oCp7733d88JjTEFOLIrUOzFIcVOEvLjkqSt2PYfYQhvG5Vm74/0cEM1lI1lyq - drA4VDrQgsEkX/NKxI7kJrJ2liDXHMJgMoa/2Op0/T7AZgNJd07BrNSVUElyWRsq - HESSZACOTbx8iKL1dvTF4dEjOKrgigsi1eA3YIgcNbgBVN/+jrrUfvZS75BziYfh - twM8Yy82bp6T3+LP5OD4UG+PlVV4puLwbhGhb7BKfYYclutjjA3aiS0JZnRA8FEB - +qOehgy6DWURvNLRkOiThZLGvQRJXsTPjh7+S9gwl2sauNoenNb8HxI8ukcO99tk - UOLmEwcM0Pojvwk1KPzEl7QjsbsXUp6wfrBky8nvOApiSKo9u5Gw1noBTLr+eOmt - g20c41JJ1CiibQGhOWY+EIUQImM1jJdUDrQoTEYKXu0sh2Obv71aCsNtJuirNi6D - nexdRm+9PYSaDoTLqDo1xGP6qBZZF3qeFZ06tMARDovmPD+V5xHvCCQftPPceznS - XgGPKXd/2QSiCEnlYLP5cV0uFu7saRSn/Ez+1WQA6uGK+lMfuSGCCVs10CRwArS8 - UGO5QYgW8Kbp9D/0PoWWJ68Y3DndUA6gzs434Wbj8mqp7DTNuN6awElQdznXxEw= - =OYP/ + hQIMA/YLzOYaRIJJARAA22jsmHM0HtkFMMH2p4jQn9E1n7eYGwnnD51CxdwrYI2a + 6xIVwCkSNlIqzGH8RysaPdXth2KCyGUR7Ll9KRO3wIKAnpY7lIDpI8LLz/ad8+ez + jnw09oVN0Hiob8Std79pVX2qGZpKwjJ1r8u/+QDhJpY+PkgGU/e8fIYYxb8P4SMJ + aWdh9tCL2/z7UDKQk0AjxEKbFrATfVBNYkyI0d+QlXJVsUukaQ99KBtTABboNFW/ + BYaAqJaJoGkJLvQQ23NnsKZDhZ7eD4S1WTUyJG2C/lBSu7e1t9lftmyv4MekeE5B + wo+9G3hGzUayXWQ3W28QnvGJO8hqDkwBzyAzN2532UDymqsUZr4uHsuE9JwEg171 + x5kxpd4UL5WTcj8LTM12tDLzTyW0exUIiM0mP9U+F8dUkRCH5fqmu5peCb18Con2 + pDDHhhrqd5cxIHFqFawPufRtw8N88fLSzgGcHYq98bP83/SqIzpRDxWPayBRxL9v + 84oPPRbRp4WsWlzqBY/D3lhE/YM/rAc+BleWM5Asmf3yVkhfr4rLW0cD8SL255Rh + PTFEsfhaNG4RN0Syt2toM6oiKEvO66akijWXhNbKKhr4UjoezNxr9XRi4DIHrwf7 + HyEv82mN03C4YhiQTARs+UHC1g3LPjOUMyaQuntZruEpQJN+UE3K+Uxldlt9tGPS + XAG10G4sLXfeeOEt/HFVe3jf31pAMbNGozEl253oZ06EZdbjqMvnPcREm4qFYsJ3 + CtF0ReA5W6/vLFwusIR4T64tV7w9vdH7JH0VFisZgb4fZqohbZSRGABbCkib + =USB6 -----END PGP MESSAGE----- fp: 91EBE87016391323642A6803B966009D57E69CC6 - - created_at: "2023-08-14T09:07:55Z" - enc: | + - created_at: "2025-03-07T23:03:16Z" + enc: |- -----BEGIN PGP MESSAGE----- - hQIMA8uqUsBLHj6XAQ/9GYctx6xUG2+i2RHYhTQIytBpLCiEte8zvfLcRM7k4fp9 - OBo1Rne4VI/TJo7nZP8HBNlD3clLWCbi+O2Xz86ACUaImiDX1wKeI7h5Im1mNFOi - /hlKCjnYOt57gic7THt/xtFWfl1QdZ6klgBKK2eAx0sSl8HfpmozHkb2NVo1CPYV - rPGBi/bpACyITyt0AW5413b3Ltt1kTfdsSH8myBzobiA8xJqDRbcidtw+9WVXp71 - AbJzUgXELzZqjcMg/8XZ0rEK/nBMIi4yE7t4lVbNLH32ECLGZvaEB9hqCqOUPcGC - VB+fPCYZBbzMuyyFeil6eX0lI9PiLHKNMalMvHz/YR+7okZ+E6N5yHP1E6FSS3ds - +IUE47S9bV+mgC7UxHR7rzvu2Sw4ZOuJaaWHEuG/oipOxMxcvLR+KRy7lWynSykp - iP0bv85uHeUq4waJ4U9wqWUu3zUXGbpkr2vchSoQP8KohGsU6mJUkwcgssQzG8Et - 4oNOPw4X/QGn1Sp2zZBV2/b584VW8KA+StyYTeDuW06yCYTzehIwngqcr2AAv6zk - 8TmlqI7kTTcmPiOe9YgjqMKP8nsYI/xyXb1Rk/X72oh7UKha6x+sD6yWnjBMuiG0 - XMvXROVl1NkA5fbdym1cW7su7LEBKpwl1a70djE/afl1DJVYQZdX8cR7aQRMa+HU - aAEJAhAqALQJDkMiTz2kmMw7WWrPENzgAflQ7d6cuuwZ7OLPwCqv6/Wb9yogOvJ4 - ws8j97f3BPdgUg4KSqHEqIvOg0Ccn9CrGgzEReMJTHNwltmkJzlvIyJSp5F33y0+ - /DtN0Yj/UUpA - =KgiM + hQIMA8uqUsBLHj6XARAAmpdUg8/6iT+S5GHFGUdnI35UyEPOx7h6gjvvSWRDGbY/ + 05CTwj1JBi02FLiiKO0hPus5HAWgMhL6Vi0K//y6soKFhV0lC26s1nJFG/AWrHa1 + yQiuvcRTsj4fn1S9GruEaj2nn6579+aYCBRnM2SGEE8Us1oFkkuBXsEgzObHDsZ6 + 2trnlFJV8m7Uu7QOLN4/ghCB0A//2TqoV9qHneAyPucL3pP+HBaoLtoc1DzgrZBL + S+SngFUBIjiM0sRyAngAORpQYJmsW95zKBBE9Q+CB+VRy6Yxnz1yAruwODQCEyY+ + bq+yXhWDnyrAAvdgi6ju75eQ7nZvoZXh7hPfFKFjYHQVY2zSuMIkU37IPtL/R5z8 + Y8xnI3hOlmQ48IcjXr6jwgK0hR756aJ//XVUesQ4VTlA/YnaifSquakZ3iwmOpR3 + PmNceArxMqpN4FRxlBVDomEt2D9MOhzyxKd/Cs6sCO3uV3k3YFDsV5+oHt5phuuA + fBApR1Y80M+duGzujM2QCqTWx7Yi+I6LBcfv6P/ya4W3gdDjOZ0fkGqF6H9mcI20 + rDOIMcu0pA9hA8H3FzG9xABsGQtKEFzhd4ylMSHLeFU3byUo9f19R3+0rL6eHZMW + 2kbIhn8dmAeBc2Uygkma1Ru2NiM2ZpHFm3q8YPkolOShE4X8g85pTN6GnhD3FHjS + XAGv1hzCc+R+PjGNvtEcb/fcejiQ/fV8ps6RO6GQHrNnRiu8bb22KX1OaiAMjffH + hwv/rMTWI0TIBJSxPTolEF4JleD24QvIrQBBhEBXkiSJrcyBaj7evXueV+PQ + =cL+E -----END PGP MESSAGE----- fp: F8634A1CFF7D61608503A70B24363525EA0E8A99 - - created_at: "2023-08-14T09:07:55Z" + - created_at: "2025-03-07T23:03:16Z" enc: |- -----BEGIN PGP MESSAGE----- - wcFMAzUXo8ZPJwGLAQ//S2W6YlF3uMy5fohr7s374W+JG/uFB7fFfpUwaXis4wTY - y/ITUZ1CtyBsN6HT7iQsHwVN9bDzI1o7qbWkLgoSNNNh2AFT5fmWFZb3GoGPRiac - 1yVAGXX0V8+KaODGLXK48cIVPUFfwnpR4cw4eq6SnQyA77fYnCeUt9sxyn0KYbOH - SQ17FpbaYMk66KzOEqQhnN9GFCfnf+2e/7/jgimeG7mErlCT6FbkYePgdHQ2W2LO - ptSBelbuJUIg3gjzbhQHgYSmuMgwKZtRyy4Z8ELzmQorLChM0qlkLXXVAk755WuK - MmDnPiXrcB0QsUKn4mhuLA/IKR+FOuFP9nmnN8+sBcS0OaXXDYXrjqs3/dDyfXca - qyP1c3NMYkgHfevdXz2PNiq2d7l/pNBcfWKcUa7V6toA1n+UonjE4GhMl+Pr4Si5 - 6NWX38YmgCnnqGmixP+BrKufR8xyt7RZvNUkSlO+fP2rYpg9vuFVcsKF2wVP9w5z - bW7vcxPc8PYrTWi0p7DDFqfEZIxnG55hoIIy6RENbvFjKVDZQNX82SFi5hY+9yIX - JpW5Pf3liCwHQCxHN8dc3xH8bTmxZwbA4wZ04PMccGvtVL3IY+mboz6iVjwtvNen - 9nKVE9ad/ZAH2wejlk/zSz+3JOXjtCxLH71cV03NzuzaA61C3OazSJ9K109xZ8/S - UQH9XsM1jSbEzawuWk2bnFtaQ/fGGQU+0Ph6byeZLhiNRoBc6nNxiQ3BFV9tCrpD - IZBwIwwU+OtB1LNEWrs7wrD0NAgidKNBxZemLrnTUgrc0A== - =1eth + hQIMAzUXo8ZPJwGLARAAkDuS3LCJqk3fyqqE9orB++QWD1U+chUSQfe7RlBSp9O9 + 84bV5+RgWjVKmJGnr+8iYnAqr4AJRUsPw8d/4v6VOrQwOO0cPefGRBDI69eEqj3D + sJcCGdXrhrNaRj5oVtuqWP6zracmpt9mc8zpvJA0cQL7Ldt0YZnK2ohVYNe+obcd + twD5L/aVrLjvBl0J1KOHOoaJZilmv9dpbrjJzT6cFI6SbmD87IXVC7ME+sTfAXdw + jPrnKWUQ/6ww738EiKf3/rwgn0rIVnV53djy+FHXD8Ki+69TMYFXz8pZOI43jj4y + M4BR3PqaoisE0rXd5IbmuPDBelIXalpl5MwHnvlOErpTCmybJ1FyHEhNDHesoss/ + Kn41QTDeG07qBlbsgYOdA0K1+ZfGTctDllITjcJ21fBE4d3uMfUDo0EDSu5aZSCQ + Fz/YGPQQ2J8agv/HLpiruF8pGboG+d0SRfnka/ITlqRhG+x8xmyiMxybgPOfDV08 + neRB4Jl83zVfbBAdx+JBdW3p0twRWrLCUpUCh/L2z2RH8wVd5mijFH7aM7c2sayy + IPmIJYwg7cztM+bTeuNqywDSiNp8Z9HUxQd8QJOiG+1b3NdDswcaLWEIKhvkCQOp + cZGaqPXr3ec10Xxkk1y4PR/xPPvOgDZvONcnYLjS2yhHhNLDSiyDDel5grUqWT7S + XAG4pnmOC09sTOTCq+VID6qREFTYLMpN2sLVD2tmlU6pICifeLfWaX84vgDqouew + av7HX2HXExY9YdhEDEj8VnJAmSzkOI82YNQGFACCCbfMTK0B4EtW7KvR8Njv + =n6ef -----END PGP MESSAGE----- fp: 116987A8DD3F78FF8601BF4DB95E8FE6B11C4D09 - - created_at: "2023-08-14T09:07:55Z" - enc: | - -----BEGIN PGP MESSAGE----- - - hQIMA30JDs8MiK29AQ/9Gz9v/L97v6sxNyplvRuvAmSR6lXjRoBIWGYiX1pJonTf - LIs/X/6Jtjata3GXeMJ/XOnFvmHrkL0m0njayuuntiA/F+vaUTe9f5gHRdpcDCmr - LqAQqXh4KlknEUszqQb/5YG+gK+NnmQigmBucFRzYg47fm6WGXm4zYkQP2mgz0vR - LOlC1b7xrCt/Nt5NLYZjrxzZYf+UQ8zLutiOD+Y2jYElym5rmQdUP1wOxx4VWHJS - EMYkIgNX6q5Pnk6AkfFXLEQlNbym8ljdO6Nl9fKLU17NPddgUXPKv4aonN52QCwh - XRP+40FEa+cvImzgjycj/+V2CUDaDJmlCAckv5PrOLL8z7/v4Qrvev9gF6lhutZk - SecHblTxjFaYoNK+Ver3kklV7xE7BO0CykthnaKLBcu9ERfWohm0o4FZ0XMnxlDL - ExuEJ/8axaeS7hRVccMjcEyA4/ZbsyUWziE+jEJ7mNimKrTLK1XNjade3VRcsTy4 - m1lsfN/RDvCbJBrNHRQuInD212Qpc+durZnFdEf2A8ymTvVWlZoK/UtUSPEfbevf - UWOToP558fsCHXqgzula3cqfXLJuED+XiPaxdpfTCU7XCI9xaW1kGiUOa42+CPU4 - o/aGMvlEQJiegZ7A6J7Cl4Z04DUU4RTadLyIZZnFFdhEWKhB+SpgqywOxAbAoHHS - XgE5ZZfsZbP2XJ9t48pU0mTRrplg4NFu/pHxnDn6wTMDqDCvF+gqNJsmA5dNmFDD - XE19avAuDRd9JPkyhYDZD9CvxoIOlzsJfU24sR2wWqoNIFTDl0vG2txXJVz93D8= - =GZZY - -----END PGP MESSAGE----- - fp: BF37903AE6FD294C4C674EE24472A20091BFA792 - - created_at: "2023-08-14T09:07:55Z" + - created_at: "2025-03-07T23:03:16Z" enc: |- -----BEGIN PGP MESSAGE----- - wV4DNffZWjBmO5ASAQdArEfjFNtkwsa6Qz+RgLCqUa/3G38dx8CgynaUkvMsGUIw - 2UvO8PIbp5pfI+9pdisQO+0AXJMTxisUhSkNWYa64Ey3mlNmRDaH//Qhfb7RI+/i - 0lEBxRWqhmcNXRmmV7Y7EU4we3NLm73IN7HMNyxNZyzGirdJED1Ie0kPl0XJpOZs - WJVCpC6FJ3aivsYMfv7PL/aSt7tNg/TTjxMI8W6m7TmlV6k= - =dvRv + hQIMA30JDs8MiK29AQ/+IihR4yGJDJnDXqtggP3mfUIFajsUgNSdk1NHJ23MtM2k + hdvre0HaHKnJQprHmYPw/cbI5Rwogi+5xGU2sRsiHqBLZk1WEqgWcOeBMV/t8nc9 + p7M9LoKowaWpQ2S827+An6AemFa058Tj1pa4oXFzWC6jsl3RbB/IC0meyYJjl+Dk + gu556cVbpNRS0Z7wMmVJvBkErP6426hZBAHQcxaz3YZG9rqHZTCmd4PkzmuNVbU6 + iRF5b7Ov+IMmVd4OmCrs4sw7KrHahIu0g2U8V0smQphvV8MDKc6sMIyscT9FFYki + 6qmqCPhtTivTG1lTTCm9W+CIr2240VxpuwLiS9/OKke63gpSa3NJX+V9mZ+jMy43 + V1nUa3J45Sv1S3hvVpIsfqnd5xHCSB4w9X+YXJll0AEcMsI38gDQd4/stTAlYRIp + O2hygqMY8bjPdt9tS3AHmOMksNdD6vlO72N68ugALgcRYpq8chUhHiImKXKFI5yC + YFFBZhsM7r1N42ti1yDR5cBF1f0ZYIYCwUedJ6fLOZsG3nVWh/isho/b0vbnNK3P + JLBMW1w2fYpH8fIEDIYasaOF8Reg+yPh87tKA+M1THam8ek5B0pFs03HeYneXJs/ + geyYOYD43kHmg4bM7SgjOMlwVALz0tYorNpj/p8ojO3cBfIp1lKuegZss2iHImXS + XAFpEl60dqYeehT51t4/bjg7e8L0tkQf8/CwVATvMi6PxrPjwlN419fn22F9ZF+u + fRg4nX3ZMBTZAE8xhkQ5MVn6alLTHQu26Yal8bhqpD+VJ3JC5CpdUya3VMNK + =oelB -----END PGP MESSAGE----- - fp: B1A16011B86BACB56ADB713DB712039D23133661 - - created_at: "2023-08-14T09:07:55Z" - enc: | + fp: BF37903AE6FD294C4C674EE24472A20091BFA792 + - created_at: "2025-03-07T23:03:16Z" + enc: |- -----BEGIN PGP MESSAGE----- - hQIMA6MARpDCLIz2AQ//RwloWGHjB9zkZuDNqiqYqLT7L95ETHD3A0rEnLCmMHp2 - 0/FJVjpghzXeCUcTqCPGGvETy7xsjXAzbbrZgFFiCHj+L62WBO+h7YuMtZygBUY0 - nvoKyV7247HiL8PZlvJVXIChrypKgF2iTotgTvmB9rJWrZaxl+M8W7ce0DyORwXT - ZoWhfR501SWrvXGCe6hdH6+qBdWgUYlZJu/WhLZ6Ii0kQCeIJjC6lG+8fYFv9Hnq - mRMD+6piReFBehm0LSK806V64+NCHYkcFPXmoRXhZVQMtIbc4ONjOB/XMVk2sq11 - x/SRossZnQ7V7x4mP1chTLY3DWn+l1kHM/tD7Fm6xYxdA9FUrKhToEyM6uJ0GUVf - V+dx9lHvyCseRtgS1sje2SllTfP6i4tQtFBSlgOtKGP0JBVH9uNlYynIMeRF0ssD - P+k/IYaLCB3d85w4kG8093QqhR0urrOzy2XPRaAPE3CFJcxKWZ1pMIJRNjKqgP3f - zeuVtprUicb9j7pejcINodG/tQAwy1gTlKkzzgDRHlDzYz64dA7BOAHXL/C8PeQK - OrFGJ1+FvnmD6L/fnKr+p/dnHWq/M9OyKj2wPoiq3VZU3S6SAfORKmH1YbLNr+iP - ME+XDEXruZZC64Hk5wzkVT6081/NaHfyWfpguaJ87f5Ruto6mqu7A5Y6twIRsNDS - XgEmEktsdVD8egMQ3rnRqPuWo9F+Xa0sOjXuQEwxWAKtTIIHuZgkyLYVHJc/2ati - Ml6yr7uiXOwtUzbo1a/ocKbvcQg1Qi4X89/aGKyI5L3XCn6YPStmekeyvJRFSBE= - =9A7J + hF4DNffZWjBmO5ASAQdA07imap27d/V8R6oVOlXUxEYL8QJcTaSiBICEnBnfJnww + i69xnBOhGKwnWAgFipvXwFeyiQcmr+LnLbdXB5YGTblDzG46PCEH8JyeMakHpHAI + 0lwBHOOaak4roVNGoxmDedniFhdH0rmd8c9MtG00iT4Bc95fjM3eSFuTrESWPY9i + RUApyfYx9WJq5jZ+lFii3uOSQg/rMpVTIpjjXC3HyJTvfy+MnECBAI6+cAWsjQ== + =J26p -----END PGP MESSAGE----- - fp: A4F92BC7B792108A463995827C1F2DA2BC929412 + fp: B1A16011B86BACB56ADB713DB712039D23133661 + - created_at: "2025-03-07T23:03:16Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4Da5T//DC6DJkSAQdAkFwtDJxwbCFZ8EyxkK1R4v5Ntfy0QIzLpKk1CxXklnkw + GKQPVXU2qFH4UwH/58fKENIGTVHlDRXZa6gALeW6EBr3uQFoJ3d/APHpD4nprqOy + 0lwB45yH3YjdTG2YY4bI3eZKplK6R9mK/lzAVG7zV7nVs+glr6/1XpaeYJxiT1/K + p6aV8I+/FTg30d7Rfv2PpPaB31spmUxA3RDIbybzn2uygwOdKB0PQnnGLAOXBA== + =vuaK + -----END PGP MESSAGE----- + fp: FBBFAC260D9283D1EF2397DD3CA65E9DD6EB319D unencrypted_suffix: _unencrypted - version: 3.7.3 + version: 3.10.1 diff --git a/secrets/tomate.yaml b/secrets/tomate.yaml new file mode 100644 index 0000000..01caa04 --- /dev/null +++ b/secrets/tomate.yaml @@ -0,0 +1,162 @@ +portunus: + search-password: ENC[AES256_GCM,data:lUG8qGioYZOAQHRhDMCBq6rRRFOs9R4ohMHEctxi/f6soE4aQZHyENEW,iv:6wgDgre5wr630SkRlT2kHak4nnOkx3DVFbNcq4FehGw=,tag:S5EiXEsoId+pGYaQ8lq7JA==,type:str] +print: + smtp-password: ENC[AES256_GCM,data:XoaLiEpqAdKapeS9YoBfh2w7HFuTCV9rHIciH+qUbhHcdsgVpnPMsSlC,iv:WxfP5d2K9soJPoRPuS6O6PbNvo4TBQjPGiV0e+a501Q=,tag:ZsTdR+b/oYFAYz/MN73PFg==,type:str] +sssd: + env: ENC[AES256_GCM,data:9IbU7uaElmemQHVUvsM88hcyNl3WFehgQeLZPtUxt2Sd0IECm8qNkQhWJ4kuvoBnQsdsUrFm/0QuW7AfDFOeE7FxMxg0,iv:dyzsYHlqClWbfzsoJ36iYjaXWpidB1ZqHXI7RP7js2Y=,tag:97FMOeVwAEy8Ka79uZKC8Q==,type:str] +ifsr-apb-auth: ENC[AES256_GCM,data:hxJOvRbgjB//YU3wy04P7yrQbV0Ggoi18wQxwy4hHgbXizTHbmlfiZ/MstITrZQ6qEPVBEW41/iGU3DO2Cg2ofpWvFU5Gr8FM1AC9DKq8SppLGqzel1mEejPfrh4RbQUMe0zZlc/YfhCah5sM0oPnBQNg8bPpveEO+5/bRq5S24jkkv7w6/AAS8tGvjALVf/g95jsCrQO2MYg9jCCEkdhORU0bowGD8cjTr6wnPkNhwzn5tiKoPn6eH6TFBkqNC+Q/5E+os10i9F1c3z/sv8Snrcl7V5higqrQekhEvGRDmax/4lE8Yb3AoxC/2M4/+9x+OPi0JUkkhC6rghETXpmYkuaD7E8+eEtLeSbiJPlPijq2HTtbtsHcSoMUdoGO8644TVe/jDxaEe54p9OWEFjRRpONijQKsfH3wENlUXmqDQDLfMSpoANxIHMh+RmRzktGIvTgvs6rlKXsWp7/gggFVxdM/5QPbE3pUvGr+JPWz4,iv:6c1HxYGrItPwKzAnQ0zUvO3TSejVZ/aWF9zs99ufzl4=,tag:fELOskceJWKmkm74MCsfoA==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age18lwgjazaxujqgcc5j0gjllnykhtjn6p0q44jzrsk4au2a5k6nd9s77kd6d + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4bW5yM1o5SHNXZldjcWtO + NkxENWNqTlpVeXVRS0MvNFhCUnNlWmVDSkZJCi9KNiszcUZHTXl0WXdJMExtcGYw + WFZVNGJkZVRrdkNRV3llUEJjay83NmMKLS0tIEhWNGRkREJuYWhaamFWQ2lEZUo2 + TXVrMHZCNU5zOG5hVnNkdEoxcTZqWXMKA9eG1zM6HeLAAOpIo8Z5+5KD4Z5P3rdc + kE8sUXHD3d8SMmSKcTYe6gGVzFuw0xxnMb/AmjAQosvDFTQsWy1sTw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-04-16T08:58:21Z" + mac: ENC[AES256_GCM,data:2aOOVZK7kshJFBWphvW/BqRUXht4p80Q15nGJNA1EbjT05f3tYdrr8QuM5Xd1vJO07rgmokWv4XwbzodRIwqidEXD5xuJ1v+kHC/jJnO3yrBKY7kVMHkia2Wq00bcN/iwdW6G6AP5D4HQbmFNo+rLHyjIVwPvtu9jutKpz12NH0=,iv:YCBX2gSEmiUa6HrHi0VEcRGWDJrXGajD8ZbOZcppFnM=,tag:FK2E4hukl8oL5aZNTCQESA==,type:str] + pgp: + - created_at: "2024-02-29T15:23:28Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DntlvaG5T7wcSAQdAVYr0vThE6byTzCZiUrErtuouL9k2b3uTQKR3pnk1qmcw + Pw8+vdUOal5i/M9jFWexJzJ1nenzhIogFWry4FdXRX7V39/nRJQ1mbF3+3T/yldD + 0l4BdQ3xmtVUiz+PYCzazHC5+wPB4iCVs3fkTiLvNBNzUDEHvj6T7w72eKhld9VT + NFcOI2lSDea9EYksEdLef4VnE8gI1DeYxJAc60GXydmBJZO30xeOFMru+XE2N7Cy + =S7ex + -----END PGP MESSAGE----- + fp: B8E1727497FC48AA14158BDF947F769D7B95EC2B + - created_at: "2024-02-29T15:23:28Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA/YLzOYaRIJJARAA0fWU9NbHhvooG/4gYcadlwNPtQqOIw+6g/L9Gx8wKEhR + i9451S9oez3ElkwIeiF1YPCzokF6TuKv/++nV5SjC9PZVSHnrixrQscdN1FtMvH9 + ad2dC4GD69fXebq3f1vj77fAZxif6OMcEMpDiRRXHHJetzuUDkLpk0YSR/ZM23m/ + ag/JrHNUNgSJPLFRjvSNqX/DO/Etf/RfEwuMoPmwpGrQFhBTwtcIjjrJ2zT38q21 + PhWrjAL0Mxjnt1zFOGLLXwV5wkpmLOj2GGIBJJ+/B1zEawkbOx/ROuzPFKrDmrrh + xz29AVi7Ok9JanwgPGRNytnUHmxToisIH+FZqwpDTsop0ZQOCtiUWIZot+i8XGxs + rJhHTKxetJfsJCQUe4K2RJtHnVKIluzLDFyxoOb5SVmXoslY/EIQEYJz2lFPG2sc + PbP6XUh5ObZTK3IRIFqeQzjjLI1eaLdYjEOr+a4Do98Dd7+vJ1nLwkC9Wo7JLaaR + yd4emYpyB8R72Zf5+TPhN6ZWAL97OQdCZCSxyh3hDUZt4Wckg3I2yjw1mh56yVJF + fFOCOA/nXWpYXyRTbxuPuvCqjVsmVDEh+STZLIFsARzvz+yrlpEFoQw0G+Xa/XfO + aUt+HWGYji15+KVZJnSOXHhN4z4amsg8mtAEKfhCU7pl3jyrxa2MvArPBIU8FB/S + XgG8vs/FjyRkm+BvmHHEHmh8JkC9B9Lx1kmMpHw+fMis90IqZ52I82RmA6aO5jqR + ywlIrtvDLC/5STZaBdTt6EJwf3OAvRY+H1Br+SLtz9xXUxgzV9JOHWTefzRH2JQ= + =3Wnv + -----END PGP MESSAGE----- + fp: 91EBE87016391323642A6803B966009D57E69CC6 + - created_at: "2024-02-29T15:23:28Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA8uqUsBLHj6XAQ//SVU6B8zLxtpp1gQ/U+EGpgbP8N3IrIcUPrPVx72dIu+y + 7acCmdgralvEe/MLG4vNSnkrJdCCk7piBG2JFTMUFbqbFkUVSyZyG1yRsyezB3AZ + czSdffSQ0SbxWL73ANO7Z4asRwXkqjDTTKTl3xL3Iw8tDu22INeFwmcZPFV9F19J + K/BanSBuofUOiQB73BNv/8lA6ssxqufj+9pDDoutzF5XWpd8wUPn2hIcNWtr6NyY + wl9U/Jb/gkhnUR/UHGO2Nz5kAWz1lhysa/dur6I1mrxBJ0mO9I0j8A6U2cBPxdG5 + JBiTuKlFi4RhKUAraPDC+c3fM3Zp6zIOWhZgRNGlnR0Tu3fTeqdt7DwYh0bCOpJy + tTtj779hRj+cnleKG0QB89MY3XFpHQR60iBEMnqg522LLlTzLbvu6BEUvM/4jv+j + 2aq45zyYyIHC99k8xG9vl5Ou+3XhDqqVRUQ3qCRbavupWRKdibaNqjcaMr/zDqQ3 + TxmDluLnsbCGnyYmZDocwAqVvTVorHEr8yumjViFpXPImRe+na/0JCuxRHbBcVt+ + 9WynLgKy83rHY3tWKhqYobh20mLXNNcCiUvdGFYI2X/wyUmSRMkuNpT8fsvdr179 + BtERX0a3VpzaBV41pMsEIj7okx1MScMxXEmAktnDEQgyPBwV2CZpp2lM3YJajVjU + aAEJAhBKMkW8iDDTeG/ISzhGv3Qz4B2ujOvb22N1j/LVH6HUcq/Kg9tNJ3nDuT0v + zP1O6zxkwZsm23at68ZkfxXdBm6Qwf/sblfxYi2SOvWn+fXSmkSfGPVgw0vDG3+G + 0DskmbWWbRuD + =9+VA + -----END PGP MESSAGE----- + fp: F8634A1CFF7D61608503A70B24363525EA0E8A99 + - created_at: "2024-02-29T15:23:28Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAzUXo8ZPJwGLAQ/+MGbYqzJX74UDkNrAC1QUvA54pROBzoKnI45ODtT9gp/5 + 9Cv5Hx3d/1UA/IGjGh6Wjv7ljCjH335R47bWBDmnE4WmrD9O2gopjBqAuF/k/tIs + Vc4+8AD7F85PTSSdb1t/2hu/gYO/FAmwpwxLBmWD7iwAwpDZoPB3lBYwvqNOlnmX + 8cFYALyacBBMskwp5ydNEUtQO02ycHUfr3WVC3TponHva971Bsif2Lq4aQW2jCfm + 0a+RvO9cdv4RjVkd0/eKXnjpsFRkmggTAmXrlrer1hydENbdq9Fl9QHPxRG/jp6b + SjzqSEc38wbxX2zo9GihPWRHPNjXEJbXGWfwAA6MZpHpI16NEU98+B3OOsrFZ6D7 + Zr7BAhVqYXgriICx9K/czFN+oDp5Dpsy1/9NGhx2mg+KJXx6F66MN4ZB24u/rgTR + iC3YGoXfx9vq0tbv2m8zPOoJ3PjmmLzfSwXQszK/GOFvu89r57Hz92K4UpyFiLPf + jUoT7GDfEnU+4OFKdmBDzqFV2xm5TCnoCpjCfi+kbpszThoaF2L3ZvgypxK5K4cf + SkPoU2HgXwL79sXfFknajKKtBFcE55eLggtKmANoBN2NOf+yUQuqwnJRaN+ELtKp + 1HJ+ztoPEcrEG3zljNZ77/n8B8kprVA+E4sxzLrNHM+sRzoiDixq+nEB7p5F6+zS + XgH/wanI8NFYgP4w48mM50rboUeeadwGoju7XNNoEcaLzCaGWkoUWNbtH+NGnaAR + OGux0gslpa4mPnHWySU7b/1LZiIop9PyXCqGDyUzjBCaNKQypMMO3BhmvdHf0ug= + =oRNh + -----END PGP MESSAGE----- + fp: 116987A8DD3F78FF8601BF4DB95E8FE6B11C4D09 + - created_at: "2024-02-29T15:23:28Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA30JDs8MiK29AQ/+JcDqCXFj6/8NsrMx+mv92Xgqo5b8hQC92DxOEVd2kBrE + aqe7LPbhpm8ujuR5rRRNKmnJX1QQXn7GHAua8tA2+7oYVhVJfpIp1m3FlOkv6Jt0 + Mz2FMotFfts/Lq5MGUB2WU1fkXMcZ2J9gXZGoEwVRFFATu4lHy6IZKtbYHm8onlM + WXuhX3+uM1Tw4TCaqnyfi8fEGvocpwD1kT4Y2F7VipNVoSbP9DNf9rVIuKfTzLMX + NxueFmfUcLt3Z1/HSV40KkYseaZcLhWOtKbpFTwG/zdzdSIWzCjxPGwcK+nVBDeS + OhFdcoKC7c9GKb1bbxaPq5BwSpy29/PBv7SBM2vfUvyc9MrKvXdh1VzOgTkSAjdH + DxeEtFNMIhrCeCuMZwjBrIckSr3dFh73YqvEbSV/1Z2nK8qLBWKEy4noAOhI0Kxe + T05cCaGFHVJxy34lmb1AMHATLt6ZDDUn+kgiOD13SozMAsS9045MSnJgcVCb953/ + cxx5LfyN3KJO/17YFgNlq28yVavFTp5h5en/DexY35nvvACBi7uah5WQh8Y3fbB6 + 5Eb0t2FcsHY3L11tbjnVz16oFRE/SuS2NK+k20QEo36eBc272cKjkj9CS1w6D3lq + 7qFQCBD4NWITn1FgHDNfDVNZI3rocMMp8VgBzpknvBZmRc2PQlW1+jIt/7x+JP3S + XgFd5m3vvtbLhJVG5X0GMbFHC4QaBTou6buKdfvuQ8ZqUb8o52MPNXKmTDW99ywM + 5pItfzPtHZ7q8T+rZKEnNcL2TBhgfHsuFzqC06D2jeC/tulvbhw0VtBcnJzSlSg= + =ihPC + -----END PGP MESSAGE----- + fp: BF37903AE6FD294C4C674EE24472A20091BFA792 + - created_at: "2024-02-29T15:23:28Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DNffZWjBmO5ASAQdAD+Em/15kuzC0vIaYSkTGQS5SwwCGRmBc9V5u5ChsunAw + RiXIlOl3EhpR6qzxCfUgLSr+WEXK20AFGo8gEfCpKqAVE3orPGh4btwcV/AzZyID + 1GgBCQIQO4OYcDhulX1kReGuRHVJWLsjvWlUJQjlYPXPaS7QD6vCmie986wNEOAN + kqDyuSsoetM3OdZgTvyj0tmTdNNm9X90xKjyV+wcYKlAkVL82PbnEwIqQhlMoZv/ + 0Uhdu9hQ3VXC1Q== + =0iem + -----END PGP MESSAGE----- + fp: B1A16011B86BACB56ADB713DB712039D23133661 + - created_at: "2024-02-29T15:23:28Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA1tId/HHLgxAAQ/+P7hzNKzSA3JVSSAqfAV5umI1hACWf3ticSkT9tlfGYx6 + +xWvkwmtLBAumPYwIrVVvKSG2KBdiD/p0CugbpMUA2164IGrJVQsnBpeyV3fgaNQ + GMbb+Jq1Nfh5QsmI0X+D4xcNcPae3Ml+4TXtjXkDlowG2c4x7AHiHKnQj9Agszry + F+IUdlVt4dESbMGv+ck6fz6AqJ3OiQaesRps+FTrWtVhzuu9DIuup4E+nb7qaADz + knmjPfPxX7rSwfAVbvgmGZ0hRM4KaIqt26Fyd0pnnxc37KslgBcQDl2bIu214SKT + vmaSwqCOF1JXe3MAKJjFu0e1Rq+6/Dt9sZxWcXi+uKVqXaQznHXrxXywG8dmV2jZ + SS1rLoHKZ7Sk+3EG9WAfNA0SDNpcRQ11TXCXKYaNkbhsNucKBa3ipGO+l3ypFWNj + zmJMHR9mZuH/cV/DRC7eyWihbcYSAVfOuNYp61KUsW5Z4aYN/yrBZIDi8wqbN2J5 + TNI13Opj/3Xvu8mVC4fipORvwRpwlFX5hT1ioDZ/vmtgufWWPNSc7XEN6HIie3OY + 8nljJqPOhdYuTStejtBkt/qvqWWGlpPILCKndqTEFoMv5h7ussNV/+6eGUIx3+1Q + G1Hj0Dptw+w9dx/CAh6BVjSCF05892o8UNljOzr0mdxvZYfOrnrMjm2aqWLYO37S + XgGHuVKMpj8zFhIERSZj9q5ZZuH4f7AFgEzeRBghNZCGeMlA9T8BW1ctZ7v20wpL + q5F3s6h/Vpif4WrdcuVwxrsF5Sar08mJaVRQdJrps6hFENwy0qs0zn55gKIae/Q= + =HZ7i + -----END PGP MESSAGE----- + fp: FB44F0746DF25F0B24A2EAE586C8A257C3EC82AB + - created_at: "2024-02-29T15:23:28Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4Da5T//DC6DJkSAQdALa6lkOmkWCMYVZj7SE95wbejf6w18ouzh0NeKx1SeTEw + NoAN13YgKuk1b30zfSbjbr1LeGvk4xvDF+1nk+8dLccUPFQO8svT0/L2DhAQ8EV3 + 0l4Bf3h1T3Hoc28my9LvjvMo7brUGqX6TDRsZiLdOe/wk/EbnuGnTUCtHytxGUIy + dtQa263hpVrA1xRIxHyhHRKACp+4PD3SvmDpQ2u33bVfZ9F9vzRPGXvE6E3Rw8jD + =Dxdr + -----END PGP MESSAGE----- + fp: FBBFAC260D9283D1EF2397DD3CA65E9DD6EB319D + unencrypted_suffix: _unencrypted + version: 3.8.1