diff --git a/.github/actions/nix-install-ephemeral/action.yml b/.github/actions/nix-install-ephemeral/action.yml index 5dbdabe8e8..c999971e46 100644 --- a/.github/actions/nix-install-ephemeral/action.yml +++ b/.github/actions/nix-install-ephemeral/action.yml @@ -48,4 +48,6 @@ runs: substituters = https://cache.nixos.org https://nix-postgres-artifacts.s3.amazonaws.com trusted-public-keys = nix-postgres-artifacts:dGZlQOvKcNEjvT7QEAJbcV6b6uk7VF/hWMjhYleiaLI= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= ${{ inputs.push-to-cache == 'true' && 'post-build-hook = /etc/nix/upload-to-cache.sh' || '' }} + extra-experimental-features = auto-allocate-uids cgroups + auto-allocate-uids = true max-jobs = 4 diff --git a/ansible/playbook.yml b/ansible/playbook.yml index fbc3d5d81b..2e9a7d8ba1 100644 --- a/ansible/playbook.yml +++ b/ansible/playbook.yml @@ -146,7 +146,11 @@ tags: - install-supabase-internal when: debpkg_mode or nixpkg_mode - + + - name: deploy system-manager + import_tasks: tasks/setup-system-manager.yml + when: debpkg_mode or stage2_nix + - name: Enhance fail2ban import_tasks: tasks/setup-fail2ban.yml when: debpkg_mode or nixpkg_mode diff --git a/ansible/tasks/setup-nix.yml b/ansible/tasks/setup-nix.yml new file mode 100644 index 0000000000..9675677dd9 --- /dev/null +++ b/ansible/tasks/setup-nix.yml @@ -0,0 +1,11 @@ +--- +- name: Check if nix is installed + ansible.builtin.command: which nix + register: nix_installed + failed_when: nix_installed.rc != 0 + ignore_errors: true + +- name: Install nix + ansible.builtin.shell: curl --proto '=https' --tlsv1.2 -sSf -L https://artifacts.nixos.org/experimental-installer | sh -s -- install --no-confirm --extra-conf 'substituters = https://cache.nixos.org https://nix-postgres-artifacts.s3.amazonaws.com' --extra-conf 'trusted-public-keys = nix-postgres-artifacts:dGZlQOvKcNEjvT7QEAJbcV6b6uk7VF/hWMjhYleiaLI=% cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=' + when: nix_installed.rc != 0 + become: true diff --git a/ansible/tasks/setup-system-manager.yml b/ansible/tasks/setup-system-manager.yml new file mode 100644 index 0000000000..cd76bbb4d4 --- /dev/null +++ b/ansible/tasks/setup-system-manager.yml @@ -0,0 +1,7 @@ +--- +- name: Deploy system manager + ansible.builtin.shell: | + . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh + cd /tmp + nix run --accept-flake-config /tmp/flake#system-manager -- switch --flake /tmp/flake 2>&1 | tee /tmp/system-manager-deploy.log + become: true diff --git a/audit-specs/baselines/ami-build/user.yml b/audit-specs/baselines/ami-build/user.yml index e764be6268..a3b1e716c8 100644 --- a/audit-specs/baselines/ami-build/user.yml +++ b/audit-specs/baselines/ami-build/user.yml @@ -6,14 +6,14 @@ user: root: exists: true home: /root - shell: /bin/bash + shell: /run/system-manager/sw/bin/bash ubuntu: exists: true home: /home/ubuntu shell: /bin/bash nobody: exists: true - shell: /usr/sbin/nologin + shell: /run/system-manager/sw/bin/nologin # PostgreSQL ecosystem postgres: diff --git a/flake.lock b/flake.lock index 839994d62b..77d65fe756 100644 --- a/flake.lock +++ b/flake.lock @@ -36,6 +36,22 @@ "type": "github" } }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" @@ -54,6 +70,28 @@ "type": "github" } }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "system-manager", + "userborn", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1768135262, + "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" @@ -115,6 +153,29 @@ "type": "github" } }, + "gitignore_2": { + "inputs": { + "nixpkgs": [ + "system-manager", + "userborn", + "pre-commit-hooks-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, "nix": { "flake": false, "locked": { @@ -276,6 +337,34 @@ "url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz" } }, + "pre-commit-hooks-nix": { + "inputs": { + "flake-compat": [ + "system-manager", + "userborn", + "flake-compat" + ], + "gitignore": "gitignore_2", + "nixpkgs": [ + "system-manager", + "userborn", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1769069492, + "narHash": "sha256-Efs3VUPelRduf3PpfPP2ovEB4CXT7vHf8W+xc49RL/U=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "a1ef738813b15cf8ec759bdff5761b027e3e1d23", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, "root": { "inputs": { "devshell": "devshell", @@ -289,6 +378,7 @@ "nixpkgs": "nixpkgs_2", "nixpkgs-oldstable": "nixpkgs-oldstable", "rust-overlay": "rust-overlay", + "system-manager": "system-manager", "treefmt-nix": "treefmt-nix" } }, @@ -312,6 +402,27 @@ "type": "github" } }, + "system-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "userborn": "userborn" + }, + "locked": { + "lastModified": 1772207794, + "narHash": "sha256-87Ids4DKqzznNpr39613aFnLbK3WIljt86pHFTOjvsA=", + "owner": "numtide", + "repo": "system-manager", + "rev": "aa740af1b7919a9969325b91ef59890ea54ecace", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "system-manager", + "type": "github" + } + }, "systems": { "locked": { "lastModified": 1681028828, @@ -327,6 +438,21 @@ "type": "github" } }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "treefmt-nix": { "inputs": { "nixpkgs": [ @@ -346,6 +472,32 @@ "repo": "treefmt-nix", "type": "github" } + }, + "userborn": { + "inputs": { + "flake-compat": "flake-compat_2", + "flake-parts": "flake-parts_2", + "nixpkgs": [ + "system-manager", + "nixpkgs" + ], + "pre-commit-hooks-nix": "pre-commit-hooks-nix", + "systems": "systems_2" + }, + "locked": { + "lastModified": 1770377964, + "narHash": "sha256-q2pnlX2IW0kg80GLFnwWd/GigIpkuZnyKPLhrgJql3E=", + "owner": "jfroche", + "repo": "userborn", + "rev": "55c2cd7952c207a62736a5bbd9499ea73da18d24", + "type": "github" + }, + "original": { + "owner": "jfroche", + "ref": "system-manager", + "repo": "userborn", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 4d9ccdbe47..6d81d25db7 100644 --- a/flake.nix +++ b/flake.nix @@ -31,6 +31,8 @@ rust-overlay.url = "github:oxalica/rust-overlay"; treefmt-nix.inputs.nixpkgs.follows = "nixpkgs"; treefmt-nix.url = "github:numtide/treefmt-nix"; + system-manager.inputs.nixpkgs.follows = "nixpkgs"; + system-manager.url = "github:numtide/system-manager"; }; outputs = @@ -53,6 +55,8 @@ nix/nixpkgs.nix nix/packages nix/overlays + nix/systemModules + nix/systemConfigs.nix ]; }); } diff --git a/nix/docs/README.md b/nix/docs/README.md index 5d177b13de..9b2f8c03c4 100644 --- a/nix/docs/README.md +++ b/nix/docs/README.md @@ -19,6 +19,7 @@ learn how to play with `postgres` in the [build guide](./build-postgres.md). - **[Start Client/Server](./start-client-server.md)** - Running PostgreSQL client and server - **[Docker](./docker.md)** - Docker integration and usage - **[Docker Image Size Analyzer](./image-size-analyzer-usage.md)** - Tool to analyze the Docker image sizes +- **[System Manager](./system-manager.md)** - Declarative system configuration with system-manager - **[Use direnv](./use-direnv.md)** - Development environment with direnv - **[Pre-commit Hooks](./pre-commit-hooks.md)** - Automatic formatting and code checks before commits - **[Nix Formatter](./nix-formatter.md)** - Code formatting with treefmt diff --git a/nix/docs/nix-directory-structure.md b/nix/docs/nix-directory-structure.md index c58441b4bc..33b8feaaca 100644 --- a/nix/docs/nix-directory-structure.md +++ b/nix/docs/nix-directory-structure.md @@ -22,7 +22,9 @@ nix/ ├── ext/ # PostgreSQL extensions ├── overlays/ # Nixpkgs overlays ├── packages/ # Custom packages - └── postgresql/ # PostgreSQL packages + ├── postgresql/ # PostgreSQL packages + ├── systemConfigs.nix # system-manager configuration definitions + └── systemModules/ # system-manager service modules ``` ## Module Descriptions @@ -150,6 +152,20 @@ Nixpkgs overlays for package customization: - `cargo-pgrx-0-11-3.nix` - PGRX toolchain overlay - `psql_16-oriole.nix` - OrioleDB PostgreSQL variant +#### `nix/systemConfigs.nix` + +System configuration definitions for [system-manager](https://github.com/numtide/system-manager). +Calls `system-manager.lib.makeSystemConfig` to produce a configuration for each supported architecture (`aarch64-linux`, `x86_64-linux`) from the enabled modules. +See [System manager](./system-manager.md) for details. + +#### `nix/systemModules/` + +Service module definitions managed by system-manager: + +- `default.nix` - Module registry that exports modules under `flake.systemModules` +- Individual `.nix` files - Service modules (e.g. nginx) loaded via `flake-parts-lib.importApply` +- `tests/default.nix` - Container-based tests using `makeContainerTest` + #### `nix/cargo-pgrx/` Rust-based PostgreSQL extension building: diff --git a/nix/docs/system-manager.md b/nix/docs/system-manager.md new file mode 100644 index 0000000000..5f790d17c8 --- /dev/null +++ b/nix/docs/system-manager.md @@ -0,0 +1,210 @@ +# System manager + +[system-manager](https://github.com/numtide/system-manager) provides declarative, Nix-based system configuration management for non-NixOS Linux systems. +It replaces imperative service setup with reproducible Nix module definitions, bringing NixOS-style service management to the AMI build without requiring a full NixOS installation. + +## How it fits into the AMI build pipeline + +The AMI build uses a two-stage pipeline orchestrated by Packer and Ansible. +Stage 1 installs Nix itself, while stage 2 uses Nix to build and deploy all services. +system-manager is deployed during stage 2 via the Ansible task `ansible/tasks/setup-system-manager.yml`: + +```yaml +- name: Deploy system manager + ansible.builtin.shell: | + . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh + cd /tmp + nix run --accept-flake-config /tmp/flake#system-manager -- switch --flake /tmp/flake 2>&1 | tee /tmp/system-manager-deploy.log + become: true +``` + +This sources the Nix daemon profile, then runs `system-manager switch` against the flake to apply the declared system configuration. + +## Nix configuration walkthrough + +### Flake input + +The system-manager flake input is declared in `flake.nix` (lines 34-35), pinned to the upstream repository with nixpkgs following the main input: + +```nix +system-manager.inputs.nixpkgs.follows = "nixpkgs"; +system-manager.url = "github:numtide/system-manager"; +``` + +The flake outputs import both the module registry and the system configurations: + +```nix +imports = [ + # ... + nix/systemModules + nix/systemConfigs.nix +]; +``` + +### System configurations + +`nix/systemConfigs.nix` defines the top-level system configurations for each supported architecture. +It calls `system-manager.lib.makeSystemConfig` to produce a configuration from the enabled modules: + +```nix +mkSystemConfig = system: { + name = system; + value.default = inputs.system-manager.lib.makeSystemConfig { + modules = mkModules system; + extraSpecialArgs = { + inherit self; + inherit system; + }; + }; +}; +``` + +The `mkModules` function returns the list of modules to enable. +Currently it enables the nginx service and sets the host platform: + +```nix +mkModules = system: [ + ({ + services.nginx.enable = true; + nixpkgs.hostPlatform = system; + }) +]; +``` + +Configurations are built for both `aarch64-linux` and `x86_64-linux`. + +### System modules + +`nix/systemModules/default.nix` is the module registry. +It is a flake-parts module that exports individual system modules under `flake.systemModules`: + +```nix +{ + imports = [ ./tests ]; + flake = { + systemModules = { + nginx = flake-parts-lib.importApply ./nginx.nix { inherit withSystem self; }; + }; + }; +} +``` + +Each module is loaded with `flake-parts-lib.importApply`, which passes `withSystem` and `self` as arguments to the module file. + +## Adding a new system module + +To add a new system module: + +1. Create a new `.nix` file under `nix/systemModules/`, for example `nix/systemModules/my-service.nix`. + The module is a standard NixOS-style module with options and config: + + ```nix + { + lib, + config, + ... + }: + let + cfg = config.supabase.services.my-service; + in + { + options = { + supabase.services.my-service = { + enable = lib.mkEnableOption "Whether to enable the my-service systemd service."; + }; + }; + + config = lib.mkIf cfg.enable { + # systemd units, environment.etc entries, etc. + }; + } + ``` + +2. Register the module in `nix/systemModules/default.nix` by adding it to the `systemModules` attribute set: + + ```nix + systemModules = { + my-service = ./my-service.nix; + }; + ``` + +3. Include and enable the module in `nix/systemConfigs.nix` by adding it to the `mkModules` list and setting the enable option: + + ```nix + mkModules = system: [ + self.systemModules.my-service + ({ + services.nginx.enable = true; + supabase.services.my-service.enable = true; + nixpkgs.hostPlatform = system; + }) + ]; + ``` + +4. Add a test assertion to the test script in `nix/systemModules/tests/default.nix` (see below). + +## Testing + +### Container tests + +Tests are defined in `nix/systemModules/tests/default.nix` using `system-manager.lib.containerTest.makeContainerTest`. +This creates a lightweight container-based NixOS test that validates the system configuration: + +```nix +check-system-manager = + let + toplevel = self.systemConfigs.${pkgs.system}.default; + in + inputs.system-manager.lib.containerTest.makeContainerTest { + hostPkgs = pkgs; + name = "check-system-manager"; + inherit toplevel; + testScript = '' + start_all() + + machine.wait_for_unit("multi-user.target") + + machine.activate() + machine.wait_for_unit("system-manager.target") + + with subtest("Verify nginx service"): + assert machine.service("nginx").is_running, "nginx should be running" + ''; + }; +``` + +The test script starts the container, waits for systemd to reach `multi-user.target`, activates the system-manager configuration, then verifies that managed services are running. +When adding a new module, extend the `testScript` with an additional `subtest` block that asserts the new service is running. + +### Running tests locally + +Run the system-manager check locally with: + +```bash +nix build .#checks.x86_64-linux.check-system-manager -L +``` + +The `-L` flag streams build logs for visibility. +These checks only run on Linux (gated by `lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux`). + +## CI integration + +The `check-system-manager` derivation is part of the flake's `checks` output, so it runs automatically in the `nix-build-checks-*` jobs of the main `nix-build.yml` workflow alongside all other checks. + +## Runtime effects + +After `system-manager switch` runs, managed software is available under `/run/system-manager/sw/`. +This affects paths throughout the system. +For example, the audit baseline `audit-specs/baselines/ami-build/user.yml` references these paths for user shells: + +```yaml +root: + exists: true + home: /root + shell: /run/system-manager/sw/bin/bash +nobody: + exists: true + shell: /run/system-manager/sw/bin/nologin +``` + +When adding new services or modifying system-manager configuration, update the audit baselines accordingly to reflect any changes to user shells, service users, or file paths that `supascan` validates during AMI builds. diff --git a/nix/mkdocs.yml b/nix/mkdocs.yml index 52c2be5392..b4374ced18 100644 --- a/nix/mkdocs.yml +++ b/nix/mkdocs.yml @@ -26,6 +26,7 @@ nav: - Create pgrx Extension: creating-pgrx-extension.md - Update pgrx Extensions: updating-pgrx-extensions.md - Receipt Files: receipt-files.md + - System manager: system-manager.md - Package Management: - Adding New Packages: adding-new-package.md - Update Extensions: update-extension.md diff --git a/nix/packages/default.nix b/nix/packages/default.nix index d49211073f..df9b8820e1 100644 --- a/nix/packages/default.nix +++ b/nix/packages/default.nix @@ -88,6 +88,7 @@ inherit (self'.packages) overlayfs-on-package; }; sync-exts-versions = pkgs.callPackage ./sync-exts-versions.nix { inherit (inputs') nix-editor; }; + system-manager = inputs'.system-manager.packages.default; trigger-nix-build = pkgs.callPackage ./trigger-nix-build.nix { }; update-readme = pkgs.callPackage ./update-readme.nix { }; supabase-cli = pkgs.callPackage ./supabase-cli.nix { }; diff --git a/nix/systemConfigs.nix b/nix/systemConfigs.nix new file mode 100644 index 0000000000..d0dd1829a5 --- /dev/null +++ b/nix/systemConfigs.nix @@ -0,0 +1,32 @@ +{ self, inputs, ... }: +let + mkModules = system: [ + self.systemModules.ssh-config + self.systemModules.fail2ban + ({ + nixpkgs.hostPlatform = system; + supabase.services.fail2ban.enable = true; + }) + ]; + + systems = [ + "aarch64-linux" + "x86_64-linux" + ]; + + mkSystemConfig = system: { + name = system; + value.default = inputs.system-manager.lib.makeSystemConfig { + modules = mkModules system; + extraSpecialArgs = { + inherit self; + inherit system; + }; + }; + }; +in +{ + flake = { + systemConfigs = builtins.listToAttrs (map mkSystemConfig systems); + }; +} diff --git a/nix/systemModules/default.nix b/nix/systemModules/default.nix new file mode 100644 index 0000000000..59d10628d8 --- /dev/null +++ b/nix/systemModules/default.nix @@ -0,0 +1,24 @@ +{ + ... +}: +{ + imports = [ ./tests ]; + flake = { + systemModules = { + ssh-config = { + environment.etc."ssh/sshd_config.d/local.conf" = { + text = '' + Match Address 127.0.0.1,::1 + ForceCommand /bin/false + DisableForwarding yes + PermitTunnel no + ''; + user = "root"; + group = "root"; + mode = "0644"; + }; + }; + fail2ban = ./fail2ban.nix; + }; + }; +} diff --git a/nix/systemModules/fail2ban.nix b/nix/systemModules/fail2ban.nix new file mode 100644 index 0000000000..a18565377c --- /dev/null +++ b/nix/systemModules/fail2ban.nix @@ -0,0 +1,83 @@ +{ + lib, + nixosModulesPath, + config, + pkgs, + ... +}: +let + cfg = config.supabase.services.fail2ban; +in +{ + imports = [ + "${nixosModulesPath}/services/security/fail2ban.nix" + ]; + + options = { + # Create a dummy openssh option to unbreak the + # > The option `services.openssh.settings' does not exist. + # we face when importing the NixOS fail2ban.nix module. + # + # Note: the fail2ban module is trying to increase the log + # verbosity of the openssh daemon to simplify debug. We don't + # really need this feature: system-manager is not controlling the + # ssh daemon here. + # + # TOREMOVE if we end up provisionning openssh through + # systemmanager. + services.openssh.settings = lib.mkOption { + type = lib.types.attrs; + }; + # Some goes for nftables + networking.nftables.enable = lib.mkEnableOption "dummy nftable module"; + + # TODO move to iptables + supabase.services.fail2ban = { + enable = lib.mkEnableOption "Fail2Ban"; + }; + }; + + config = lib.mkIf cfg.enable { + # Dummy + networking.nftables.enable = true; + services.fail2ban = { + enable = true; + bantime = "3600"; + packageFirewall = pkgs.nftables; + jails = { + postgresql = { + settings = { + enabled = true; + port = "5432"; + protocol = "tcp"; + filter = "postgresql"; + logpath = "/var/log/postgresql/auth-failures.csv"; + maxretry = 3; + ignoreip = "192.168.0.0/16 172.17.1.0/20"; + }; + }; + pgbouncer = { + settings = { + enabled = true; + port = "6543"; + protocol = "tcp"; + filter = "pgbouncer"; + backend = "systemd[journalflags=1]"; + maxretry = 3; + }; + }; + }; + }; + + environment.etc = { + "fail2ban/filter.d/postgresql.conf".source = ./postgresql-filter.conf; + "fail2ban/filter.d/pgbouncer.conf".source = ./pgbouncer.conf; + }; + + systemd.services.fail2ban = { + wantedBy = lib.mkForce [ + "system-manager.target" + ]; + }; + }; +} diff --git a/nix/systemModules/pgbouncer.conf b/nix/systemModules/pgbouncer.conf new file mode 100644 index 0000000000..24418cb3a8 --- /dev/null +++ b/nix/systemModules/pgbouncer.conf @@ -0,0 +1,8 @@ +[Init] +maxlines = 3 + +[Definition] +failregex = ^.+@:.+password authentication failed$ + ^.+@:.+pooler error: no such user$ + ^.+@:.+registered new auto-database.*\n.*\n.*server login failed: FATAL database ".+" does not exist.*$ +journalmatch = _SYSTEMD_UNIT=pgbouncer.service diff --git a/nix/systemModules/postgresql-filter.conf b/nix/systemModules/postgresql-filter.conf new file mode 100644 index 0000000000..01558cc4bd --- /dev/null +++ b/nix/systemModules/postgresql-filter.conf @@ -0,0 +1,4 @@ +[Definition] +failregex = ^.*,.*,.*,.*,":.*password authentication failed for user.*$ + ^.*no pg_hba\.conf entry for host "",.*$ +ignoreregex = ^.*,.*,.*,.*,"127\.0\.0\.1.*password authentication failed for user.*$ diff --git a/nix/systemModules/tests/default.nix b/nix/systemModules/tests/default.nix new file mode 100644 index 0000000000..d9d92b3326 --- /dev/null +++ b/nix/systemModules/tests/default.nix @@ -0,0 +1,40 @@ +{ self, inputs, ... }: +{ + perSystem = + { + lib, + pkgs, + ... + }: + { + checks = lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux { + check-system-manager = + let + toplevel = self.systemConfigs.${pkgs.system}.default; + in + inputs.system-manager.lib.containerTest.makeContainerTest { + hostPkgs = pkgs; + name = "check-system-manager"; + inherit toplevel; + testScript = '' + start_all() + + machine.wait_for_unit("multi-user.target") + + machine.activate() + machine.wait_for_unit("system-manager.target") + + with subtest("Verify ssh config"): + assert machine.file("/etc/ssh/sshd_config.d/local.conf").exists, "/etc/ssh/sshd_config.d/local.conf should exist" + assert machine.file("/etc/ssh/sshd_config.d/local.conf").mode == 0o644, "/etc/ssh/sshd_config.d/local.conf should have mode 0644" + assert machine.file("/etc/ssh/sshd_config.d/local.conf").user == "root", "/etc/ssh/sshd_config.d/local.conf should be owned by root" + assert machine.file("/etc/ssh/sshd_config.d/local.conf").group == "root", "/etc/ssh/sshd_config.d/local.conf should be owned by root" + assert machine.file("/etc/ssh/sshd_config.d/local.conf").contains("Match Address"), "/etc/ssh/sshd_config.d/local.conf should contain 'Match Address'" + with subtest("Verify system manager config"): + machine.wait_for_unit("fail2ban.service") + + ''; + }; + }; + }; +} diff --git a/stage2-nix-psql.pkr.hcl b/stage2-nix-psql.pkr.hcl index 032dd71e52..d751a506d4 100644 --- a/stage2-nix-psql.pkr.hcl +++ b/stage2-nix-psql.pkr.hcl @@ -120,6 +120,11 @@ build { destination = "/tmp/ansible-playbook" } + provisioner "file" { + source = "${abspath(path.root)}" + destination = "/tmp/flake" + } + provisioner "shell" { environment_vars = [ "GIT_SHA=${var.git_sha}",