Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.codezero.io/llms.txt

Use this file to discover all available pages before exploring further.

For HTTP routes, Cordon fetches credentials from external secret stores per-request. PostgreSQL listeners currently resolve credentials at startup. Two sources are supported.

1Password

Fetches secrets from 1Password vaults using the 1Password CLI (op).
[routes.auth.secret]
source = "1password"
vault = "Engineering"
item = "Stripe API Key"
field = "secret_key"
FieldDescription
vault1Password vault name (within the currently authenticated account)
itemItem name within the vault
fieldField label within the item (case-sensitive)
Cordon uses whichever 1Password account the op CLI is currently authenticated against. It does not support specifying which account to use — if you have multiple 1Password accounts, ensure the correct one is signed in before starting cordon. Use op whoami to check which account is active and op vault list to see available vaults.

Prerequisites

The op CLI must be installed and authenticated before starting cordon:
# Install (macOS)
brew install --cask 1password-cli

# Sign in (eval exports the session token to your shell)
eval $(op signin)
If op is not on PATH (common for background services), specify the binary path explicitly in the provider config:
[secrets]
[[secrets.providers]]
type = "1password"
path = "/opt/homebrew/bin/op"
For detailed setup, security considerations, and troubleshooting, see the 1Password guide.

OS Keyring

Reads credentials from the operating system’s built-in credential store.
[routes.auth.secret]
source = "keyring"
account = "stripe-api-key"
FieldRequiredDescription
accountyesAccount name (identifier for the credential)
servicenoKeyring service name. Defaults to "cordon" when omitted.
decodenoDecoding strategy for encoded values. Currently supports "go-keyring".
By default, cordon uses cordon as the keyring service name. If you inspect the OS keychain directly (e.g., macOS Keychain Access, security find-generic-password -s cordon), entries appear under the service cordon.

Reading third-party keychain entries

You can use service to read credentials stored by other tools under their own keychain entries, avoiding token duplication. For example, the GitHub CLI (gh) stores its token under service gh:github.com:
[routes.auth.secret]
source = "keyring"
account = "lightcap"
service = "gh:github.com"
decode = "go-keyring"
This reads gh’s token directly — no need to copy it into cordon’s keyring. When gh auth refresh updates the token, cordon picks up the new value automatically.

The decode field

Some tools encode values before storing them in the keychain. The decode field tells cordon how to decode the raw keychain value before using it.
ValueDescription
"go-keyring"Handles encoding from Go’s zalando/go-keyring library. Strips go-keyring-base64: or go-keyring-encoded: prefixes and decodes the remainder. Values without a recognized prefix are used as-is.
decode is only needed when the tool that stored the credential uses an encoding wrapper. Most tools (Python, Rust, native CLI tools) store raw values and don’t need it. The go-keyring encoding is used by Go CLI tools including gh.

Storing keyring credentials

Use cordon secret set to store credentials under the default cordon service. The account name defaults to the route name during cordon route add, so in most cases they match. Use cordon route show <name> to confirm the account name for a route:
cordon secret set stripe
# Prompts for the secret value
On macOS, you can also use the native security CLI:
security add-generic-password -s cordon -a stripe-api-key -w 'sk_live_...'
cordon secret set always stores under the cordon service. When using a custom service to read from a third-party keychain entry, the credential is managed by that tool — you don’t need to store it via cordon.

Platform differences

macOS Keychain enforces per-application access control. The binary that creates a keychain entry owns it and can read it without prompting. Any other binary triggers a system authorization dialog.Use cordon secret set to create entries owned by cordon. Entries created by other tools (e.g., security CLI) will prompt on every request that needs the secret.Upgrading cordon, doing a fresh cargo build during development, or changing the install path changes the binary identity. macOS will prompt for keychain access the first time the new binary reads the secret. When this prompt appears, click Always Allow (not just Allow) to permanently grant the new binary access. Because cordon resolves keyring secrets just-in-time on each request, clicking “Allow” (one-time) means the prompt reappears on the very next request — which can be milliseconds later.In SSH, headless, or detached screen/tmux sessions, the keychain is locked and cannot display a prompt. Run security unlock-keychain ~/Library/Keychains/login.keychain-db first, or run the command from a terminal in a desktop session (directly or via screen sharing) where the login keychain is already unlocked. See Troubleshooting (macOS) for details.
On Linux, cordon uses the D-Bus Secret Service API, typically provided by GNOME Keyring or KDE Wallet. Secrets are encrypted on disk and unlocked with the user’s login session. There are no per-application ACLs — any process running as the user can read entries. Security relies on standard Unix user isolation.A Secret Service provider must be installed and running:
sudo apt install gnome-keyring   # Debian/Ubuntu
After installing, log out and log back in to initialize the default “login” collection. Without this step, cordon secret set will fail with:
DBus error: Object does not exist at path "/org/freedesktop/secrets/collection/login"
A running D-Bus session bus is required — the keyring source does not work in containers, CI, or headless environments.

Troubleshooting (macOS)

The macOS login keychain is locked. This happens in SSH sessions, headless CI, and detached screen/tmux sessions where Keychain cannot display its authorization dialog.Unlock the login keychain before running cordon secret set:
security unlock-keychain ~/Library/Keychains/login.keychain-db
This prompts for your macOS login password. Once unlocked, keychain operations work for the remainder of the session. If you have access to the Mac directly or via screen sharing, run cordon secret set from a terminal in the desktop session instead — the login keychain is already unlocked there.
macOS Keychain enforces per-application access control based on the binary identity. Any change to the cordon binary — upgrades, fresh builds during development, different install paths — triggers a new authorization prompt.Quick fix: Click Always Allow on the macOS Keychain dialog. This permanently grants the new binary access. Do not click just “Allow” — cordon resolves keyring secrets per-request, so a one-time allow triggers a new prompt on every subsequent request.Alternative: Re-store credentials with cordon secret set <account> to make the current binary the entry owner.

Troubleshooting (Linux)

A Secret Service provider is not running or has not initialized its default collection. Fix:
sudo apt install gnome-keyring
Then log out and log back in so the keyring daemon starts and creates the “login” collection.
The D-Bus session bus is not available. Verify it’s reachable:
# Check for session bus address
echo $DBUS_SESSION_BUS_ADDRESS

# Or check for systemd user bus socket
ls $XDG_RUNTIME_DIR/bus
If neither is available, you’re not in a desktop session (e.g., SSH, container, or headless server). The keyring source requires a desktop session.
The Secret Service provider is not responding. Check that gnome-keyring-daemon (or your provider) is running:
ps aux | grep gnome-keyring
If not running, log out and back in, or start it manually:
gnome-keyring-daemon --start --components=secrets

Mixing sources

You can use different secret sources for different routes:
[[routes]]
name = "stripe"

[routes.match]
host = "api.stripe.com"

[routes.auth]
type = "bearer"

[routes.auth.secret]
source = "1password"
vault = "Engineering"
item = "Stripe API Key"
field = "secret_key"

[[routes]]
name = "internal-api"

[routes.match]
host = "api.internal.example.com"

[routes.auth]
type = "api_key"
header_name = "X-Api-Key"

[routes.auth.secret]
source = "keyring"
account = "internal-api-key"