Progress Note — 2026-03-02
Session with Claude (Sonnet 4.6) focused on designing and beginning implementation of a homelab automation system for provisioning Raspberry Pi servers and deploying Docker-based services, driven from the macBook admin workstation with secrets stored in 1Password.
Decisions Made
Vault structure — three vaults with clear separation of concern
| Vault | Purpose |
|---|---|
Lab | Environment-agnostic items (GitHub SSH key, shared secrets) |
devLab | Dev-specific secrets + dev service account token |
prodLab | Prod-specific secrets + prod service account token |
Service account tokens are scoped at creation time and cannot be changed. Dev token
reads Lab + devLab; prod token reads Lab + prodLab. This enforces env
isolation at the 1Password API level — a dev host cannot access prod secrets even
if the script is run incorrectly.
1Password item naming conventions
- Item names use period delimiter:
host.rpicm5b,service.n8n - Fields intended as env vars are prefixed
env.: e.g.env.POSTGRES_PASSWORD - Service account token item is named
op-service-accountin bothdevLabandprodLab - GitHub SSH key lives in
Labvault
Two provisioning scripts, not one
provision-host.sh— prepares a bare host (apt, Docker, 1Password CLI, SSH key, git clone)provision-service.sh— deploys a named service to an already-prepared host
Rationale: a host is prepared once; multiple services may be deployed to it over time.
Repo as service catalog
A service is supported if and only if services/<name>/ exists in the repo.
Adding support for a new service requires no changes to the provisioning scripts.
Admin username — ops (not tim, not admin)
Generic, non-personal, not on the nose. Consistent across all environments (different usernames per env was considered and rejected — OP token scope already enforces env isolation more reliably).
Secrets stay on the host
The macBook fetches the service account token from the env-specific vault, passes
it to the host via OP_SERVICE_ACCOUNT_TOKEN in the SSH command. The host then
fetches secrets directly from 1Password and writes .env locally. Secrets never
travel over the SSH connection.
install command for file placement
Standard Unix coreutils command — copies a file to a destination and sets permissions/ownership atomically. Used throughout the scripts for placing keys and config files with correct permissions in one step.
Work Completed
- Created
STRATEGY.mddocumenting vision, vault structure, naming conventions, provisioning flow, and open questions - Created
provision-host.sh— 7-phase host preparation script - Created
provision-service.sh— 3-step service deployment script - Created
common/lib.sh— sharedlog(),die(),vault_for_env()functions - Created
common/gen-env.sh— fetchesenv.*fields from 1Password, emits.env - Created
services/n8n/directory (moveddocker-compose.ymlin) - Placed GitHub SSH key on
rpicm5bfrom 1Password viaop readpipe +install - Verified GitHub SSH authentication from
rpicm5b(Hi corneo!) - Renamed
op-service-accounttoken item in 1Password; rebuilt tokens with correct vault scope after renamingdevvault toLab
Immediate Next Steps
- Rebuild
rpicm5bimage with usernameops(currentlytim— scripts expectops) - Run
provision-host.sh --env dev --host rpicm5bas first real test of the script - Run
provision-service.sh --env dev --host rpicm5b --service n8n - Confirm prod vault name and update
lib.shTODO
Open Questions (carried forward)
See STRATEGY.md for full list. Key ones:
- Repo rename —
n8n-server-setup→ something more general (e.g.homelab)? - Secret merging — host-level and service-level items combined or separate
.env? - SSH auth — how does macBook authenticate post-flash (pre-placed key assumed)?