Files
oikos/secrets
root 65ece6f447 secrets: distribute write-scoped Gitea PAT + homelab refresh-creds
Adds secrets/gitea-pat.yaml (SOPS-encrypted, dtoro PAT with read+write
scopes) so any enrolled client can push to dtoro/Homelab-Docs — not just
where I have SSH. Recipient set = hello.yaml's (hubris, apps, republic);
expand alongside hello.yaml when enrolling new clients.

bin/homelab gains 'refresh-creds': decrypts gitea-pat.yaml, rewrites
/etc/homelab-context/git-credentials with the write token, repoints
git's --system credential helper. Re-execs via sudo for non-root callers
(same pattern as 'homelab secret').

After this lands, 'homelab client add/remove' and wiki edits can run
from any client. The initial bootstrap still needs an operator-supplied
read-only PAT (chicken-and-egg); 'refresh-creds' upgrades the client
to write afterwards.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:25:36 +02:00
..

secrets/

SOPS-encrypted YAML files. The plaintext lives only in transit and in the operator's head — committed files are always ciphertext.

Conventions

  • One file per logical grouping (e.g. gitea-tokens.yaml, webhook-hmacs.yaml, api-keys.yaml).
  • Recipients are declared in ../.sops.yaml by path-regex, not per-file.
  • The plaintext schema inside each file is free-form YAML; the consumer code decides what it expects (e.g. gitea-tokens.yaml contains {"<host>": "ghp_xxx"}).

How to add a secret

# 1. Decide which clients should be able to decrypt it; edit ../.sops.yaml to
#    list their age public keys for the new path_regex.
# 2. Create the plaintext, encrypt in place:
sops -e --in-place secrets/my-thing.yaml
# 3. Commit + push. The 5-min sync propagates to every recipient.

How to consume a secret

# On any client that's a recipient:
homelab secret my-thing               # prints plaintext
# Or programmatically:
sops -d /opt/homelab-context/secrets/my-thing.yaml

The mcp tool list_my_secrets(caller_pubkey) returns the names of secrets the caller can decrypt. The MCP server never reads plaintext — decryption stays client-side.

Granting / revoking access

To grant a new recipient: edit ../.sops.yaml to add their age pubkey, then re-key every affected file:

sops updatekeys -y secrets/my-thing.yaml

To revoke: remove the recipient from ../.sops.yaml and sops updatekeys — but remember this only protects future ciphertext. Past plaintext the client already decrypted is gone from your control. Rotate the underlying credential if compromise is suspected.

homelab client remove <name> does the recipient removal + updatekeys for you, and prints the rotation checklist as a follow-up.

hello.yaml — bootstrap decrypt test

secrets/hello.yaml is encrypted to every enrolled client. Used by Phase 3a verification to confirm the end-to-end decrypt path works on a freshly- bootstrapped machine. Content is intentionally trivial:

greeting: hello from the homelab