Skip to content

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 ​

sh
# 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

# Start the agent and sign up (or log in)
foks ctl start
foks signup

Add these definitions to fnox.toml. Merge them into any existing tables with the same names:

toml
[providers]
foks = { type = "foks", prefix = "/fnox/" }

[secrets]
DATABASE_URL = { provider = "foks", value = "DATABASE_URL" }
sh
# Store a secret and read it back
fnox set DATABASE_URL "postgres://..." --provider foks
fnox get DATABASE_URL

Prerequisites ​

  • The foks CLI on your PATH
  • A running FOKS agent (foks ctl start)
  • A FOKS account, either on the hosted service or your own server

Installation ​

bash
# 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 | sh

See 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.

bash
foks ctl start

2. Sign up or log in ​

bash
foks signup    # new user
foks login     # existing user, new device

3. (Optional) create a team for shared secrets ​

If you want to share secrets with teammates, create a FOKS team:

bash
foks team create my-team
foks team add my-team alice

Each team has its own KV namespace.

4. Configure the provider ​

toml
[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 every foks kv invocation, 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. Relative paths are resolved from the config file that declares the provider. Falls back to FNOX_FOKS_HOME / FOKS_HOME if not set.
  • host — The FOKS server hostname (e.g. foks.app or your self-hosted server). Required for non-interactive bot-token auth (see CI/CD). Falls back to FNOX_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 the FOKS_BOT_TOKEN env var instead, so it isn't checked into your config. Also accepts FNOX_FOKS_BOT_TOKEN.

Referencing secrets ​

toml
[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 ​

bash
# 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 start

Personal vs team secrets ​

Use named provider instances to mix personal and team-scoped secrets in the same config:

toml
[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:

  1. Create a bot token for the user or team the runner should act as.
  2. Add the token to your CI provider's secret store as FOKS_BOT_TOKEN.
  3. Set host in the provider config (or FOKS_HOST env var).
toml
# fnox.toml
[providers]
foks = { type = "foks", prefix = "/fnox/", team = "ops", host = "foks.app" }

[secrets]
DATABASE_URL = { provider = "foks", value = "DATABASE_URL" }
yaml
# .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.sh

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.

Usage notes ​

The provider invokes the FOKS CLI and requires its local agent. Personal and team namespaces are selected by provider configuration. CI needs the host and a bot-token bootstrap.

Troubleshooting ​

"could not connect to the FOKS agent" ​

Start the agent and try again:

bash
foks ctl start
foks ctl status

"no logged-in user" / "not logged in" ​

Sign up or log in:

bash
foks signup    # new account
foks login     # existing account

Secret not found ​

List the keys to confirm the path is what you expect:

bash
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:

bash
foks kv ls --team my-team /

Next steps ​

MIT LicenseCopyright © 2026jdx.dev