Skip to main content
Version: Next

Running with Docker Compose

This guide covers deploying the complete Shyntr ecosystem using Docker Compose. It spins up the core database, the Identity Hub backend, the management Dashboard, and the user-facing Auth Portal.

Prerequisites

Ensure you have installed:

Quick Start Deployments

Shyntr provides two official deployment topologies depending on your environment needs.

Option A: Standard Local Setup (Direct Access)

Best for rapid local development. Uses direct port mapping. Use the docker-compose.local.yml file:

  • Dashboard: http://localhost:3274
  • Auth Portal: http://localhost:3000
  • Identity Hub (Internal/Exposed): Add port mappings 7496:7496 to the backend service to access OIDC endpoints directly.
docker-compose.local.yml
services:
# ----------------------------------------
# 1. DATABASE (PostgreSQL)
# ----------------------------------------
postgres:
image: postgres:16-alpine
container_name: shyntr_db
environment:
- POSTGRES_USER=shyntr
- POSTGRES_PASSWORD=secretpassword
- POSTGRES_DB=shyntr
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U shyntr" ]
interval: 5s
timeout: 5s
retries: 5
networks:
- shyntr-net

# ----------------------------------------
# 2. SHYNTR IDENTITY HUB (Backend)
# ----------------------------------------
shyntr-backend:
image: shyntr/shyntr:dev
container_name: shyntr-backend
ports:
- "7496:7496" # Public Port (SHYN)
- "7497:7497" # Admin Port (ADMN)
environment:
- GIN_MODE=release
- GO_ENV=production
- DSN=postgres://shyntr:secretpassword@postgres:5432/shyntr?sslmode=disable
- APP_SECRET=12345678901234567890123456789012
- PORT=7496
- ADMIN_PORT=7497
- ISSUER_URL=http://localhost:7496
- EXTERNAL_LOGIN_URL=http://localhost:3000/login
- EXTERNAL_CONSENT_URL=http://localhost:3000/consent
- CORS_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:3274
- ADMIN_CORS_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:3274,http://localhost:7497
- LOG_LEVEL=info
- SKIP_TLS_VERIFY=true # Dev only. TLS behavior only; outbound policy restrictions still apply.
depends_on:
postgres:
condition: service_healthy
networks:
- shyntr-net
healthcheck:
test: [ "CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:7496/health" ]
interval: 10s
timeout: 5s
retries: 5
start_period: 5s
command: >
sh -c "./shyntr migrate && ./shyntr serve"

# ----------------------------------------
# 3. SHYNTR DASHBOARD (React / Nginx)
# ----------------------------------------
shyntr-dashboard:
image: shyntr/shyntr-dashboard:dev
container_name: shyntr_dashboard
ports:
- "3274:80"
environment:
- REACT_MANAGEMENT_BACKEND_URL=http://localhost:7497
- REACT_PUBLIC_BACKEND_URL=http://localhost:7496
depends_on:
shyntr-backend:
condition: service_healthy
networks:
- shyntr-net

# ----------------------------------------
# 4. SHYNTR AUTH PORTAL (Next.js)
# ----------------------------------------
shyntr-auth-portal:
image: shyntr/shyntr-auth-portal:dev
container_name: shyntr_auth_portal
ports:
- "3000:3000"
environment:
- SHYNTR_INTERNAL_API_URL=http://host.docker.internal:7497
- SHYNTR_PUBLIC_API_URL=http://host.docker.internal:7496
depends_on:
shyntr-backend:
condition: service_healthy
networks:
- shyntr-net

# ----------------------------------------
# VOLUMES & NETWORKS
# ----------------------------------------
volumes:
postgres_data:

networks:
shyntr-net:
driver: bridge

Option B: Traefik API Gateway Setup (Production-like)

Best for staging/production or simulating domain-based routing. Uses Traefik as a reverse proxy to route everything through a unified entrypoint (localhost). Use the docker-compose.traefik.yml file:

  • Auth Portal: https://localhost/
  • Dashboard: https://localhost/dashboard
  • Identity Hub API: https://localhost/shyntr
docker-compose.traefik.yml
services:
# ----------------------------------------
# 0. TRAEFIK API Gateway
# ----------------------------------------
traefik:
image: traefik:v3.6
environment:
- TZ=Europe/Istanbul
ports:
- "8080:8080"
- "80:80"
- "443:443"
labels:
- "traefik.enable=true"
- "traefik.docker.network=shyntr-net"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.rule=Host(`localhost`) && (PathPrefix(`/traefik`) || PathPrefix(`/api`))"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.routers.traefik.middlewares=traefik-strip"
- "traefik.http.middlewares.traefik-strip.stripprefix.prefixes=/traefik"
- "traefik.http.routers.root.middlewares=app-context"
- "traefik.http.middlewares.app-context.redirectregex.regex=^https://localhost/?$$"
- "traefik.http.middlewares.app-context.redirectregex.replacement=https://localhost/"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
command:
- "--serverstransport.insecureskipverify=true"
- "--providers.docker=true"
- "--providers.docker.network=shyntr-net"
- "--providers.docker.endpoint=unix:///var/run/docker.sock"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.watch=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.websecure.http.tls=true"
- "--api=true"
- "--api.insecure=true"
- "--api.dashboard=true"
- "--accesslog=true"
- "--log.level=DEBUG"
networks:
- shyntr-net

# ----------------------------------------
# 1. DATABASE (PostgreSQL)
# ----------------------------------------
postgres:
image: postgres:16-alpine
container_name: shyntr_db
environment:
- POSTGRES_USER=shyntr
- POSTGRES_PASSWORD=secretpassword
- POSTGRES_DB=shyntr
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U shyntr" ]
interval: 5s
timeout: 5s
retries: 5
networks:
- shyntr-net

# ----------------------------------------
# 2. SHYNTR IDENTITY HUB (Backend)
# ----------------------------------------
shyntr-backend:
image: shyntr/shyntr:dev
container_name: shyntr_app
ports:
- "7496:7496" # Public Port (SHYN)
- "7497:7497" # Admin Port (ADMN)
environment:
- GIN_MODE=release
- GO_ENV=production
- DSN=postgres://shyntr:secretpassword@postgres:5432/shyntr?sslmode=disable
- APP_SECRET=12345678901234567890123456789012
- PORT=7496
- ADMIN_PORT=7497
- ISSUER_URL=https://localhost/shyntr
- APP_PRIVATE_KEY_BASE64=LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRZ0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1N3d2dna29BZ0VBQW9JQ0FRREhERFR5NlQvQ2dINksKUHY1Z3FBUlRUZ2szU3B5V2JBOTllNU5DamZYb3EvY3ZWR1V2dkkxSmsvU1NwNUk5V3pwY0pvQ2RJWGZteHhOUworc2dhNG1uTCtGTVpYdGhwTnlwOElwS1dhNE5vblN5K3RESVhuTndGZlA4SUU3eGZjb0g3NVpaMTMvNjVyVWUvCnhDVzVmUWNPZ0EyWTNXRStuVW5OVjRKVm9tdmM5NGZHUmpQTHlwMGI1SHZTYkZjZzRxbitZQ0JnVUpXbUtjaW0KangwK3RsTG5UdXFHU3daZEpKMmk5ZDlKa0xBNmpZOWcvZWZxeENjZWs5OFJaOUhiOGZqYVYzYnY2WkRWZHJzRApXVUdyc0tCWHdjSVF3MGphbC9wZ1E5WkoycG1aTGdtcFNNbWF1M2lFOWI4UUora3Q5bXRlemFlQlE1S2krbm9VCmt6SkpiSDZCYzd1MllaM3hqdzZ3SDA5WCtSUnMveVJJSFkxaEtGNjJ2TFIzWHlRVEVlRWdrVW1yR0ZjdlZzY1YKaDV4SkJSWFBLczF1QnNuWkxabGV2VXRUUHJmMGV4ZTZxYXRMcUNKZXV5T1lHSEpvNHlMWHJIdkpoQWluRFFiYQo5VFlLeUxaQTBWUnUzN29KODh0UmxnUlQ3SWt6elJuZTE2VmdFRElidGswdTg0OWhvV3VSc0t5ajJlYUlSS2xQCk44cWQ2M0lxQkhGVXVEeThBWFRkVTNvRFh0ZEJJVlpYSmRlc2ZxQWtqMUZNS3R3QTRRcVZndHRLMUVFWE9tYkIKV3BmZ0VIcitCa3BaWW54MHBhL1BZRVU2MW9CZ0xpZWRaOTdjVlJlVXlsZVRtUzY0d0ZFb3RpVEtHS3pOaHlBOQppcG5HbjRJWU9OZUdkazhPZVA2R2ZrOGpEU0wydFFJREFRQUJBb0lDQUIydVM4ejNEQXRvVnJZdHE0ZmxOZlBvCkhJYXlxUVBqTERJbGRiR0VjcWxWenordkFZR3JSNVF6ckZJY0M3bjdld25Yc2ZEOFZ5RkNDVGNqN3lmWElEaUsKbUhXZGgzNjArN0JVQlhESnFtZzBtOEg2SThnU20xcDBKNkZnTkFRMWtuMXA0RlJHYVBqdUJsZHBtOGg3aE14YwpPdXJUQkJldW81MHJrZU5NRzNKeE5MMVRwWkNiYjI4RDFKVHRrOVp6Qmk5SXpUc2ZlUmswZk5lZFdwcUozSFhpCmRpVTlWYjhZNFNxMktDd1RsN3U3ZFNoYzVETEZPaUljb2JRNk8zaGxMaHI4MU43MGdLVGNGZ25yU3RnYnQrVXUKSHM2YUdDaUVaaERwdksvNW1WTFdveGtyb2VoaFVSamVmaldlQmU3VkluQ2FFUUs4L1VZeFBIZ0o5UU11MnZRVwpTS1c5RExJLzBzL3lCZytqV25sSnZlT1A2Z0pLSEZ5aU16dDhGc0FWa3FES1kxaDFxR05RcEgxSkVNeXc5QW1LCjBwTkxLc3FUOWIrTGI5TUFpWFgwL1plNDZaQWcwSjludlNCczlWaU1HMkc4R092c2ZoVEVEcGtGeUVYM1FjS04KUWFKV3B2eEE5M1ZJZkNzWDdZTlM1YjhFZEhwa2RqQUE0RkRldmliMEc1T05lNTBvdUlaTEtxS1FXR2Z6NHZuegorVVN1eVpCZUhTNHNtK25lYWQ3OXZPQUxVNW9qcjVvRHJna24wem5FaUQ2UTkraFNHc0RnVGpreDdicVpmaEhKClROdkR4MzcvSTAvWk9CTzlwUlU5M0l1Q21TaFpLa0VhdjdwVmdvMEtTaUF5TnpzS0lxUE94enMxVzhRT0FiTmMKWVhCa2ZIRURHS0JpSFk5cUpMMFJBb0lCQVFEdnlLL0xGY0NjVyt5TFY2V1AvMjNUQlJQcHlmdE5hNy96ckdCUApMN0l2NkJYbnJ4OS9rZGEreGh6RkhYMGVyOFRLdlFQcWZyUnlaaFMrWjJ6Y1g3S2NlWFBESlN3T3dnWU5xOGliCnBNLzh0ZnBmbDNaWmdPYXg2bnoxRmw1L1RadnlyMkp0b09EUTBhSElIdGNsd3VDdG40SGRlTmlCVEZyUEZqMGgKdU1QSWZuVmxrZ0xEaWU2aGVDZU9yYlR5bkNuOFpaeXNZNFNBMmVncFArMmNCYzZ1Q3UzZmZ3ekE5bE9WNnBvUgpYaHVTemhiQWdzVEkwYmtvRDNCTTJSdERkNXp0TGUxYkZOWUZ1NHNhVGszNnBJLzJDUlpZdXZnbkJZamU5aWxiCndQZVRXNW10MHlNZzJmMmVRL2dHS1hicDZYOWY0V2htb2YzTGxaNzEwc2I2NVZqNUFvSUJBUURVZ2tQQUcxQWUKNXdFNHJLcmVSNkU5dUk5b21VR2ZoUU5lN2FxbnNFT3hJMU5VWmRSMThvV083cGplTlZseGQ0b2ZubldETTc1NwpXaTFFVnRLOXB0aG43RThqbEVnQ2RISXUyVmpLbVJaYWtSK3h6c2MwRU1NNGduQUtIM0dldjlEcTg3TVNHRDhOCkFTVmk1bnNWbFJ2bmUzYzFES3FJQ0RPK25abWhJN1RHYmx0djZ3Y0lneWtFR3hlR1B6U3laWmp6bnNkb3BDY2cKRHhCUE9mUmcrRSt2ZTdqbnZGT2lVbEVKOUtmcHVmLzZ2SU1nMlRES0k4RGE1UXpCd0xHRHlvTi9MZ1lpMmU1Ngp6TnJ3UkRSUXlmYTZqZlNZQW5yVEVDUHFOTU1HWVlVUFlTOW9ob2tBM3BhMmYyaEFOa2JJVWNyNHFldFpDc3RaClNucDF2bm83QmhhZEFvSUJBRVJHcTYrekdPNHN5cFQrdHZqaXJYM3BzenJkdFgzZEVZSXI4aHg2STAyNjB3bnUKZHBTWGpVTXpIQndRZ29FTFlZaXMrNEY0NUo2eWJIT3U5WE5tbUhBdnNRTy9BT1dPMzdSaTFyTmk0WW8rc3ZVbgpKcDdqc2t5MHpUSG9WYTRBQmtpN0lkYS9lV1JjWEtta0JuVU5JWGF1dFlhL2t6NTE1R0dWSG9FTW9FcmxuejMxCnJtM0pSN2FZaFFMK2VVaWZxT0RpZWhNb0h5R2xhcExjVGljZ0RETElqK1VVd3lmcXUvQXpKZjJPQTJIdzVzK1kKTExwVjVWZi8xV1U4YUtQMFdpMjY1eHdKT2N2V0ZBekFnVG0rUS9PMXNMUkJRTW16ckw1MzcxemQvR0RzTXowbwpvcGNIRzAxR1kwZzE1Rk5FbG0xUnZLMkVzTVNZYlBQb09acFZWZGtDZ2dFQVpualNGcWFWQWZHK2d3ZXY5VE54Ckt3UCtFeUFqcHJwTEg5RlhBemxaeXVjUDNaaWsxS00zaCs3QnhCVFJwb2RRRVdNbG96aW1WM0RxZHhPdTEwakcKL1lYVHU0SmJIdVByMDI5M0EyckNmcldRSlB0aXoxWnQ3S2ZwUXRoYXY0UWJSOUJ2dnYvMkYxMUFHK3FyMjRKbApURUFiQVhlMEc1aG82emV2eHlZaW03VEhYclprVTlSN1NNR1BuR3FLREtRMUZ2U3ZqMlBvZ2VzQm9GSi81dXFWCjhqYWt1UW4xQWtiVFVRdXFsR2ZlYVpmUlcxdWZ6VGxrVzZrcmQ1cGxmdmwrWXl0Y1JoMzBnejZaTEZhWEs0WFgKOWFsU0VxTFBlMHRESmtKKzhHckI4T0thSzdzRUFXbFVIM2hjV3VwUlEzTTlmcDdoSDdTMnpiMitRMXl3TUJvRgplUUtDQVFFQTVHdUhpRGwzOHc2Vnp4UXRxN1crbmdhVDRDVzVIYkQyNHZKTXFHUEhVZXRjWU0zQnpmcUtwbWFsCnBYRFNPYVNsSGc1c1hzamNRTXJrTFlGdW1IU1JhUUFjamZHYUd6c0hFYm1EWWMyZWtLZ2FPdHdha1grUVA0Z1EKQ0xwbXVEZk5RM0I2cXJKVnRyQkwyRS9jamYzZjROdUhmMEExWHlrcDcvTEdkcjdwMlVXQ2Q3Zjk2MDE1UE8wMgpqMkhka1JRanZwcmZrTzBkWFZHTlJKckFGZUlKZTN2dmtsMlRHTkhTTUNkVVVQMHVoT3EwUXRrVEFKbDV1eitZClhBMkpLWXNZekFCeFhXRVBCUlE3WDFBWUVXV1B2QTB0RFVkaTQ4bGtjMnB1L2dVODgra3ZaNGIwTXB4QU5qNHMKR0Z3MllMMkEyQ240ZEw2TWxFUUR3STFkeFBpdmZ3PT0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=
- EXTERNAL_LOGIN_URL=https://localhost/login
- EXTERNAL_CONSENT_URL=https://localhost/consent
- CORS_ALLOWED_ORIGINS=https://localhost
- ADMIN_CORS_ALLOWED_ORIGINS=https://localhost
- LOG_LEVEL=info
- SKIP_TLS_VERIFY=true # Development only. TLS behavior only; outbound policy restrictions still apply.
depends_on:
postgres:
condition: service_healthy
labels:
- "traefik.enable=true"
- "traefik.docker.network=shyntr-net"
- "traefik.http.routers.shyntr-backend.entrypoints=websecure"
- "traefik.http.routers.shyntr-backend.rule=Host(`localhost`) && PathPrefix(`/shyntr`)"
- "traefik.http.routers.shyntr-backend.service=shyntr-backend"
- "traefik.http.routers.shyntr-backend.middlewares=shyntr-backend@docker"
- "traefik.http.services.shyntr-backend.loadbalancer.server.port=7496"
- "traefik.http.middlewares.shyntr-backend.stripPrefix.prefixes=/shyntr"
- "traefik.http.routers.shyntr-admin-backend.entrypoints=websecure"
- "traefik.http.routers.shyntr-admin-backend.rule=Host(`localhost`) && PathPrefix(`/admin`)"
- "traefik.http.routers.shyntr-admin-backend.service=shyntr-admin-backend"
- "traefik.http.routers.shyntr-admin-backend.middlewares=shyntr-admin-backend@docker"
- "traefik.http.services.shyntr-admin-backend.loadbalancer.server.port=7497"
- "traefik.http.middlewares.shyntr-admin-backend.stripPrefix.prefixes=/admin"
networks:
- shyntr-net
healthcheck:
test: [ "CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:7496/health" ]
interval: 10s
timeout: 5s
retries: 5
start_period: 5s
command: >
sh -c "./shyntr migrate && ./shyntr serve"

# ----------------------------------------
# 3. SHYNTR DASHBOARD (React / Nginx)
# ----------------------------------------
shyntr-dashboard:
image: shyntr/shyntr-dashboard:dev
container_name: shyntr_dashboard
environment:
- SHYNTR_MANAGEMENT_BACKEND_URL=https://localhost/admin
- SHYNTR_PUBLIC_BACKEND_URL=https://localhost/shyntr
- SHYNTR_PATH_PREFIX=/dashboard
labels:
- "traefik.enable=true"
- "traefik.docker.network=shyntr-net"
- "traefik.http.routers.shyntr-dashboard.entrypoints=websecure"
- "traefik.http.routers.shyntr-dashboard.rule=Host(`localhost`) && PathPrefix(`/dashboard`)"
- "traefik.http.routers.shyntr-dashboard.service=shyntr-dashboard"
- "traefik.http.routers.shyntr-dashboard.middlewares=add-dash-slash,shyntr-dashboard"
- "traefik.http.services.shyntr-dashboard.loadbalancer.server.port=80"
- "traefik.http.middlewares.shyntr-dashboard.stripPrefix.prefixes=/dashboard"
- "traefik.http.middlewares.add-dash-slash.redirectregex.regex=^(https?://[^/]+/dashboard)(\\?.*)?$"
- "traefik.http.middlewares.add-dash-slash.redirectregex.replacement=$1/$2"
- "traefik.http.middlewares.add-dash-slash.redirectregex.permanent=true"
depends_on:
shyntr-backend:
condition: service_healthy
networks:
- shyntr-net

# ----------------------------------------
# 4. SHYNTR AUTH PORTAL (Next.js)
# ----------------------------------------
shyntr-auth-portal:
image: shyntr/shyntr-auth-portal:dev
container_name: shyntr_auth_portal
environment:
- SHYNTR_INTERNAL_API_URL=http://shyntr-backend:7496
- NEXT_PUBLIC_BACKEND_URL=https://localhost/shyntr
labels:
- "traefik.enable=true"
- "traefik.docker.network=shyntr-net"
- "traefik.http.routers.shyntr-auth-portal.entrypoints=websecure"
- "traefik.http.routers.shyntr-auth-portal.rule=Host(`localhost`)"
- "traefik.http.routers.shyntr-auth-portal.service=shyntr-auth-portal"
- "traefik.http.services.shyntr-auth-portal.loadbalancer.server.port=3000"
depends_on:
shyntr-backend:
condition: service_healthy
networks:
- shyntr-net

# ----------------------------------------
# VOLUMES & NETWORKS
# ----------------------------------------
volumes:
postgres_data:

networks:
shyntr-net:
driver: bridge
Start the Traefik Environment
docker-compose -f docker-compose.traefik.yml up -d

The Shyntr Ecosystem

The Docker Compose setup includes the complete ecosystem:

┌─────────────────────────────────────────────────────────────────┐
│ Shyntr Ecosystem │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Auth Portal │ │ Dashboard │ │
│ │ (Next.js) │ │ (React) │ │
│ │ :3000 │ │ :3274 │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ └───────────┬───────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ Shyntr Identity │ │
│ │ Hub (Go Backend) │ │
│ │ :7496 (Public) │ │
│ │ :7497 (Admin) │ │
│ └────────┬────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ PostgreSQL │ │
│ │ :5432 │ │
│ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

Component Roles

ComponentRole
Shyntr Identity HubCore backend handling protocol translation, token issuance, and security
Auth PortalUser-facing UI for login, consent, and logout flows
DashboardAdmin interface for managing tenants, clients, and IdP connections
PostgreSQLPersistent storage for configuration, sessions, and tokens
Customization

Both the Auth Portal and Dashboard are optional reference implementations. You can:

  • Use them directly out of the box
  • Customize them to match your branding
  • Build your own UIs using the Shyntr APIs

Production Configuration

For production deployments, make these critical changes:

1. Secure Secrets

Change Default Secrets!

The example uses placeholder secrets. For production:

  • Generate a cryptographically random APP_SECRET (exactly 32 bytes)
  • Use strong PostgreSQL passwords
  • Generate new RSA keys
Generation secure APP_SECRET

openssl rand -hex 16

2. Update Environment Variables

Production environment changes
shyntr-backend:
environment:
- GO_ENV=production
- GIN_MODE=release
- APP_SECRET=${SHYNTR_APP_SECRET} # Use environment variable
- ISSUER_URL=https://auth.yourdomain.com
- SKIP_TLS_VERIFY=false # Always false in production!
- COOKIE_SECURE=true # Requires HTTPS
Outbound Request Security

SKIP_TLS_VERIFY only affects TLS certificate verification for outbound HTTPS requests.

Actual outbound access control in Shyntr is enforced separately through policy-based outbound restrictions. Even in development mode, enabling SKIP_TLS_VERIFY does not remove outbound destination validation.

Reverse Proxy & SAML POST Bindings (Crucial)

If you are deploying Shyntr behind a reverse proxy with HTTPS (e.g., Traefik, Nginx, Cloudflare), you MUST set COOKIE_SECURE=true in your environment variables.

Without this, modern browsers will block cross-domain session cookies during SAML POST requests (ACS endpoints) or OIDC callbacks, causing infinite login loops or "session not found" errors.

3. TLS/HTTPS

Use a reverse proxy like Traefik or Nginx for TLS termination:

docker-compose.traefik.yml (with Traefik)
services:
shyntr-backend:
labels:
- "traefik.enable=true"
- "traefik.http.routers.shyntr.rule=Host(`auth.yourdomain.com`)"
- "traefik.http.routers.shyntr.tls=true"
- "traefik.http.routers.shyntr.tls.certresolver=letsencrypt"

4. Database with SSL

Production PostgreSQL
postgres:
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
command: >
-c ssl=on
-c ssl_cert_file=/var/lib/postgresql/server.crt
-c ssl_key_file=/var/lib/postgresql/server.key

Creating Initial Resources

After starting the ecosystem, use the Dashboard or CLI to create resources:

Via Dashboard

  1. Open http://localhost:3274
  2. Navigate to ClientsCreate Client
  3. Configure your OIDC client settings

Via CLI

# Create an OIDC client
docker exec shyntr_app ./shyntr create-client \
--name "My Application" \
--redirect-uris "http://localhost:8080/callback"

# Output:
# Client ID: abc123def456
# Client Secret: secret_xxxxxxxxxxxxxxxx

Logging and Monitoring

View Logs

# All services
docker-compose logs -f

# Specific service
docker-compose logs -f shyntr-backend
docker-compose logs -f shyntr-dashboard
docker-compose logs -f shyntr-auth-portal

# Last 100 lines
docker-compose logs --tail 100 shyntr-backend

Health Endpoints

EndpointServiceDescription
http://localhost:7496/healthIdentity HubLiveness check
http://localhost:7496/readyIdentity HubReadiness check (includes DB)

Troubleshooting

Services Not Starting

# Check container status
docker-compose ps

# Check specific service logs
docker-compose logs shyntr-backend

Database Connection Issues

# Check PostgreSQL is healthy
docker exec shyntr_db pg_isready -U shyntr

# Connect to database
docker exec -it shyntr_db psql -U shyntr

Reset Everything

# Stop and remove all containers, volumes, and networks
docker-compose down -v

# Start fresh
docker-compose up -d

Next Steps