
Deploy Hexclave — Self-Hosted Auth, S3 Storage & Webhooks
Self-hosted auth, teams, analytics, and file uploads with built-in S3.
minio-init
Just deployed
svix-db
Just deployed
MinIO
Just deployed
svix-server
Just deployed
hexclave-cron
Just deployed
hexclave
Just deployed
hexclave-proxy
Just deployed
Just deployed
/var/lib/postgresql/data
ClickHouse
Just deployed
Deploy and Host Hexclave on Railway
Hexclave is a self-hosted authentication and user-management platform (the stackauth/server image) — authentication, teams, RBAC, and analytics — an open, self-hosted alternative to hosted auth providers. This template runs the whole stack on Railway with batteries included: object storage (MinIO) and webhooks (self-hosted Svix) run in the same project, so there are no external service accounts to wire up for the core features. Everything is pre-configured and links together on the first deploy.
About Hosting Hexclave
Hosting Hexclave means running its backend + dashboard server alongside the supporting infrastructure it depends on: a Postgres database, a ClickHouse analytics store, a reverse proxy, a cron worker for background jobs, S3-compatible object storage, and a Svix webhooks engine. This template provisions and connects all of it for you, exposing the dashboard on a single generated domain, with every secret generated per-deploy. You only bring your own SMTP, Freestyle, and AI keys when you want those optional features.
The template also pre-sets STACK_DISABLE_PLAN_LIMITS=true on the hexclave service. Hexclave's paid-plan quota enforcement (analytics-event caps, session-replay limits, email quotas, seat checks) is backed by its cloud-only Bulldozer metering service, which is not part of the self-hosted image. This flag is hexclave's built-in switch to skip those checks before the Bulldozer lookup — without it, opening the Analytics pages fails with a 500 from the quota gate. Leave it enabled when self-hosting.
| Service | Image | Purpose |
|---|---|---|
| hexclave | stackauth/server | The app — auth/teams backend + dashboard |
| hexclave-proxy | Caddy | Reverse proxy — serves the whole app on one public domain |
| hexclave-cron | stackauth/server | Scheduled background jobs |
| Postgres | postgres | Primary database |
| ClickHouse | clickhouse | Analytics event store |
| MinIO + minio-init | minio/minio | S3-compatible object storage |
| svix-db + svix-server | svix/svix-server | Self-hosted Svix webhooks engine |
Why Deploy Hexclave on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
By deploying Hexclave on Railway, you get the entire multi-service stack — app, databases, object storage, and webhooks — provisioned and networked together in one project, instead of manually standing up and connecting seven services yourself. Railway's private networking, generated domains, and per-service variables handle the wiring, so you go from template to a working auth platform in a single deploy.
Common Use Cases
- Self-hosting authentication and user management for your SaaS instead of a paid auth provider.
- Running an internal identity platform with teams, RBAC, and organization management.
- Owning your auth data and infrastructure for compliance or data-residency requirements.
- Delivering webhooks and events to your own services from a self-hosted Svix instance.
Dependencies for Hexclave Hosting
- The
stackauth/servercontainer image (the Hexclave app). - Postgres and ClickHouse databases — provisioned by this template.
- S3-compatible object storage (MinIO) — provisioned by this template.
- A Svix webhooks server — provisioned by this template.
- Optional, for extra features: an SMTP provider (email), a Freestyle API key (email rendering), and an OpenRouter key (AI).
Deployment Dependencies
1. General setup (first deploy)
Step 1 — Deploy. Every service comes up with generated secrets and is wired to the others automatically. The public domain is generated on deploy.
Step 2 — Log in. The seed script creates an initial dashboard admin from these variables on the hexclave service:
HEXCLAVE_SEED_INTERNAL_PROJECT_USER_EMAIL
HEXCLAVE_SEED_INTERNAL_PROJECT_USER_PASSWORD
Open the app's public URL and sign in with those credentials.
Step 3 — Lock the seed. ⚠️ After your first successful login, set the following on the hexclave service and redeploy:
HEXCLAVE_SKIP_SEED_SCRIPT=true
The seed only runs cleanly once. If you skip this, later redeploys crash with "Environment configuration overrides cannot be changed in a development environment."
Custom domain (optional)
-
Attach your domain to the hexclave-proxy service and add the DNS record Railway gives you.
-
On the hexclave service, point both public URLs at it:
NEXT_PUBLIC_HEXCLAVE_DASHBOARD_URL=https://auth.yourcompany.com NEXT_PUBLIC_HEXCLAVE_API_URL=https://auth.yourcompany.com -
Re-seed once so the domain is registered as trusted: set
HEXCLAVE_SKIP_SEED_SCRIPT=false, redeploy (it merges the domain, then crashes — expected), then set it back totrueand redeploy.
2. Email setup (SMTP)
To send transactional email (verification, password reset, magic links, invites) through any SMTP provider, set these on the hexclave service:
STACK_EMAIL_HOST=smtp.yourprovider.com
STACK_EMAIL_PORT=587
STACK_EMAIL_USERNAME=your-smtp-username
STACK_EMAIL_PASSWORD=your-smtp-password
STACK_EMAIL_SENDER=no-reply@yourdomain.com
- Address validation is disabled by default (
HEXCLAVE_EMAILABLE_API_KEY=disable_email_validation). Leave it unless you have an Emailable key. - SMTP alone is not enough — Hexclave renders its email templates by executing code at runtime, so you also need the rendering engine in section 3.
Where you'll see this: if the rendering engine isn't configured, opening a project's Email settings page (dashboard → your project → Emails) shows "Something went wrong" and bounces you back to the dashboard. That page loading correctly is your sign the engine is set up.
3. Freestyle setup (email template rendering)
Hexclave renders email templates through an external JavaScript execution engine. The primary engine is Freestyle.
Symptom if this isn't set up: the Email settings page shows "Something went wrong" and redirects. Configuring Freestyle fixes it.
Step 1. Create a Freestyle account, enable the code-execution / serverless product (this may require adding a payment method — a key from an un-provisioned account returns 401 Invalid API key), and copy an API key.
Step 2. On the hexclave service, set the key — use the STACK_ prefix, not HEXCLAVE_:
STACK_FREESTYLE_API_KEY=your-freestyle-key
The code reads this variable under the
STACK_name, and theHEXCLAVE_→STACK_auto-mirroring is not reliable for it. SettingHEXCLAVE_FREESTYLE_API_KEYalone can silently send an empty key.
Step 3. Leave STACK_VERCEL_SANDBOX_TOKEN at its pre-set placeholder. The renderer throws on startup if it is completely unset — even when you only use Freestyle. (To use Vercel Sandbox as the engine instead, replace it with a real token and add STACK_VERCEL_SANDBOX_TEAM_ID and STACK_VERCEL_SANDBOX_PROJECT_ID.)
Verify a key directly: POST https://api.freestyle.sh/execute/v1/script with header Authorization: Bearer <key>. A 200 (or a script error) means the key is accepted; 401 means it isn't.
4. Webhooks (self-hosted Svix)
Webhooks are fully self-hosted and pre-wired — no Svix Cloud account needed. svix-server (backed by its own svix-db Postgres) runs in the project and is already connected to hexclave.
Using it: in the dashboard, open a project → Webhooks, add an endpoint URL, and Hexclave delivers events (user.created, team.updated, session events, …) to it. The management UI is served by your own svix-server.
Already wired for you:
- In-memory queue and cache — single-instance, no Redis required.
svix-serveris on a public Railway domain, because the dashboard's webhook UI calls it directly from the browser.- hexclave points at it via
STACK_SVIX_SERVER_URL(private, backend) plus bothNEXT_PUBLIC_STACK_SVIX_SERVER_URLandNEXT_PUBLIC_HEXCLAVE_SVIX_SERVER_URL(public, browser). Both public spellings are required — with only one set, the dashboard falls back toapi.svix.comand 401s.
🔒 Production hardening. This template ships a fixed SVIX_JWT_SECRET and matching admin token so webhooks work the instant you deploy. Because svix-server is public, rotate them for a production deployment:
- Set a new random
SVIX_JWT_SECRETon the svix-server service. - Generate a fresh admin token against it:
svix-server jwt generate. - Paste the token into
STACK_SVIX_API_KEYon the hexclave service, then redeploy both.
Delivery durability. The in-memory queue means in-flight retries are lost if svix-server restarts (new events are unaffected). For durable retries, add a Redis service and set SVIX_QUEUE_TYPE=redis with a SVIX_REDIS_DSN pointing at it.
5. AI features (optional)
Some Hexclave features use OpenRouter. To enable, set this on the hexclave service:
HEXCLAVE_OPENROUTER_API_KEY=your-openrouter-key
Notes & limitations
- Analytics: the Analytics dashboards and queries run on the bundled ClickHouse and work out of the box (with
STACK_DISABLE_PLAN_LIMITS=true, see About Hosting). Only the features that specifically require the cloud-only Bulldozer metering service — usage metering, session replay, and enforced plan quotas — stay unavailable on a self-hosted deploy. - Secrets: all service passwords and keys are generated per-deploy, except the Svix secret/token noted in section 4.
- Source of truth: for anything not covered here, see the official self-hosting guide — https://docs.hexclave.com/guides/other/self-host
Template Content
minio-init
minio/mc:latestsvix-db
postgres:16MinIO
minio/minio:latestsvix-server
svix/svix-serverhexclave-cron
curlimages/curl:latesthexclave
stackauth/server:ebe7877HEXCLAVE_SEED_INTERNAL_PROJECT_USER_EMAIL
Email for the admin account seeded on first boot — this is what you'll sign in to the dashboard with.
hexclave-proxy
caddy:2-alpineClickHouse
clickhouse/clickhouse-server:25.10
