4 24 Security Baseline
Nimmo edited this page 2026-09-12 17:04:55 +01:00

Security Baseline

  • Type: Policy
  • Status: Current
  • Scope: Managed NixOS fleet and services declared by this repository
  • Canonical sources: AGENTS.md; .sops.yaml; secrets/README.md; modules/server/base.nix; modules/networking/nebula.nix; service listener, firewall, credential, backup, and systemd declarations; Service Catalogue; Network and Access Topology; Storage and Data Map
  • Last verified: Source commit 556df88494686003b1c4f20c8e0b99b5afc16a6e (2026-09-12)
  • Review triggers: New hosts or services; listener, firewall, ingress, authentication, secret-recipient, privilege, backup, boot-security, or update-control changes; newly identified exceptions

This policy defines the minimum security controls and review gates for the personal fleet. The System Atlas pages own the exact current implementation; this page owns what is required, which exceptions are presently known, and how they are reviewed.

Policy principles

  1. Expose the narrowest usable interface. Prefer a local socket or loopback, then an explicitly permitted Nebula listener, then authenticated public ingress. A broad listener requires a documented reason and compensating control.
  2. Authenticate independently where practical. A private address, Docker bridge, tunnel, or permissive mesh is a route boundary, not automatically an application identity boundary.
  3. Grant secrets to consumers, not fleets. Secret files and recipients must be scoped to the hosts and services that need them, with deliberate recovery recipients.
  4. Minimise privileged access. Custom services should run with the least useful identity and systemd sandboxing. Docker daemon access is root-equivalent and must be treated as such.
  5. Protect recovery as part of security. Configuration, authoritative data, credentials, encryption keys, and an independent recovery route must survive the failure modes claimed for them.
  6. Make failure visible. A control is incomplete when authentication, backup, update, or service failure cannot be detected and investigated.

Required controls

Administrative access

  • SSH password authentication and direct root login must remain disabled on managed hosts.
  • Administrative listeners must use the narrowest firewall/interface scope compatible with their operating model. Host-wide SSH or Mosh exposure is an explicit exception requiring review, not a default inherited silently.
  • Human and automation credentials must be separate when their permissions or revocation lifecycle differ. Forgejo bot, Paseo, MCP, and personal access tokens must not be treated as interchangeable.
  • Provisioning and emergency access must have a deliberate off-host recovery path without embedding plaintext credentials in the repository.

Network and ingress

  • Every service must have an identified bind address, firewall path, ingress path, authentication control, and intended client set.
  • Administrative interfaces and databases should be loopback-only or mesh-only. Public access should normally terminate at authenticated TLS ingress rather than at an application listener.
  • A listener on 0.0.0.0 or a globally allowed host port must have a documented need. Review physical LAN, mesh, container bridge, and public-tunnel reachability separately; one does not imply the others.
  • Newt and relay clients may initiate outbound connections, but the external Pangolin route and public DNS configuration must be reviewed as part of the effective exposure. Configuration in this repository cannot attest to those external controls on its own.
  • Docker networks are connectivity boundaries, not protection from a user who can control the Docker daemon.

Secrets and credentials

  • Secret values must never enter Nix expressions, the Nix store, wiki pages, issue comments, logs, or agent memory.
  • Repository secrets must remain SOPS-encrypted. Runtime plaintext should be materialised under /run/secrets and passed through a file, environment file, or systemd credential rather than command-line arguments where supported.
  • Each scoped secret file must include only the consuming hosts plus intentional administrative recovery recipients. Host-specific network identities and credentials declared as per-host must remain isolated per host.
  • The Nebula CA must not be granted to ordinary servers merely because they are mesh members. A compromised member must not thereby gain certificate-issuing authority.
  • Rotation must preserve a verified recovery recipient and re-encrypt every affected tracked file. Removing an old recipient is incomplete until access with the new recipient has been tested.

Service privilege and isolation

  • Services must run as dedicated or dynamic users where practical and own only the state paths they require.
  • New custom systemd services must be reviewed for NoNewPrivileges, private temporary directories, protected system/home paths, capability restrictions, and writable-path allowlists. Unsupported controls and necessary exceptions must be recorded rather than forced blindly.
  • Container mounts, devices, host networking, privileged mode, and Docker socket access require explicit justification. Membership in the docker group is accepted only as a conscious root-equivalent convenience on the personal machines where it is configured.
  • Tokens exposed to desktop AI tools or MCP launchers must be limited to the service and permissions required; a brokered internal service should retain upstream credentials when clients need only the broker token.

Host, boot, and physical protection

  • Disk-encryption policy must be decided per host from physical access risk, sensitivity of local state, and unattended-reboot requirements. An unencrypted host is a recorded risk decision, not an implicit default.
  • Secure Boot or TPM unlock must retain an independent, tested recovery route. Recovery must not depend solely on the TPM, the protected host, or keys stored on that host.
  • Bootloader, encryption, filesystem, host-key, and provisioning changes require the recovery checkpoint and evidence defined by Project and Change Governance.

Data protection and recovery

  • Every authoritative state path and database must have an identified backup owner, destination, retention policy, and restore procedure—or a documented acceptance that it is disposable.
  • A database backup must capture a recoverable database representation; backing up adjacent application files is not sufficient. A locally generated dump is not an off-host backup until it enters an off-host path.
  • Backup configuration is intent, not proof. New services and material storage changes require a successful backup and a risk-appropriate restore check.
  • NAS-hosted data, mutable Docker stacks, recovery keys, and other state outside the NixOS host must have an explicit external owner rather than disappearing from the review because it is outside this repository.

Updates, provenance, and observability

  • Deployment artefacts must pass the validation and canary gates in Project and Change Governance. Automated update publication must retain its build, lease, rollback, and guarded-remediation controls.
  • Pinned source revisions and fixed-output hashes must be used where the repository packages external code outside normal nixpkgs provenance.
  • Important service, update, backup, authentication, and recovery failures must be visible through systemd status, monitoring, notification, or workflow evidence appropriate to the component.
  • Monitoring agents should make outbound connections where possible rather than creating new unauthenticated inbound administration ports.

Host and service review gate

A new host or service is not complete until its issue records the applicable answers and evidence:

Area Required review
Identity Runtime user, administrator path, user/client authentication, automation credentials, and revocation path
Exposure Bind addresses, host and mesh firewall rules, Docker networks, ingress route, intended clients, and TLS boundary
Secrets Exact scoped file, consumers, SOPS recipients, runtime delivery method, file ownership/mode, and recovery recipients
Privilege systemd sandboxing, capabilities, writable paths, devices, container privileges, and root-equivalent Docker access
Data Authoritative and disposable state, databases, mounts, backup path, retention owner, and restore evidence
Host security Physical threat, disk encryption, boot trust, unattended reboot, and independent recovery route
Supply chain Package/source provenance, pins and hashes, update path, deterministic validation, and rollback
Visibility Health check, relevant logs, failure notification, backup monitoring, and responsible responder

The review must compare evaluated listeners and firewall rules with the intended topology. For external Pangolin, NAS, Proxmox, DNS, or mutable Docker/SWAG state, record what was inspected and what remains outside repository verification.

Current implementation and known exceptions

The fleet already implements SOPS runtime decryption, host- and service-scoped secret rules, disabled SSH password/root login, host firewalls, Nebula, TLS ingress, service-specific identities in many native units, encrypted restic backups, monitoring, and guarded update publication. Electra additionally has LUKS storage, signed boot artefacts, Secure Boot, TPM policy, and independent passphrase recovery. Exact placement belongs in the linked System Atlas pages.

The following declared exceptions and gaps require either remediation or an explicit continuing risk decision in Forgejo:

  • the Nebula policy is permissive within the mesh, with NixOS interface firewall rules carrying most service-specific restriction;
  • server-profile SSH and Mosh are host-wide rather than mesh-only;
  • Engram Cloud, Lyra Ollama/Wyoming, and retained media ports include broad listeners or global firewall openings;
  • Tdarr authentication and SABnzbd web login are disabled, making topology and ingress controls security-critical;
  • Docker group access remains intentionally root-equivalent, and Lyra retains a mutable Docker/SWAG estate outside full repository review;
  • .sops.yaml still has a fleet-wide fallback and a shared rule for several legacy split files; recipient scope therefore remains broader than consumer scope for some secrets;
  • the nebula-ca.yaml rule currently includes Vega and Lyra even though its inline comment says servers are excluded, so CA recipient policy and implementation disagree;
  • only Electra declares storage encryption in the current Disko specifications;
  • Vega PostgreSQL dumps are local-only, BookStack MariaDB lacks declared backup coverage, Lena's second user's home is omitted, Engram Cloud state is only partially covered, and Lyra /srv/stacks is outside Backrest;
  • Electra's secure-boot runbook still records a final post-change recovery archive task as incomplete.

These are configuration findings, not assertions of compromise. Do not remove one from this list merely because it is familiar or longstanding: link the implemented remediation, an accepted ADR/risk decision, or evidence that the source no longer exhibits it.

Exceptions and enforcement

An exception must name its owner, affected hosts/services, threat or failure mode, compensating controls, review date or trigger, and a Forgejo issue or accepted decision record. Convenience alone is not sufficient documentation.

Reviewers should block a new host/service or material exposure change when the review gate is absent, secret scope is broader than its consumers, recovery is untested, or configuration and asserted topology disagree. Urgent remediation may proceed through the smallest safe change path, but the exception and follow-up evidence must remain tracked.

Implementation detail is in the Service Catalogue, Network and Access Topology, and Storage and Data Map. Operating and recovery commands belong in Operations and Runbooks. ADR-002 owns workload-placement rationale and ADR-003 owns the network trust model. ADR-006 owns scoped-secret rationale rather than repeating it here.