FOKS
Integrate with FOKS — the Federated Open Key Service — to store secrets in an end-to-end encrypted, self-hostable key-value store. Secrets are encrypted on the client; the server only ever sees ciphertext.
FOKS pairs well with fnox for teams that want their secrets manager to be open source, federated, and free of cloud-vendor lock-in. The hosted instance at foks.app and self-hosted FOKS servers behave identically. fnox just shells out to the foks CLI either way.
Quick Start
# 1. Install the foks CLI
brew install foks # macOS / Linuxbrew
# or: curl -fsSL https://pkgs.foks.pub/install.sh | sh && apt-get install foks # Debian/Ubuntu
# 2. Start the agent and sign up (or log in)
foks ctl start
foks signup
# 3. Configure the FOKS provider
cat >> fnox.toml << 'EOF'
[providers]
foks = { type = "foks", prefix = "/fnox/" }
[secrets]
DATABASE_URL = { provider = "foks", value = "DATABASE_URL" }
EOF
# 4. Store a secret and read it back
fnox set DATABASE_URL "postgres://..." --provider foks
fnox get DATABASE_URLPrerequisites
- The
foksCLI on yourPATH - A running FOKS agent (
foks ctl start) - A FOKS account, either on the hosted service or your own server
Installation
# macOS (Homebrew)
brew install foks
# Debian / Ubuntu
curl -fsSL https://pkgs.foks.pub/install.sh | sh
apt-get install foks
# Fedora
curl -fsSL https://pkgs.foks.pub/install.sh | sh
dnf install foks
# Arch Linux (AUR)
yay -Sy go-foks
# Windows
winget install foks
# Static binary (any platform)
curl -fsSL https://pkgs.foks.pub/install-static.sh | shSee foks.pub for the most up-to-date instructions.
Setup
1. Start the agent
The foks CLI talks to a long-running agent that holds your keys in memory (similar to ssh-agent). Start it once per machine; it persists across logins via launchd / systemd / the Windows Registry.
foks ctl start2. Sign up or log in
foks signup # new user
foks login # existing user, new device3. (Optional) Create a team for shared secrets
If you want to share secrets with teammates, create a FOKS team:
foks team create my-team
foks team add my-team aliceEach team has its own KV namespace.
4. Configure the provider
[providers]
foks = { type = "foks", prefix = "/fnox/" }Configuration options (all optional):
prefix— Path prefix prepended to every key (must be absolute, e.g./fnox/or/apps/myapp/). FOKS rejects relative paths; if you forget the leading/, the provider adds it for you.team— A FOKS team name. When set, fnox passes--team <name>to everyfoks kvinvocation, so secrets read and write to that team's namespace instead of your personal one.home— A custom FOKS home directory, passed through as--home. Falls back toFNOX_FOKS_HOME/FOKS_HOMEif not set.host— The FOKS server hostname (e.g.foks.appor your self-hosted server). Required for non-interactive bot-token auth (see CI/CD). Falls back toFNOX_FOKS_HOST/FOKS_HOST.bot_token— A FOKS bot token for non-interactive auth (CI). Almost always you want to leave this unset and supply it via theFOKS_BOT_TOKENenv var instead, so it isn't checked into your config. Also acceptsFNOX_FOKS_BOT_TOKEN.
Referencing Secrets
[secrets]
DATABASE_URL = { provider = "foks", value = "DATABASE_URL" }
API_KEY = { provider = "foks", value = "API_KEY" }The value is the key path within the FOKS KV store, joined with the provider's prefix. With prefix = "/fnox/", value = "DATABASE_URL" resolves to foks kv get /fnox/DATABASE_URL.
Usage
# Store a secret (FOKS encrypts it client-side before upload)
fnox set DATABASE_URL "postgres://..." --provider foks
# Fetch it
fnox get DATABASE_URL
# Run a command with secrets injected as env vars
fnox exec -- npm startPersonal vs Team Secrets
Use named provider instances to mix personal and team-scoped secrets in the same config:
[providers]
me = { type = "foks", prefix = "/fnox/" }
ops = { type = "foks", prefix = "/fnox/", team = "ops" }
[secrets]
PERSONAL_TOKEN = { provider = "me", value = "github-token" }
DATABASE_URL = { provider = "ops", value = "db/primary" }
DEPLOY_KEY = { provider = "ops", value = "deploy/key" }PERSONAL_TOKEN is read from your personal namespace; the rest are read from the ops team's namespace and stay accessible to teammates.
CI/CD
For non-interactive environments, configure the provider with a host and let fnox handle authentication via a FOKS bot token. On the first auth failure, the provider runs foks bot use --host <host> with the token from the FOKS_BOT_TOKEN env var, then transparently retries.
Setup:
- Create a bot token for the user or team the runner should act as.
- Add the token to your CI provider's secret store as
FOKS_BOT_TOKEN. - Set
hostin the provider config (orFOKS_HOSTenv var).
# fnox.toml
[providers]
foks = { type = "foks", prefix = "/fnox/", team = "ops", host = "foks.app" }
[secrets]
DATABASE_URL = { provider = "foks", value = "DATABASE_URL" }# .github/workflows/deploy.yml
jobs:
deploy:
runs-on: ubuntu-latest
env:
FOKS_BOT_TOKEN: ${{ secrets.FOKS_BOT_TOKEN }}
steps:
- uses: actions/checkout@v4
- run: brew install foks
- run: foks ctl start
- run: fnox exec -- ./deploy.shfnox runs foks bot use the first time the agent reports it's not authenticated, then retries the failed kv call once.
If you'd rather keep host out of fnox.toml, set it via FOKS_HOST in the workflow env. Likewise, bot_token can live in the config (encrypted with a bootstrap provider like age) instead of the env var, but the env var is usually simpler.
Pros
- ✅ End-to-end encrypted — the FOKS server never sees plaintext
- ✅ Open source and self-hostable
- ✅ Federated: a self-hosted FOKS server interoperates with the hosted service
- ✅ Teams have first-class shared namespaces
- ✅ Hierarchical KV paths and multiple devices per identity
Cons
- ❌ Newer / smaller ecosystem than Vault, AWS Secrets Manager, etc.
- ❌ Requires the
foksagent to be running locally - ❌ CI integration requires a bot-token bootstrap step
Troubleshooting
"could not connect to the FOKS agent"
Start the agent and try again:
foks ctl start
foks ctl status"no logged-in user" / "not logged in"
Sign up or log in:
foks signup # new account
foks login # existing accountSecret not found
List the keys to confirm the path is what you expect:
foks kv ls /
foks kv ls /fnox/ # if you set prefix = "/fnox/"If you set a team in your provider config, scope the listing to the team:
foks kv ls --team my-team /Next Steps
- HashiCorp Vault — Closest comparable self-hosted alternative
- password-store — GPG-based local alternative
- Real-World Example — Complete setup walkthrough