MCP Forge
View Markdown
Production deployment.mdDownload .md

Running Runku in production

This is the checklist for taking Runku past "trying it out" into something pointed at a real database that real agents will use. Read installation.md and auth-and-permissions.md first if you haven't already — this page assumes you have.

1. Initialize a clean production store

Create a new admin store with runku auth init. Save the initial credential in a secrets manager, remove the temporary token file as instructed, and create narrower identities for normal use. Never import credentials from examples or another environment.

2. Generate real credentials, and treat the init token file with care

runku auth init's interactive path writes one initial API key to a plaintext file (.runku-init-token, next to your config.yaml) and prints it once. runku serve refuses to start while that file exists — this is deliberate friction, not a bug to route around:

runku auth init --config config.yaml
# copy the printed token into a real secrets manager / password manager
rm .runku-init-token
runku serve --config config.yaml

Don't script around the refusal (e.g. by auto-deleting the file immediately after init without actually saving the token anywhere) — the whole point is a human deliberately handling the one credential that can never be recovered after this step. Once you have a working initial identity, create narrower, purpose-specific identities and roles for real agents (see auth-and-permissions.md) and consider disabling or rotating the initial one.

3. Prefer OIDC over long-lived API keys where you can

If you already run an identity provider (Keycloak, Okta, Auth0, Entra ID — anything standards-compliant), configure auth.oidc and skip API keys for human-facing or rotating access entirely. runku auth init detects auth.oidc being set and skips API-key generation for exactly this reason. API keys remain the right choice for long-running service agents that can't do an interactive login — just scope each one to a narrow role and rotate it periodically (runku auth apikey create / revoke).

4. Design least-privilege roles before pointing agents at real data

Don't bind every identity to an unrestricted role by default. For each agent or team that will call Runku:

See policy.md for masking and mutation column allow-lists — those apply to every caller regardless of role, and are your first line of defense; per-identity roles are the second.

5. Turn on TLS, or terminate it in front of Runku

# Terminate TLS directly in Runku. Omit this block behind a trusted TLS proxy.
server:
  tls:
    # Require HTTPS on the Runku listener.
    enabled: true
    # Mounted PEM certificate chain and its matching private key.
    cert_file: /etc/runku/tls/cert.pem
    key_file: /etc/runku/tls/key.pem

Or leave it plain HTTP behind a reverse proxy/load balancer that already terminates TLS — either is fine, but don't run bearer tokens or API keys over plaintext HTTP on an untrusted network.

6. Decide on audit durability and shipping deliberately

The stdout audit line is always on and can't be turned off — capture it with whatever your platform already uses for container/process logs. Beyond that:

7. Use a real store backend appropriate to your deployment shape

PostgreSQL is the recommended production backend for the admin store. It also supports high availability and multiple runku serve instances sharing one admin database:

# Production admin store for policies, roles, identities and API-key hashes.
store:
  # PostgreSQL supports backups, HA and multiple Runku instances.
  driver: postgres
  # Dedicated admin-database DSN supplied through the environment.
  dsn: ${RUNKU_MCP_STORE_DSN}

Keep the DSN in the environment or your secrets manager, require TLS when the database is remote, and back up the PostgreSQL database using your normal database backup process.

SQLite remains supported for small, single-instance installations where its simpler operational model is preferable.

8. Back up the right files

None of these are the target database Runku protects — back that up the way you already do, independently.

9. Apply policy changes without downtime

runku policy apply --file policy.yaml <connector-id>
kill -HUP <pid>

SIGHUP reloads policy and role/identity bindings from the admin store in place — no restart, no dropped connections mid-request. Build this into your deployment tooling rather than restarting the process for every policy change.

10. Verify before you trust it

Before pointing real agents at a real deployment: confirm masked columns genuinely don't appear anywhere (schema, results, schema_overview, audit log — try filtering by one, it should be rejected); confirm a restricted identity is actually restricted (attempt something it shouldn't be able to do, confirm it's blocked and logged); confirm runku serve refuses to start with a stale .runku-init-token file present. Perform these checks after every upgrade and configuration change.