Mechanical, semantics-preserving cleanup so the codebase passes the new lint stage:
- ruff format: all 32 Python files (wraps long signatures, normalizes quotes/blank lines).
- nixpkgs-fmt: modules/drone-runner.nix.
- shfmt (-i 2 -ci): scripts/*.sh.
Lint fixes (reviewed, behavior-preserving — no test weakened):
- ruff SIM105: try/except-pass -> contextlib.suppress (abra.py app_config rm; lifecycle.py janitor).
- ruff SIM115: open().read() -> with open() (run_recipe_ci.py redaction-values + gitea-token).
- statix: merge repeated sops `secrets.*` keys into one `secrets = { ... }` (comments kept);
empty fn pattern `{ ... }:` -> `_:` (packages.nix).
- deadnix: drop unused lambda args (flake `self`; configuration.nix `lib`; overlay `final` -> `_`).
Verified on cc-ci: `scripts/lint.sh` -> lint: PASS; nixosConfigurations.cc-ci evaluates;
all Python byte-compiles. The deployed bridge/dashboard/runner source changes hash (reformat),
so cc-ci will be rebuilt to the new closure in W2 before the cold D1-D10 re-verification.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
58 lines
3.0 KiB
Nix
58 lines
3.0 KiB
Nix
# sops-nix wiring (D6 infra secrets). cc-ci decrypts secrets at activation using its own
|
|
# ed25519 SSH host key as the age identity (no separate key file to manage on the box).
|
|
# Encrypted material lives in ../secrets/secrets.yaml — Phase-1c moved this into the private
|
|
# `cc-ci-secrets` repo, mounted here as a git SUBMODULE at ../secrets/ (so the path is unchanged).
|
|
# Readable only by the recipients in secrets/.sops.yaml (host key + off-box master recovery key).
|
|
{ config, ... }:
|
|
{
|
|
sops = {
|
|
defaultSopsFile = ../secrets/secrets.yaml;
|
|
# Decrypt using the host's SSH host key (converted to an age identity by sops-nix).
|
|
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
|
|
# Phase-1c: also accept a bootstrap age key at a fixed path — THE one out-of-band secret,
|
|
# provisioned to the host before the first rebuild. On the canonical cc-ci this holds the
|
|
# host-derived age identity (== the sshKeyPaths recipient, no new exposure); on a fresh/cloned
|
|
# host (e.g. the throwaway-VM rebuild) it holds the off-box recovery key, so a host whose SSH
|
|
# host key is NOT a sops recipient can still decrypt every secret. NOTE: sops-install-secrets
|
|
# aborts activation if this file is set but missing, so it must exist before `nixos-rebuild`.
|
|
age.keyFile = "/var/lib/sops-nix/key.txt";
|
|
# Do not also look for a GPG key.
|
|
gnupg.sshKeyPaths = [ ];
|
|
|
|
secrets = {
|
|
# M0 proof secret — confirms the decrypt path works end to end.
|
|
test_secret = { };
|
|
|
|
# M2 Drone (A2 internal secrets). drone_rpc_secret is shared between the swarm-deployed
|
|
# Drone server (inserted as the `rpc_secret` swarm secret by scripts/deploy-drone.sh) and
|
|
# the host exec runner (read via the env template below). drone_gitea_client_secret is the
|
|
# Gitea OAuth app secret, inserted as the server's `client_secret` swarm secret.
|
|
drone_rpc_secret = { };
|
|
drone_gitea_client_secret = { };
|
|
|
|
# M3 comment-bridge (A2). Read by modules/bridge.nix's reconcile oneshot, which copies them
|
|
# into swarm secrets the bridge container mounts. webhook_hmac is also set on the Gitea webhook.
|
|
bridge_webhook_hmac = { };
|
|
bridge_drone_token = { };
|
|
bridge_gitea_token = { };
|
|
|
|
# Phase-1c C2: the wildcard TLS cert+key are now sops secrets (in cc-ci-secrets), decrypted at
|
|
# activation to /var/lib/ci-certs/live/{fullchain.pem,privkey.pem} — the exact path the traefik
|
|
# reconcile (modules/proxy.nix) already reads. Replaces the prior operator-drops-a-cert-file step.
|
|
wildcard_cert = {
|
|
path = "/var/lib/ci-certs/live/fullchain.pem";
|
|
mode = "0444"; # leaf+intermediate chain — not secret
|
|
};
|
|
wildcard_key = {
|
|
path = "/var/lib/ci-certs/live/privkey.pem";
|
|
mode = "0400"; # private key — root only
|
|
};
|
|
};
|
|
|
|
# EnvironmentFile for the host exec runner: DRONE_RPC_SECRET rendered from the sops secret.
|
|
templates."drone-runner.env".content = ''
|
|
DRONE_RPC_SECRET=${config.sops.placeholder.drone_rpc_secret}
|
|
'';
|
|
};
|
|
}
|