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:
- Docker (v20.10+)
- Docker Compose (v2.0+)
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:7496to the backend service to access OIDC endpoints directly.
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
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
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
| Component | Role |
|---|---|
| Shyntr Identity Hub | Core backend handling protocol translation, token issuance, and security |
| Auth Portal | User-facing UI for login, consent, and logout flows |
| Dashboard | Admin interface for managing tenants, clients, and IdP connections |
| PostgreSQL | Persistent storage for configuration, sessions, and tokens |
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
The example uses placeholder secrets. For production:
- Generate a cryptographically random
APP_SECRET(exactly 32 bytes) - Use strong PostgreSQL passwords
- Generate new RSA keys
openssl rand -hex 16
2. Update Environment Variables
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
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.
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:
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
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
- Open http://localhost:3274
- Navigate to Clients → Create Client
- 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
| Endpoint | Service | Description |
|---|---|---|
http://localhost:7496/health | Identity Hub | Liveness check |
http://localhost:7496/ready | Identity Hub | Readiness 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
- Configure Environment Variables for your deployment
- Learn the CLI Reference for management commands
- Set up custom Headless Login & Consent UIs
- Explore Multi-Tenancy for SaaS deployments