Passwordless access to PostgreSQL and MySQL
Octelium is a free and open source, self-hosted zero trust access platform. Its database modes authenticate to the upstream on the User's behalf, so nobody receives a password or a connection string, the upstream account is forced by configuration, and every request is authorized and recorded.
- Free and open source
- No passwords distributed
- Works with ordinary clients
kind: Service
metadata:
name: pg-prod
spec:
mode: POSTGRES
port: 5432
config:
upstream:
url: postgres://10.0.4.21:5432
postgres:
user: analytics_ro
database: analytics
auth:
password:
fromSecret: pg-password
sslMode: REQUIREkind: Service
metadata:
name: mysql-prod
spec:
mode: MYSQL
port: 3306
config:
upstream:
url: mysql://10.0.4.30:3306
mysql:
user: reporting
database: sales
auth:
password:
fromSecret: mysql-passwordkind: Policy
metadata:
name: analysts
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.user.spec.type == "HUMAN"
- match: '"analysts" in ctx.user.spec.groups'
- match: ctx.session.status.type == "CLIENT"A unified secure access platform
Databases are one mode of the same platform. Each capability is described in detail below, in the same order.
- Unified access platform
One architecture for client-based zero-config VPN-like access over WireGuard and QUIC tunnels and clientless access over browsers for humans and OAuth2 access for workloads.
Read more - L7-aware access control
Identity-based, application-layer aware ABAC access control with policy-as-code via CEL and OPA, applied on a per-request basis.
Read more - Secretless access
Dynamic secretless access where teams and AI agents access protected infrastructure without ever holding a credential.
Read more - Unified identity management
Teams, workloads and AI agents share the same model for identity management, access control, and auditing.
Read more - Real-time visibility and auditing
OpenTelemetry-native, real-time, application-layer-aware visibility and structured logging.
Read more - GitOps-friendly management
Octelium is administered like Kubernetes. Define your resources in YAML files, store them in a Git repository.
Read more
One architecture for every database you run
Each database is represented by a Service, which is served by an identity-aware proxy that abstracts away the network details of the upstream behind it. People keep using psql, mysql and their usual GUI clients.
- The Service is reached over a client-based WireGuard or QUIC tunnel at a stable private name, so a database's actual host, port and network stop being things anyone has to know.
- An upstream can also be an address that is only reachable from the side of a connected host, which covers databases in other private networks, branch offices and customer environments with no inbound port.
- Protected public databases are covered by the same model, including managed and serverless providers, with TLS to the upstream required by configuration.
kind: Service
metadata:
name: pg-prod
spec:
mode: POSTGRES
port: 5432
config:
upstream:
url: postgres://10.0.4.21:5432
postgres:
user: analytics_ro
database: analytics
auth:
password:
fromSecret: pg-passwordkind: Service
metadata:
name: pg-edge
spec:
mode: POSTGRES
port: 5432
config:
upstream:
url: postgres://pg.branch.local
user: branch-gw
postgres:
user: app
database: app
auth:
password:
fromSecret: pg-edge-passwordkind: Service
metadata:
name: pg-cloud
spec:
mode: POSTGRES
port: 5432
config:
upstream:
url: postgres://db.provider.example:5432
postgres:
user: app
database: main
auth:
password:
fromSecret: pg-cloud-password
sslMode: REQUIRELayer-7 aware access control with policy-as-code
Access is authorized using CEL or Open Policy Agent, against the identity behind the connection and the database request itself rather than the network path it arrived on.
- The database user and database requested by the client are part of the request context for both PostgreSQL and MySQL, and combine with identity and device attributes in the same expression.
- Policies attach to a Service, a Namespace, a User, a Group or a Credential, so production and staging databases can carry different rules without duplicating them per person.
- Zero standing privileges. No permanent admins or superuser Users. All access is explicitly allowed by a Policy that can be tied by time and context.
kind: Policy
metadata:
name: read-only-db
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.request.postgres.connect.user
== "analytics_ro"
- match: '"analysts" in ctx.user.spec.groups'kind: Policy
metadata:
name: reporting-only
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.request.mysql.connect.user == "reporting"
- match: ctx.request.mysql.connect.database == "sales"
- match: '"analysts" in ctx.user.spec.groups'kind: Policy
metadata:
name: production-db
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.user.spec.type == "HUMAN"
- match: ctx.session.status.type == "CLIENT"
- match: ctx.device.status.osType in ["MAC", "LINUX"]
- match: '"dba" in ctx.user.spec.groups'Passwords that are never distributed
The upstream password is stored in the Cluster as a Secret and used by the proxy to authenticate to the database once a connection has been authorized. Nobody receives it, so there is no connection string to rotate across laptops and scripts when someone leaves.
- The Service forces the upstream database user and the database regardless of what the client supplies, which removes shared accounts as a practical concern rather than a policy exception.
- Dynamic configuration maps groups to different upstream accounts, databases and credentials on the same Service, so an analyst lands on a read-only account and an administrator on a writing one.
- TLS to the upstream can be required by configuration, independently of what the downstream client asked for.
octeliumctl create secret pg-password
# Or from a file
octeliumctl create secret \
--file /path/to/password \
pg-password
# Users never receive the value.kind: Service
metadata:
name: pg
spec:
mode: POSTGRES
port: 5432
config:
upstream:
url: postgres://10.0.4.21:5432
postgres:
user: analytics_ro
database: analytics
auth:
password:
fromSecret: pg-ro-password
dynamicConfig:
configs:
- name: writer
upstream:
url: postgres://10.0.4.21:5432
postgres:
user: app_rw
database: analytics
auth:
password:
fromSecret: pg-rw-password
rules:
- condition:
match: '"dba" in ctx.user.spec.groups'
configName: writerkind: Service
metadata:
name: pg-prod
spec:
mode: POSTGRES
port: 5432
config:
upstream:
url: postgres://10.0.4.21:5432
postgres:
user: analytics_ro
database: analytics
auth:
password:
fromSecret: pg-password
sslMode: REQUIREA unified identity model for humans and workloads
Human and workload Users share the same identity management, authentication, access control and visibility model. A migration job, an ETL run and an AI agent reaching a database are all identities rather than copies of a connection string.
- Workloads authenticate with authentication tokens, with the OAuth2 client credentials flow, or secretlessly with federated OIDC assertions from GitHub Actions, cloud providers and Kubernetes clusters.
- People authenticate through any OpenID Connect or SAML 2.0 identity provider, with native FIDO2 and WebAuthn passkeys, TOTP and TPM 2.0 authenticators available on top of it.
- An agent can be given its own identity and its own upstream account, so what it may read is a Policy decision rather than whichever credential it was handed.
- Cordium, built on Octelium, provides isolated sandboxes for agents and developers, where processes reach authorized Services through the Workspace identity with no secrets inside the sandbox.
kind: IdentityProvider
metadata:
name: github-actions
spec:
oidcIdentityToken:
issuerURL: https://token.actions.githubusercontent.com
audience: https://example.comkind: User
metadata:
name: migrations
spec:
type: WORKLOAD
groups:
- cikind: Policy
metadata:
name: agent-read-only
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.user.spec.type == "WORKLOAD"
- match: '"agents" in ctx.user.spec.groups'
- match: ctx.request.postgres.connect.database
== "analytics"Queries attributed to a person, not an account
Every request produces an AccessLog identifying the User, Session and Device alongside the application-layer detail of the database request, emitted in real time to your OpenTelemetry OTLP receivers.
- Because the Service forces the upstream account, a shared database user stops being a gap in the audit trail: the request is still attributed to the identity behind it.
- The same stream covers HTTP requests, SSH session recordings, Kubernetes verbs and MCP and LLM operations, so database access is not audited in a separate system from everything else.
- Logs are exported over OpenTelemetry OTLP in real-time to SIEM providers you already operate.
A scalable platform that also deploys your workloads
A Cluster runs on Kubernetes and uses it to scale its own data plane, place Service proxies across Gateways, and run containerized applications that the Cluster itself deploys.
- Databases, their Services, the Groups that may reach them and the Secrets they use are all YAML in a Git repository, applied with a single octeliumctl apply.
- Managed containers deploy, scale and serve containerized applications as Service upstreams, alongside the database Services those applications reach.
- Management is centralized over the Cluster's gRPC APIs, so onboarding a new database can itself be automated.
$ octeliumctl apply ./cluster
Secret: pg-password Updated
Secret: mysql-password Updated
IdentityProvider: okta Updated
Policy: read-only-db Created
Group: analysts Created
Group: dba Updated
Service: pg-prod.db Created
Service: mysql-prod.db Created
Service: pg-cloud.db Created
Namespace: db Created
Cluster Core resources successfully applied
7 resources created
3 resources updated
ClusterConfig updatedWhat database access has to solve, and what solves each part
Connecting to a database is easy. These are the problems that appear once more than a handful of people and jobs need to, next to the mechanism in an Octelium Cluster that handles each one.
- 01
Getting the password to the right people
Nothing is distributed. The upstream password is stored in the Cluster as a Secret and used by the identity-aware proxy to authenticate to the database once a connection has been authorized.
Read more - 02
Taking it away again
Revoking access is a Policy change or a Session revocation rather than rotating a password on the database and then chasing every laptop, script and connection string that held a copy of it.
Read more - 03
Shared accounts nobody can attribute
The Service forces the upstream database user and database regardless of what the client asks for, so a shared account stops being a gap in the audit trail: each connection is still attributed to the Octelium User behind it.
Read more - 04
Giving different people different rights
Dynamic configuration maps groups to different upstream accounts, databases and credentials on the same Service, so an analyst lands on a read-only account and a database administrator on a writing one.
Read more - 05
Reaching databases that are not routable
A Service upstream can be an address that is only reachable from the side of a connected host, so a database in another private network, a branch office or a customer environment needs no inbound port.
Read more - 06
Hosted and serverless databases
Protected public databases are covered by the same model, with TLS to the upstream forced by configuration, which brings managed providers under the same identity and audit story as internal ones.
Read more - 07
Changing the client tooling
There is nothing to change. People use psql, mysql and ordinary drivers against a stable private name, and applications use their normal connection libraries.
Read more - 08
Being able to show what was run
Every request produces an identity-aware AccessLog with the application-layer detail of the database request, streamed in real time over OpenTelemetry to your own log management and SIEM providers.
Read more
A password vault shortens how long a credential lives in one place. It still hands the credential to whoever asks, and the database still sees one account. Injecting it at the proxy changes both.
The same platform capabilities ship with every deployment, whichever way you use it.
Frequently asked
- Which databases are supported?
- PostgreSQL and MySQL have dedicated application-layer modes, which give per-request authorization, secretless upstream credentials, dynamic configuration and protocol-aware auditing. That covers wire-compatible databases and managed providers as well. Anything else that speaks a TCP protocol can be reached through the generic TCP mode, including databases protected by mutual TLS, though authorization there happens at connection time.
- How do people connect?
- With their normal client. The Service is reached at a stable private name over the client-based tunnel, and the proxy authenticates to the database on the User's behalf. Nothing about psql, mysql, a GUI client or an application driver changes, and no password is entered. For MySQL Services, authorized Users currently connect with an empty password value.
- Can different people get different privileges on the same database?
- Yes. The Service forces an upstream database user and database regardless of what the client asks for, and dynamic configuration selects which upstream, account and credential are used per request from identity and context. One Service can therefore map an analyst group to a read-only account and a database administrator group to a writing one.
- What about hosted databases?
- They are covered by the same model. The upstream is simply a public address, TLS to the upstream can be required with the sslMode field, and the provider password stays in the Cluster as a Secret. That brings managed and serverless providers under the same identity, policy and audit story as internal databases.
- Is the traffic recorded?
- Yes. Each request produces an identity-aware AccessLog with the application-layer detail of the database request, streamed in real time over OpenTelemetry to your own log management and SIEM providers, attributed to the Octelium User, Session and Device behind it rather than to a shared database account.
- Is Octelium free and open source?
- Yes. Octelium is free and open source and is designed for single-tenant self-hosting. There is no proprietary cloud-based control plane, and it is not a limited edition of a separate paid product. An enterprise package is available for organizations that need capabilities such as a web console, SCIM provisioning and secret encryption at rest, and it is free for personal, homelab and evaluation use.
Related solutions
Zero trust SSH
Secretless SSH without distributing keys or operating a PKI, with session recording and embedded SSH for fleets.
Read moreZero trust Kubernetes access
Per-verb Kubernetes authorization with the kubeconfig held by the Cluster rather than handed to a User.
Read moreStrongDM alternative
The same infrastructure access model across SSH, databases and Kubernetes, self-hosted end to end.
Read moreDeploy Octelium on your own infrastructure in minutes
Free and open source. Self-hosted. No vendor lock-in.