Documentation Index
Fetch the complete documentation index at: https://docs.hexclave.com/llms.txt
Use this file to discover all available pages before exploring further.
If you self-host, YOU will be responsible for updating Stack Auth and its dependencies. Security patches, bug fixes, and new features require manual updates on your infrastructure. If you would like premium support to help with this, contact us.
stackauth/server Docker image, which runs the Stack Auth API backend and dashboard in one container.
If you are unsure whether you should self-host, here are some things to consider:
- Complexity: Stack Auth is a complex project with many interdependent services. Self-hosting requires managing these services and ensuring they work together seamlessly.
- Updates: Stack Auth is a rapidly evolving project with frequent feature and fix releases. Self-hosting requires you to manage updates and apply them timely.
- Reliability: Self-hosting requires you to ensure the reliability of your infrastructure. Downtimes and outages can be costly to handle.
- Security: Self-hosting requires ensuring the security of your infrastructure. A compromised service can affect your users.
What You Run
In production, plan for these components:- Stack Auth server: The Docker image that serves the API backend and dashboard. The API is what your application SDKs call. The dashboard is where you manage projects, users, auth methods, and app settings.
- Postgres: Required. Stores Stack Auth data and is migrated by the server image on startup unless you disable migrations.
- Cron scheduler: Required for production. Calls internal maintenance endpoints for email queue processing and database sync jobs.
- Reverse proxy or load balancer: Required for a production deployment. Terminate HTTPS and route traffic to the API and dashboard ports.
- Email provider: Required for production email flows such as magic links, verification, password reset, and invitations. Configure SMTP or use a provider integration from the dashboard.
- Svix: Required only if you use webhooks. You can use Svix Cloud or self-host Svix.
- S3-compatible storage: Required for features that store files or assets.
- ClickHouse: Required for the supported Docker deployment path. The migration script creates ClickHouse databases, tables, views, users, grants, and row policies after Postgres migrations.
- Freestyle and OpenRouter keys: Freestyle is required for custom, manual, or programmatic email sending. OpenRouter is optional and used by AI-assisted dashboard features.
Deploy With Docker
1. Create Postgres and ClickHouse
Use a managed Postgres service for production. The server reads its database URL fromSTACK_DATABASE_CONNECTION_STRING.
Use a managed ClickHouse service or your own ClickHouse cluster. The server reads its ClickHouse URL and credentials from STACK_CLICKHOUSE_URL, STACK_CLICKHOUSE_ADMIN_USER, STACK_CLICKHOUSE_ADMIN_PASSWORD, and STACK_CLICKHOUSE_EXTERNAL_PASSWORD, and the database name from STACK_CLICKHOUSE_DATABASE (defaults to default when unset—set it to match the database you use in ClickHouse).
The ClickHouse admin user must be able to create databases, tables, views, users, grants, and row policies. The migration script creates the analytics_internal database, views in the configured database, and a limited external user used by analytics queries.
For a quick non-production smoke test, you can run both databases locally:
Terminal
STACK_CLICKHOUSE_DATABASE to the same logical database your ClickHouse server uses (for this smoke test, CLICKHOUSE_DB=analytics and STACK_CLICKHOUSE_DATABASE=analytics). If you omit STACK_CLICKHOUSE_DATABASE, the backend defaults to default and will not match a container created only with CLICKHOUSE_DB=analytics.
Do not use the example passwords, open ports, or single-node database layout for production.
2. Create an Environment File
Start from the server environment template, then fill in your production values. At minimum, set:stack-auth.env
STACK_SERVER_SECRET with a stable, high-entropy value and keep it unchanged across deploys:
Terminal
STACK_SEED_INTERNAL_PROJECT_*_KEY values with any stable random values, for example:
Terminal
CRON_SECRET with a stable random value too. Your scheduler uses it to authenticate internal maintenance requests:
Terminal
3. Run the Server
Run the Docker image with the environment file:Terminal
| Service | Container port | Purpose |
|---|---|---|
| Dashboard | 8101 | Admin dashboard for Stack Auth projects |
| API backend | 8102 | API used by the dashboard and your applications |
STACK_RUN_MIGRATIONS=true and STACK_RUN_SEED_SCRIPT=true, then run steady-state application containers with:
4. Run Cron Jobs
The Docker image does not start cron jobs for you. In production, configure exactly one scheduler for each deployment environment to call these internal endpoints with theCRON_SECRET bearer token:
| Endpoint | Purpose |
|---|---|
/api/latest/internal/email-queue-step | Processes queued emails. |
/api/latest/internal/external-db-sync/sequencer | Schedules external database sync work. |
/api/latest/internal/external-db-sync/poller | Polls and advances external database sync work. |
Scheduler
CronJob, systemd timer, or another reliable cron service. If you run multiple application replicas, do not let every replica run its own scheduler against the same database.
5. Put It Behind HTTPS
Expose the dashboard and API through HTTPS with your reverse proxy or load balancer:| Public URL | Proxies to |
|---|---|
https://auth.example.com | dashboard port 8101 |
https://auth-api.example.com | API backend port 8102 |
NEXT_PUBLIC_STACK_DASHBOARD_URL and NEXT_PUBLIC_STACK_API_URL. The API URL must be reachable from browsers, your application servers, and the dashboard.
Keep
NEXT_PUBLIC_STACK_API_URL as the browser-reachable API URL. In the bundled Docker image, the entrypoint sets the dashboard’s server-side API URL to the backend inside the same container, so most deployments should not set API split variables manually. If you run the API and dashboard as separate services outside the bundled image, the codebase also supports NEXT_PUBLIC_BROWSER_STACK_API_URL and NEXT_PUBLIC_SERVER_STACK_API_URL for advanced network layouts.6. Sign In to the Dashboard
Open your dashboard URL and sign in with the seeded admin user fromSTACK_SEED_INTERNAL_PROJECT_USER_EMAIL and STACK_SEED_INTERNAL_PROJECT_USER_PASSWORD.
After you have access, create a project for your application and follow the setup guide. For self-hosted projects, your app must also point the SDK at your API URL:
.env.local
Service Configuration
STACK_EMAILABLE_API_KEY to an Emailable key if you want email validation. Use disable_email_validation only when you intentionally want to skip validation.
The dashboard’s Managed Domain email flow is an operator-managed integration. It requires additional server-side provider credentials such as STACK_RESEND_API_KEY, STACK_DNSIMPLE_API_TOKEN, and STACK_DNSIMPLE_ACCOUNT_ID. If you do not operate that integration, use Custom SMTP or your own Resend API key instead.
Webhooks
If you use webhooks, configure Svix:STACK_SVIX_SERVER_URL empty when using Svix Cloud. Set it when you self-host Svix. If the browser and container need different Svix URLs, also set NEXT_PUBLIC_STACK_SVIX_SERVER_URL to the external URL.
S3-Compatible Storage
Configure S3-compatible storage for features that store assets:AI and Custom Code Features
Some dashboard AI features require OpenRouter:Operations
Upgrades
Before upgrading:- Back up Postgres and any configured object storage.
- Back up ClickHouse if you depend on analytics or external database sync data.
- Pull the new Docker image.
- Run the new image once with migrations enabled.
- Verify dashboard sign-in, project loading, cron jobs, email sending, and any webhook flows you use.
- Roll forward your application containers to the same image.
Health Checks
After deploy, verify:Terminal
Common Issues
The Dashboard Cannot Reach the API
Check thatNEXT_PUBLIC_STACK_API_URL is the public API URL and has no typo or unreachable internal hostname.
Redirects Fail
Add your application origin to the project’s allowed domains in the dashboard. OAuth providers also need callback URLs that point at your self-hosted API URL.Emails Do Not Arrive
Check the email provider configuration, sender domain verification, and any provider logs. For development-only email testing, use the Local Emulator instead of a production self-host deployment.You Cannot Access the Dashboard
If you did not seed an admin user, temporarily enable internal project sign-up and rerun the seed script by restarting a container with seeding enabled:STACK_SEED_INTERNAL_PROJECT_SIGN_UP_ENABLED=false, and prefer a seeded admin user for future deployments.