1Password Authentication — Home Lab

1Password is the single source of truth for all credentials in the home lab. It participates in three distinct authentication modes, each serving a different context. They are independent mechanisms — not a single unified flow.


Mode 1: SSH Authentication (1Password SSH Agent)

Used for: Mac → RPi, Mac → GitHub

The 1Password desktop app runs a built-in SSH agent (Settings → Developer → SSH Agent). The agent exposes a Unix socket and responds to the standard SSH agent protocol:

~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock

~/.zprofile exports SSH_AUTH_SOCK pointing to this socket, so ssh, git, VSCode, and any other SSH agent-aware tool uses 1Password automatically.

When a connection is initiated, the agent presents sshkey.github from the Lab vault, handles the signing challenge (private key never leaves 1Password’s process), and prompts for Touch ID on first use in a session.

~/.ssh/config key settings:

Host *
    IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
    AddKeysToAgent no

Host n8n homeassistant ha rpi rpicm5b 5b
    ForwardAgent yes

Host github.com
    User git

AddKeysToAgent no prevents ssh-add from populating the agent — 1Password manages the key lifecycle directly.

The key: sshkey.github

AttributeValue
Namesshkey.github
TypeEd25519
FingerprintSHA256:KRxIURcQzuXar...
Stored in1Password — Lab vault
Also on disk~/.ssh/id_ed25519 (Mac only; can eventually be removed)

RPi authorized_keys

Each RPi host has sshkey.github’s public key in /home/ops/.ssh/authorized_keys. A legacy RSA pubkey is also present for backwards compatibility. The tim user account on RPis is deprecated — see [ARD07: Account Strategy](../A30-Architectural Decisions/ard07-accounts.md).

Agent forwarding (RPi → GitHub)

With ForwardAgent yes, an ssh command run inside a Mac → RPi session tunnels back to the Mac’s 1Password agent. The Pi’s git or ssh command can reach GitHub without a locally stored key — 1Password signs on the Mac and returns only the signed response.

Note: During provisioning, provision-host.sh Phase 5 does place id_ed25519 (the same sshkey.github private key) on the Pi at /home/ops/.ssh/id_ed25519 using op read (see Mode 2 below). This allows the Pi to reach GitHub independently, without requiring an active forwarded session from the Mac.


Mode 2: op CLI — Interactive (Mac)

Used for: provisioning scripts run from the Mac (provision-host.sh, provision-service.sh, gen-spec.sh)

The op CLI (installed via brew install --cask 1password-cli) integrates with the 1Password desktop app on macOS. When a script calls op, the CLI authenticates via the running desktop app — biometric (Touch ID) in practice, no token required.

The CLI is used in provisioning scripts to:

  • Read the GitHub SSH private key and push it to a Pi during host setup:

    op read "op://Lab/sshkey.github/private key?ssh-format=openssh" \
      | ssh ops@rpicm5b "install -m 600 /dev/stdin /home/ops/.ssh/id_ed25519"
  • Fetch the service account token for the target environment and install it on the Pi (see Mode 3):

    OP_TOKEN=$(op item get "op-service-account" --vault devLab --fields credential --reveal)
  • Read server.* items from the Lab vault to generate servers.yaml.

This mode requires the 1Password desktop app to be running and unlocked. It is not used on the RPi — only on the Mac.


Mode 3: op CLI — Service Account (RPi)

Used for: service deployment on RPi hosts (provision-service.sh, gen-env.sh)

RPi hosts are headless — no desktop app, no biometric auth. Instead, provision-host.sh Phase 5b places a service account token on each host during provisioning:

/home/ops/.op_env   (mode 600)

Contents:

export OP_SERVICE_ACCOUNT_TOKEN=<token>

When op sees OP_SERVICE_ACCOUNT_TOKEN in the environment, it authenticates directly to the 1Password API using that token — no interactive prompt, no desktop app.

The token is scoped to a single vault:

EnvironmentVaultToken item
devdevLabop-service-account in devLab
prodprodLabop-service-account in prodLab

provision-service.sh sources /home/ops/.op_env before calling gen-env.sh, which then calls op item get <service-item> --vault <vault> to read fields prefixed env. and write them as NAME=value pairs to the service’s .env file.

This is how secrets reach running Docker Compose services without ever being committed to the repo.


How the Modes Relate

The three modes are independent. They happen to all use 1Password as the backend, but they use different authentication paths and serve different phases of operation:

ModeAuth pathUsed onWhen
SSH agent1Password desktop app → socketMacEvery SSH/git connection
op CLI interactive1Password desktop app → CLIMacProvisioning from workstation
op CLI service accountOP_SERVICE_ACCOUNT_TOKEN env varRPiService deployment on host

A typical provisioning run exercises all three in sequence:

  1. Mac SSHes into the Pi (Mode 1) to run remote commands
  2. Mac calls op read/op item get (Mode 2) to fetch secrets and push them to the Pi
  3. The Pi later sources .op_env and calls op item get (Mode 3) to generate .env

Vault Layout

VaultPurpose
LabShared items: sshkey.github, server.* host specs
devLabDev secrets: op-service-account, service.* items
prodLabProd secrets: op-service-account, service.* items

  • [ARD04: Secrets Management](../A30-Architectural Decisions/ard04-secrets.md)