a dotfile but it's really big
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

cleanup pds module

karitham 5882f921 1aa46eeb

+18 -344
-5
modules/default.nix
··· 37 37 ${lib.getExe self'.packages.strands-agents-sops} skills --output-dir $out 38 38 ''; 39 39 }; 40 - checks = { 41 - pds-simple = pkgs.callPackage ./pds/pds-recovery-simple.nix { inherit (inputs) nixpkgs; }; 42 - pds-full = pkgs.callPackage ./pds/pds-recovery-full.nix { inherit (inputs) nixpkgs; }; 43 - }; 44 40 formatter = pkgs.nixfmt; 45 41 devShells.default = pkgs.mkShell { packages = with pkgs; [ sops ]; }; 46 42 }; ··· 89 85 dev = import ./dev/nixos.nix; 90 86 desktop = import ./desktop/nixos.nix; 91 87 multi-scrobbler = import ./services/multi-scrobbler.nix; 92 - pds = import ./pds/nixos.nix; 93 88 }; 94 89 }; 95 90 }
-66
modules/pds/nixos.nix
··· 1 - { 2 - config, 3 - lib, 4 - options, 5 - ... 6 - }: 7 - let 8 - inherit (lib) 9 - mkOption 10 - mkIf 11 - mkMerge 12 - mkEnableOption 13 - mkDefault 14 - types 15 - ; 16 - 17 - cfg = config.services.pds-with-backups; 18 - inherit (cfg) secretsFiles; 19 - in 20 - { 21 - options.services.pds-with-backups = { 22 - enable = mkEnableOption "Zero-Touch Recovery PDS with Litestream and S3 blob storage"; 23 - 24 - dataDir = mkOption { 25 - type = types.path; 26 - default = "/var/lib/pds"; 27 - description = "PDS data directory for SQLite databases."; 28 - }; 29 - 30 - secretsFiles = mkOption { 31 - type = types.listOf types.path; 32 - description = '' 33 - List of paths to secrets files in dotenv format. 34 - All files will be sourced to load credentials. 35 - Required variables: PDS_JWT_SECRET, PDS_ADMIN_PASSWORD, PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX, 36 - AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, S3_BUCKET. 37 - Optional: AWS_ENDPOINT_URL. 38 - ''; 39 - example = [ "/run/secrets/pds.env" ]; 40 - }; 41 - 42 - settings = mkOption { 43 - inherit (options.services.bluesky-pds.settings) type; 44 - default = { }; 45 - description = "Additional settings to pass to bluesky-pds:\n\n" ++ options.services.bluesky-pds.settings.description; 46 - example = { 47 - PDS_PORT = 3000; 48 - PDS_HOSTNAME = "hi.example.com"; 49 - }; 50 - }; 51 - }; 52 - 53 - config = mkIf cfg.enable { 54 - services.bluesky-pds = { 55 - enable = mkDefault true; 56 - settings = mkMerge [ 57 - { 58 - PDS_SQLITE_DISABLE_WAL_AUTO_CHECKPOINT = "true"; 59 - PDS_DATA_DIRECTORY = cfg.dataDir; 60 - } 61 - cfg.settings 62 - ]; 63 - environmentFiles = secretsFiles; 64 - }; 65 - }; 66 - }
-151
modules/pds/pds-recovery-full.nix
··· 1 - { nixpkgs, pkgs }: 2 - let 3 - _pkgs = import nixpkgs { 4 - config = { }; 5 - inherit (pkgs.stdenv.hostPlatform) system; 6 - overlays = [ (import ../overlays) ]; 7 - }; 8 - in 9 - _pkgs.testers.runNixOSTest { 10 - name = "pds-full"; 11 - meta.maintainers = [ ]; 12 - 13 - nodes.machine = 14 - { pkgs, ... }: 15 - { 16 - imports = [ ./nixos.nix ]; 17 - 18 - services.minio = { 19 - enable = true; 20 - rootCredentialsFile = "/tmp/minio-credentials"; 21 - }; 22 - 23 - systemd.tmpfiles.rules = [ 24 - "f /tmp/minio-credentials 0600 root root - MINIO_ROOT_USER=minioadmin\\nMINIO_ROOT_PASSWORD=minioadmin123" 25 - "f /run/secrets/s3.env 0600 pds pds - AWS_ACCESS_KEY_ID=minioadmin\\nAWS_SECRET_ACCESS_KEY=minioadmin123\\nAWS_ENDPOINT_URL=http://127.0.0.1:9000\\nS3_BUCKET=pds-test-bucket" 26 - "f /run/secrets/pds.env 0600 pds pds - PDS_JWT_SECRET=test-jwt-secret-for-full-testing\\nPDS_ADMIN_PASSWORD=test-admin-password\\nPDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=1111111111111111111111111111111111111111111111111111111111111111" 27 - ]; 28 - 29 - services.pds-with-backups = { 30 - enable = true; 31 - secretsFiles = [ 32 - "/run/secrets/pds.env" 33 - "/run/secrets/s3.env" 34 - ]; 35 - backupS3Prefix = "pds-replica"; 36 - settings = { 37 - PDS_HOSTNAME = "advanced.example.com"; 38 - }; 39 - }; 40 - 41 - environment.systemPackages = with pkgs; [ 42 - sqlite 43 - curl 44 - jq 45 - minio-client 46 - awscli2 47 - ]; 48 - }; 49 - 50 - testScript = '' 51 - import json 52 - 53 - machine.start() 54 - 55 - print("=== PDS Recovery Full Integration Test ===") 56 - 57 - print("\n--- Setting up MinIO ---") 58 - machine.wait_for_unit("minio.service") 59 - machine.wait_for_open_port(9000) 60 - 61 - machine.succeed("test -f /tmp/minio-credentials") 62 - machine.succeed("test -f /run/secrets/s3.env") 63 - machine.succeed("test -f /run/secrets/pds.env") 64 - 65 - machine.succeed("mc alias set local http://127.0.0.1:9000 minioadmin minioadmin123") 66 - machine.succeed("mc mb local/pds-test-bucket --ignore-existing") 67 - print(" [PASS] MinIO bucket created") 68 - 69 - print("\n--- Test 1: PDS Initialization ---") 70 - machine.succeed("systemctl start pds-restore") 71 - machine.wait_for_unit("pds-restore.service") 72 - 73 - machine.succeed("systemctl start bluesky-pds") 74 - machine.wait_for_unit("bluesky-pds.service") 75 - machine.wait_for_open_port(3000) 76 - 77 - health_response = machine.succeed("curl -s http://127.0.0.1:3000/xrpc/_health") 78 - try: 79 - health_data = json.loads(health_response) 80 - assert "version" in health_data or "status" in health_data, f"Unexpected health response: {health_response}" 81 - print(f" [PASS] PDS is running and healthy: {health_response}") 82 - except json.JSONDecodeError: 83 - assert health_response.strip() in ["", "OK"], f"Unexpected health response: {health_response}" 84 - print(" [PASS] PDS is running and healthy (empty response)") 85 - 86 - print("\n--- Test 2: Litestream replication ---") 87 - machine.wait_for_unit("litestream-pds.service") 88 - machine.succeed("systemctl status litestream-pds.service") 89 - print(" [PASS] Litestream service is running") 90 - 91 - print("\n--- Test 3: Database creation ---") 92 - pds_files = machine.succeed("ls -la /var/lib/pds/") 93 - print(f" Files in /var/lib/pds: {pds_files}") 94 - 95 - sqlite_files = machine.succeed("find /var/lib/pds -name '*.sqlite' 2>/dev/null || true") 96 - assert sqlite_files.strip() != "", f"No sqlite files found in /var/lib/pds. Output: {sqlite_files}" 97 - print(f" Found sqlite files: {sqlite_files.strip()}") 98 - print(" [PASS] Database files created") 99 - 100 - print("\n--- Test 4: Simulating disaster (data loss) ---") 101 - machine.succeed("systemctl stop bluesky-pds litestream-pds") 102 - 103 - machine.succeed("rm -rf /var/lib/pds/*") 104 - remaining = machine.succeed("find /var/lib/pds -name '*.sqlite' 2>/dev/null || true") 105 - assert remaining.strip() == "", "Should have no sqlite files after deletion" 106 - print(" [PASS] All data deleted - simulating complete server failure") 107 - 108 - print("\n--- Test 5: Automatic restore from S3 ---") 109 - restore_result = machine.succeed("pds-litestream-restore 2>&1") 110 - print(f" Restore output: {restore_result}") 111 - 112 - restored_sqlite = machine.succeed("find /var/lib/pds -name '*.sqlite' 2>/dev/null || true") 113 - assert restored_sqlite.strip() != "", "Expected databases to be restored from S3" 114 - print(f" Restored sqlite files: {restored_sqlite.strip()}") 115 - print(" [PASS] Databases restored from S3") 116 - 117 - print("\n--- Test 6: Data integrity verification ---") 118 - machine.succeed("systemctl start bluesky-pds") 119 - machine.wait_for_unit("bluesky-pds.service") 120 - machine.wait_for_open_port(3000) 121 - 122 - health_response2 = machine.succeed("curl -s http://127.0.0.1:3000/xrpc/_health") 123 - try: 124 - health_data2 = json.loads(health_response2) 125 - assert "version" in health_data2, f"Unexpected health response: {health_response2}" 126 - print(" [PASS] PDS is healthy after recovery") 127 - except json.JSONDecodeError: 128 - pass 129 - 130 - print("\n--- Test 7: Litestream resumption ---") 131 - machine.succeed("systemctl start litestream-pds") 132 - machine.wait_for_unit("litestream-pds.service") 133 - 134 - final_minio = machine.succeed("mc ls local/pds-test-bucket/pds-replica/ --recursive 2>/dev/null") 135 - assert ".sqlite" in final_minio, "Expected ongoing replication" 136 - print(" [PASS] Litestream resumed replication after recovery") 137 - 138 - print("\n--- Test 8: Health check service ---") 139 - machine.succeed("systemctl start pds-healthcheck") 140 - health_log = machine.succeed("journalctl -u pds-healthcheck.service -o cat 2>/dev/null || true") 141 - assert "All services healthy" in health_log, f"Expected health check message, got: {health_log}" 142 - print(" [PASS] Health check service working") 143 - 144 - print("\n" + "="*60) 145 - print("ALL FULL INTEGRATION TESTS PASSED") 146 - print("Zero-touch disaster recovery verified successfully") 147 - print("Data integrity maintained through backup/restore cycle") 148 - print("Multiple secrets files work correctly") 149 - print("="*60) 150 - ''; 151 - }
-113
modules/pds/pds-recovery-simple.nix
··· 1 - { nixpkgs, pkgs }: 2 - let 3 - _pkgs = import nixpkgs { 4 - config = { }; 5 - inherit (pkgs.stdenv.hostPlatform) system; 6 - overlays = [ (import ../overlays) ]; 7 - }; 8 - in 9 - _pkgs.testers.runNixOSTest { 10 - name = "pds-simple"; 11 - meta.maintainers = [ ]; 12 - 13 - nodes.machine = 14 - { pkgs, lib, ... }: 15 - { 16 - imports = [ ./nixos.nix ]; 17 - 18 - services.pds-with-backups = { 19 - enable = true; 20 - secretsFiles = [ 21 - "/run/secrets/pds.env" 22 - "/run/secrets/s3.env" 23 - ]; 24 - backupS3Prefix = "test-pds"; 25 - settings = { 26 - PDS_HOSTNAME = "example.com"; 27 - }; 28 - }; 29 - 30 - systemd.tmpfiles.rules = [ 31 - "f /run/secrets/pds.env 0644 pds pds - PDS_JWT_SECRET=test-jwt-secret\nPDS_ADMIN_PASSWORD=test-password\nPDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=0000000000000000000000000000000000000000000000000000000000000000" 32 - "f /run/secrets/s3.env 0644 pds pds - AWS_ACCESS_KEY_ID=test-key\nAWS_SECRET_ACCESS_KEY=test-secret\nAWS_ENDPOINT_URL=https://s3.test.example.com\nS3_BUCKET=test-bucket" 33 - ]; 34 - 35 - services.bluesky-pds.enable = true; 36 - systemd.services.bluesky-pds.serviceConfig.ExecStart = 37 - lib.mkForce "${pkgs.coreutils}/bin/echo 'PDS mocked for testing'"; 38 - 39 - environment.systemPackages = with pkgs; [ 40 - sqlite 41 - coreutils 42 - ]; 43 - }; 44 - 45 - testScript = '' 46 - machine.start() 47 - machine.wait_for_unit("multi-user.target") 48 - 49 - print("=== PDS Recovery Simple Configuration Tests ===") 50 - 51 - print("\n--- Test 1: Systemd service creation ---") 52 - services_to_check = [ 53 - "/etc/systemd/system/pds-restore.service", 54 - "/etc/systemd/system/litestream-pds.service", 55 - "/etc/systemd/system/pds-healthcheck.timer" 56 - ] 57 - 58 - for service in services_to_check: 59 - machine.succeed(f"test -f {service}") 60 - print(f" [PASS] {service} exists") 61 - 62 - print("\n--- Test 2: User and group creation ---") 63 - machine.succeed("getent passwd pds") 64 - machine.succeed("getent group pds") 65 - print(" [PASS] PDS user and group exist") 66 - 67 - print("\n--- Test 3: Directory creation ---") 68 - machine.succeed("test -d /var/lib/pds") 69 - machine.succeed("test -d /var/log/pds-backup") 70 - pds_dir_info = machine.succeed("stat -c '%U:%G %a' /var/lib/pds") 71 - assert "pds:pds" in pds_dir_info, f"Unexpected ownership: {pds_dir_info}" 72 - print(" [PASS] Directories created with correct permissions") 73 - 74 - print("\n--- Test 4: Secrets files ---") 75 - machine.succeed("test -f /run/secrets/pds.env") 76 - machine.succeed("test -f /run/secrets/s3.env") 77 - print(" [PASS] Secrets files exist") 78 - 79 - print("\n--- Test 5: Restore script availability ---") 80 - machine.succeed("which pds-litestream-restore") 81 - print(" [PASS] Restore script is available") 82 - 83 - print("\n--- Test 6: pds-restore service configuration ---") 84 - restore_config = machine.succeed("systemctl cat pds-restore.service") 85 - assert "Type=oneshot" in restore_config, "pds-restore should be oneshot" 86 - assert "RemainAfterExit=true" in restore_config, "pds-restore should remain after exit" 87 - assert "/run/secrets/pds.env" in restore_config, "Restore should use pds.env" 88 - assert "/run/secrets/s3.env" in restore_config, "Restore should use s3.env" 89 - print(" [PASS] pds-restore configured correctly") 90 - 91 - print("\n--- Test 7: litestream-pds service configuration ---") 92 - litestream_config = machine.succeed("systemctl cat litestream-pds.service") 93 - assert "User=pds" in litestream_config, "litestream should run as pds user" 94 - assert "Restart=on-failure" in litestream_config, "litestream should restart on failure" 95 - assert "/run/secrets/pds.env" in litestream_config, "Litestream should use pds.env" 96 - assert "/run/secrets/s3.env" in litestream_config, "Litestream should use s3.env" 97 - print(" [PASS] litestream-pds configured correctly") 98 - 99 - print("\n--- Test 8: PDS service dependencies ---") 100 - pds_config = machine.succeed("systemctl cat bluesky-pds.service") 101 - assert "pds-restore.service" in pds_config, "PDS should depend on restore service" 102 - print(" [PASS] PDS service correctly depends on restore") 103 - 104 - print("\n--- Test 9: Package dependencies ---") 105 - machine.succeed("which litestream") 106 - machine.succeed("which aws") 107 - print(" [PASS] Required packages are available") 108 - 109 - print("\n" + "="*60) 110 - print("ALL SIMPLE CONFIGURATION TESTS PASSED") 111 - print("="*60) 112 - ''; 113 - }
+18 -9
systems/reg/pds.nix
··· 1 - { config, self, ... }: 1 + { config, lib, ... }: 2 + let 3 + inherit (lib) 4 + mkMerge 5 + mkDefault 6 + ; 7 + in 2 8 { 3 9 imports = [ 4 - self.nixosModules.pds 5 10 ../../modules/services/acme-nginx.nix 6 11 ]; 7 12 ··· 19 24 }; 20 25 }; 21 26 22 - services.pds-with-backups = { 23 - enable = true; 24 - secretsFiles = [ config.sops.secrets.pds.path ]; 25 - settings = { 26 - PDS_HOSTNAME = "0xf.fr"; 27 - PDS_BLOBSTORE_DISK_LOCATION = null; 28 - }; 27 + services.bluesky-pds = { 28 + enable = mkDefault true; 29 + environmentFiles = [ config.sops.secrets.pds.path ]; 30 + settings = mkMerge [ 31 + { 32 + PDS_SQLITE_DISABLE_WAL_AUTO_CHECKPOINT = "true"; 33 + PDS_DATA_DIRECTORY = "/var/lib/pds"; 34 + PDS_HOSTNAME = "0xf.fr"; 35 + PDS_BLOBSTORE_DISK_LOCATION = null; 36 + } 37 + ]; 29 38 }; 30 39 31 40 services.acme-nginx = {