Skip to main content

SSO: Deploying the SSO Application

  • The SSO application is distributed as a single Docker image (ravendb/sso) that bundles Nginx, the authentication sidecar, and oauth2-proxy.

  • The ravendb/sso repository ships with an interactive installer (install.sh for Linux/macOS, install.ps1 for Windows) that asks all the questions, pre-flights DNS and host permissions, generates a complete deployment directory, and optionally starts the stack. This is the recommended way to set up a new SSO application.

Use the installer

Unless you have a specific reason to assemble the deployment by hand (for example because you're integrating into existing automation), run install.sh / install.ps1.
The installer produces the same artifacts that the manual setup below describes, but with secrets generated for you, file permissions set, and DNS sanity-checked.

Prerequisites

  • Docker (Compose v2).
  • A public domain you control, with the ability to create DNS records.
  • At least one of:
    • OAuth credentials for GitHub, Google, or Microsoft/Entra ID, or
    • A Kerberos keytab for an Active Directory service principal.
  • For the bundled Let's Encrypt option: an AWS account with Route53 hosting the SSO domain and an IAM user authorized to create TXT records (DNS-01 challenge). The installer can also wire up a manually-supplied certificate instead.

DNS setup

The SSO application is reached at a base domain (e.g. sso.example.com). Each RavenDB cluster behind it is exposed at <cluster-alias>.<sso-domain> - for example my-cluster.sso.example.com. You therefore need both an apex record and a wildcard for sub-aliases:

TypeNameValue
Asso.example.comyour server's public IP
CNAME*.sso.example.comsso.example.com

The installer probes both records before continuing and will warn (but not block) if they are missing.

The installer is a single self-contained script - every template it writes (including nlog.config and the docker-compose.yml) is embedded inline, so you can download and run it directly without cloning the repository.

Download and run:

curl -fsSL https://ravendb-build-assets.s3.us-east-1.amazonaws.com/Sso/install.sh -o install.sh
chmod +x install.sh
./install.sh

Or pipe directly into Bash:

bash <(curl -fsSL https://ravendb-build-assets.s3.us-east-1.amazonaws.com/Sso/install.sh)

If you'd rather have the rest of the repository (for the manual example/ deployment, source, or tests), clone it and run the script from there instead:

git clone https://github.com/ravendb/sso.git && cd sso && ./install.sh

The script walks through the following steps:

  1. Output directory - defaults to ./sso-deploy. Must be empty.
  2. Host user check (Linux only) - verifies that UID 10000 exists; offers to create the ravendb-sso system user (the SSO container runs as 10000:10000).
  3. SSO URL - your public https://sso.example.com.
  4. DNS sanity check - resolves the apex A record and probes a random subdomain to confirm the wildcard CNAME is in place.
  5. TLS certificate strategy - pick certbot-route53 (automated Let's Encrypt via Route53 DNS-01) or manual (you supply fullchain.pem and privkey.pem).
  6. Authentication providers - multi-select between GitHub, Google, Microsoft/Entra ID, and Kerberos. Each selected provider expands into its own credential prompts.
  7. Kerberos files (if Kerberos was chosen) - paths to krb5.conf and krb5.keytab. On Linux the script verifies that UID 10000 can read both files and offers to apply an ACL (setfacl -m u:10000:r) if not.
  8. Clusters - for each RavenDB cluster, an alias (lowercase letters, digits, hyphens) and one or more node URLs (HTTPS only).
  9. Summary and confirmation, then file generation.

What the installer produces

The installer generates a self-contained deployment directory:

sso-deploy/
sso.env # SSO secrets - mode 600
certbot.env # AWS creds + LE email (only if cert mode = certbot) - mode 600
docker-compose.yml # Two services if certbot, one if manual certs
config/
settings.json # Generated cluster topology
nlog.config # Copied from the example
certs/ # Pre-created, owned by UID 10000 (populated by certbot or pre-staged)
logs/ # Pre-created, owned by UID 10000
README-deploy.md # Per-deployment quick reference

OAUTH2_PROXY_COOKIE_SECRET is generated automatically (32 hex chars). config/, certs/, and logs/ are chowned to 10000:10000 so the container can write to them. After the script finishes, start the stack from the generated directory:

cd sso-deploy
docker compose up -d

As its final step, the installer offers to run docker compose up -d for you.

Manual deployment with Docker Compose

If you can't or don't want to run the installer, the example under Raven.Sso/example/ in the ravendb/sso repository is the same layout the installer generates, just filled in by hand. The compose file runs two containers:

  • certbot - certbot/dns-route53. Obtains the wildcard certificate on first start and renews every 12 hours.
  • sso - ravendb/sso:latest. Starts once certbot has produced a valid certificate, and reloads Nginx every 6 hours to pick up renewals.

1. Copy and fill the environment files

The example splits environment variables into two files so AWS credentials aren't exposed to the SSO container:

cp sso.env.example sso.env
cp certbot.env.example certbot.env

Edit each file with your domain, OAuth credentials, and AWS keys. The complete list of variables is on the SSO application configuration page.

2. (Optional) Configure clusters via settings.json

The list of RavenDB clusters the SSO application should proxy can live in config/settings.json:

{
"Clusters": [
{
"ClusterUrls": ["https://a.my-cluster.example.com"],
"ClusterAlias": "my-cluster"
}
]
}

Alternatively, set RAVENDBSSO_Clusters in sso.env to the same JSON array - environment variables override file values.

3. Start the stack

docker compose up -d

On first run, certbot requests the wildcard certificate from Let's Encrypt; this can take 1–2 minutes while the DNS TXT record propagates. The SSO container's depends_on waits for certbot to report healthy before starting Nginx.

Use RSA keys

The example's certbot entrypoint pins --key-type rsa. RavenDB's certificate utilities only support RSA; do not switch this to ECDSA.

4. Volumes and on-host layout

The deployment maps these host directories into the containers:

example/
sso.env # SSO env vars
certbot.env # certbot env vars
docker-compose.yml
config/
settings.json # optional - clusters can come from env vars instead
nlog.config # optional - logging configuration (autoReload)
certs/ # populated by certbot
live/<domain>/
fullchain.pem
privkey.pem
logs/ # SSO + Nginx logs

Quick start (single container)

For local testing without Let's Encrypt, build the image directly and pass credentials on the command line:

docker build -t ravendb/sso .

docker run --rm -it \
-p 8080:8080 \
-e OAUTH2_PROXY_COOKIE_SECRET=$(openssl rand -base64 32) \
-e GITHUB_CLIENT_ID=... \
-e GITHUB_CLIENT_SECRET=... \
-e GOOGLE_CLIENT_ID=... \
-e GOOGLE_CLIENT_SECRET=... \
-e MICROSOFT_CLIENT_ID=... \
-e MICROSOFT_CLIENT_SECRET=... \
-e MICROSOFT_TENANT=common \
-v /path/to/app.keytab:/etc/nginx/app.keytab:ro \
-v /path/to/krb5.conf:/etc/krb5.conf:ro \
ravendb/sso

Any combination of providers can run concurrently. Volumes for the keytab and krb5.conf are only needed when using Kerberos.

After login, the SSO portal lists the clusters the user can reach - each cluster is exposed under its own sub-alias of the SSO domain:

SSO cluster picker

Registering OAuth providers

For every OAuth provider you enable, the redirect URI is https://<sso-domain>/oauth2/<provider>/callback.

GitHub

  1. Open GitHub Settings → Developer settings → OAuth Apps.
  2. New OAuth App.
  3. Set Homepage URL to your SSO URL and Authorization callback URL to https://<sso-domain>/oauth2/github/callback.
  4. Generate a client secret. Set GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET.

Google

  1. In Google Cloud ConsoleAPIs & Services → Credentials, create an OAuth 2.0 Client ID of type Web application.
  2. Add https://<sso-domain>/oauth2/google/callback to Authorized redirect URIs.
  3. Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET.

Microsoft / Entra ID

The SSO image uses oauth2-proxy's entra-id provider, which supports both single-tenant and multi-tenant apps.

  1. In Azure Portal → App registrations, click New registration.
  2. Pick Supported account types - single-tenant, multi-tenant, or multi-tenant + personal accounts. This must match the MICROSOFT_TENANT value you choose.
  3. Set Redirect URI (Web) to https://<sso-domain>/oauth2/microsoft/callback.
  4. Under Token configuration, add email as an optional claim for the ID token - organizational accounts don't emit it by default, and the SSO application uses it as the username.
  5. Under Certificates & secrets, create a client secret.
  6. Set MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET, and MICROSOFT_TENANT:
    • Single-tenant: your tenant GUID.
    • Multi-tenant (orgs only): organizations.
    • Multi-tenant + personal accounts: common.
  7. For multi-tenant apps, scope access by setting MICROSOFT_ALLOWED_TENANTS (comma-separated tenant GUIDs) and / or MICROSOFT_ALLOWED_EMAIL_DOMAINS. Without these allowlists a multi-tenant app accepts any organization's users.

oauth2-proxy requires an encryption key for its session cookie.

# Single-container quick-start (32-byte base64):
openssl rand -base64 32

# docker-compose example (16/24/32-char hex):
openssl rand -hex 16

Set the result as OAUTH2_PROXY_COOKIE_SECRET.

Kerberos / Active Directory

On a domain controller (or with delegated rights):

# 1. Create a service account, e.g. svc_docker, then map an SPN to it:
setspn -A HTTP/app.domain.com svc_docker

# 2. Export a keytab:
ktpass /princ HTTP/app.domain.com@DOMAIN.COM `
/mapuser DOMAIN\svc_docker `
/pass YourPassword123 `
/out C:\temp\app.keytab `
/crypto All `
/ptype KRB5_NT_PRINCIPAL

Mount the keytab at /etc/nginx/app.keytab and supply a Kerberos client config at /etc/krb5.conf:

[libdefaults]
default_realm = DOMAIN.COM
dns_lookup_kdc = true
dns_lookup_realm = false

[realms]
DOMAIN.COM = {
kdc = dc01.domain.com
admin_server = dc01.domain.com
}

[domain_realm]
.domain.com = DOMAIN.COM
domain.com = DOMAIN.COM

If Kerberos auth fails or isn't available, Nginx falls back to OAuth automatically.

Logs

All logs are written under /app/logs/ inside the container - mount the directory to keep them on the host:

FileSourceContent
app.logNLog (rotating, 7-day retention)Startup, certificate generation, cluster polling, errors
audit.logNLog (rotating, 30-day retention)Login success/failure, access denied, logout - with user and client IP
app.out.logstdoutRaw .NET process stdout
app.err.logstderrRaw .NET process stderr
nginx-access.logNginxStandard combined access log
nginx-error.logNginxErrors and warnings
nginx-audit.logNginxPer-request audit log - real client IP, authenticated user, target host, status, response time

nlog.config is loaded from /app/config/nlog.config at startup with autoReload="true", so log levels can be changed without restarting the container.

Troubleshooting

Common symptoms and their likely causes:

SymptomLikely cause
certbot fails with a Route53 errorAWS credentials or the DNS zone isn't actually in Route53.
sso container exits immediatelyRAVENDBSSO_Url not set in sso.env.
502 Bad Gateway shortly after startupThe .NET sidecar on 127.0.0.1:3000 is still warming up - retry.
Login loops back to the providerWrong callback URL registered, or OAUTH2_PROXY_COOKIE_SECRET length is invalid (must be 16, 24, or 32 chars).

To find the cause of any of these symptoms, check the container logs:

docker logs ravendb-sso # nginx + .NET app
docker logs certbot # certificate issues

Next steps

Once the SSO application is up, register its certificate and create SSO user entries in your RavenDB cluster following SSO Certificates and Users.

In this article