bos55-nix-config-cicd/SECURITY.md
Tibo De Peuter ce0543a20f
Some checks failed
Check / check (push) Failing after 2s
feat(ci): implement signed commit verification and update security policy
Added a CI/CD step to verify cryptographic signatures for deployments. Updated SECURITY.md with the new trust model and refined GHA workflows for consistency.
2026-03-17 19:42:17 +01:00

5.2 KiB

Security and Trust Model

This document outlines the security architecture, trust boundaries, and assumptions of the Bos55 NixOS deployment pipeline. This model is designed to support a multi-member infrastructure team and remains secure even if the repository is published publicly.

Trust Zones

The system is partitioned into three distinct trust zones, each with specific controls to prevent lateral movement and privilege escalation.

🔴 Zone 1: Trusted Maintainers (Source of Truth)

  • Actors: Infrastructure Team / Maintainers.
  • Capabilities:
    • Full access to the Git repository.
    • Ownership of sops-nix master keys (GPG or Age).
    • Direct root access to NixOS hosts via personal SSH keys for emergency maintenance.
  • Trust: Root of trust. All changes must originate from or be approved by a Trusted Maintainer.
  • Security Controls:
    • Signed Commits: All contributions must be cryptographically signed by a trusted GPG/SSH key to be eligible for deployment.
    • MFA: Hardware-based multi-factor authentication for repository access.
    • Metadata Redaction: Sensitive identifiers like SSH authorizedKeys are stored in sops-nix. This prevents infrastructure fingerprinting, where an attacker could link your public keys to your personal identities or other projects.

🟡 Zone 2: CI/CD Pipeline (Automation Layer)

  • Actor: GitHub Actions / Forgejo Runners.
  • Capabilities:
    • Builds Nix derivations from the repository.
    • Access to the DEPLOY_SSH_KEY (allowing SSH access to the deploy user on target hosts).
    • Trusted Signers: The public keys for verifying signatures are stored as a Runner Secret (TRUSTED_SIGNERS). This hides the identities of the infrastructure team even in a public repository.
    • NO ACCESS to sops-nix decryption keys. Secrets remain encrypted during the build.
  • Security Controls:
    • Signature Enforcement: The deploy.yml workflow verifies the cryptographic signature of every maintainer commit. Deployment is aborted if the signature is missing or untrusted.
    • Sandboxing: Runners execute in ephemeral, isolated containers.
    • Branch Protection: Deployments to production (main) require approved Pull Requests.
    • Fork Protection: CI workflows (and secrets) are explicitly disabled for forks.

🟢 Zone 3: Target NixOS Hosts (Runtime)

  • Actor: Production, Testing, and Service nodes.
  • Capabilities: Decrypt secrets locally using host-specific age keys.
  • Trust: Consumers of builds. They trust Zone 2 only for the pushing of store paths and triggering activation scripts.
  • Security Controls:
    • Restricted deploy User: The SSH user for automation is non-root. Sudo access is strictly policed via sudoers rules to allow only nix-env and switch-to-configuration.
    • Immutable Store: Building on Nix ensures that the system state is derived from a cryptographically hashed store, preventing unauthorized local modifications from persisting across reboots.

Security Assumptions & Policies

1. Public Repository Safety

The repository is designed to be safe for public viewing. No unencrypted secrets should ever be committed. The deployment pipeline is protected against "malicious contributors" via:

  • Mandatory PR Reviews: No code can reach the main branch without peer review.
  • Secret Scoping: Deployment keys are only available to authorized runs on protected branches.

2. Supply Chain & Dependencies

  • Flake Lockfiles: All dependencies (Nixpkgs, deploy-rs, etc.) are pinned to specific git revisions.
  • Renovate Bot: Automated version upgrades allow for consistent tracking of upstream changes, though they require manual review or successful status checks for minor/patch versions.

3. Signed Commit Enforcement

To prevent "force-push" attacks or runner compromises from injecting malicious code into the history, the pipeline should be configured to only deploy commits signed by a known "Trusted Maintainer" key. This ensures that even if a git account is compromised, the attacker cannot deploy code without the physical/cryptographic signing key.


Trust Boundary Diagram

graph TD
    subgraph "Zone 1: Trusted Workstations"
        DEV["Maintainers (Team)"]
        SOPS_KEYS["Master SOPS Keys"]
        SIGN_KEYS["Signing Keys (GPG/SSH)"]
    end

    subgraph "Zone 2: CI/CD Runner (Sandboxed)"
        CI["Automated Runner"]
        SSH_KEY["Deploy SSH Key"]
    end

    subgraph "Zone 3: NixOS Target Hosts"
        HOST["Target Host"]
        HOST_AGE["Host Age Key"]
    end

    DEV -- "Signed Push / PR" --> CI
    CI -- "Push Store Paths & Activate" --> HOST
    HOST_AGE -- "Local Decrypt" --> HOST
    
    style DEV fill:#f96,stroke:#333
    style CI fill:#ff9,stroke:#333
    style HOST fill:#9f9,stroke:#333

Security Best Practices for Maintainers

  1. Keep Master Keys Offline: Never store sops-nix master keys on the CI runner or public servers.
  2. Audit Runner Logs: Periodically review CI execution logs for unexpected behavior.
  3. Rotate Deployment Keys: Rotate the DEPLOY_SSH_KEY if maintainer membership changes significantly.