Skip to content
TrueSelphPublic

About

Dokploy Compose stack for self-hosted Hexclave

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

Hexclave on Dokploy

Self-hosted Hexclave for a Dokploy Compose service. The stack runs the published stackauth/server image, Postgres 16, ClickHouse 25.10, and one cron loop. Dokploy's Traefik terminates HTTPS.

Service Role Port
hexclave Dashboard and API 8101 dashboard, 8102 API
postgres Application data internal only
clickhouse Analytics internal only
cron Email queue and external database sync internal only

ClickHouse wants several gigabytes of RAM. Give the Dokploy server enough memory for ClickHouse plus the Hexclave image (about 900 MB compressed).

1. Generate secrets

Use hex or base64url values. Characters such as @, :, and / break the Postgres URL.

openssl rand -base64 32 | tr '+/' '-_' | tr -d '='
openssl rand -hex 32
openssl rand -hex 24

Use the first command for HEXCLAVE_SERVER_SECRET, the second for CRON_SECRET, and the third for POSTGRES_PASSWORD, CLICKHOUSE_PASSWORD, and HEXCLAVE_CLICKHOUSE_EXTERNAL_PASSWORD.

Keep HEXCLAVE_SERVER_SECRET and the three passwords unchanged after the first successful boot. Hexclave derives the internal project keys from the server secret.

2. Create the Dokploy service

  1. Create a project, then a Compose service with type Docker Compose.
  2. Set the provider to your Git host, this repository, and the branch you deploy.
  3. Set the compose path to ./docker-compose.yml.
  4. Leave Isolated Deployments off so the Postgres and ClickHouse volumes survive redeploys.
  5. Open the Environment tab and paste every key from .env.example. Replace the public URLs and fill every blank secret.
  6. Save. Dokploy writes those values to .env next to the compose file. The compose file reads that .env; variables in the UI are not injected on their own.

NEXT_PUBLIC_HEXCLAVE_DASHBOARD_URL and NEXT_PUBLIC_HEXCLAVE_API_URL must be the public https:// URLs you will attach below. They are baked into the dashboard when the container starts.

Use HEXCLAVE_* names. The image also accepts the older STACK_* names, and it exits if both spellings are set to different values.

3. Attach two domains

On the compose service, open Domains and add both hosts to the hexclave service. Enable HTTPS with Let's Encrypt. Leave path, internal path, and strip path empty.

Host Container port
Dashboard URL host 8101
API URL host 8102

Create DNS records for both hosts pointing at the Dokploy server. Domain changes on a Compose service apply on the next deploy.

The compose file publishes no host ports. Traefik reaches Hexclave on dokploy-network. Postgres, ClickHouse, and cron stay on the private internal network.

4. Deploy

Enable Auto Deploy in the service's general tab. On GitHub, Dokploy deploys when you push the configured branch. On GitLab, Bitbucket, or Gitea, add the webhook URL from the deployment logs. The branch in Dokploy must match the branch you push.

Deploy and wait. The first start pulls the image and migrates Postgres and ClickHouse. Startup also copies the application into a runtime directory, which takes several minutes, so the health check allows ten minutes.

HEXCLAVE_RUN_SEED_SCRIPT is false. The published image seeds a development project and then, on every later boot, tries to update that project's environment config. The image rejects that write and the container exits before the API listens. With seed left on, Dokploy reports dependency hexclave failed to start because the cron service waits for a healthy API.

On an empty database, set HEXCLAVE_RUN_SEED_SCRIPT=true for one deploy. Wait until the hexclave logs show Seeding complete! and the service is healthy. Set it back to false and redeploy. The admin user from that seed is the dashboard login.

After the hexclave service is healthy:

curl -fsS "https://auth-api.example.com/health?db=1"

Sign in at the dashboard URL with HEXCLAVE_SEED_INTERNAL_PROJECT_USER_EMAIL and HEXCLAVE_SEED_INTERNAL_PROJECT_USER_PASSWORD.

For each application project, point the SDK at this API:

NEXT_PUBLIC_HEXCLAVE_API_URL=https://auth-api.example.com
HEXCLAVE_API_URL=https://auth-api.example.com

Use the project id and keys from this dashboard.

Optional features

Add these in the Dokploy Environment tab and redeploy. Empty values are ignored.

  • Email. Set HEXCLAVE_EMAIL_HOST, HEXCLAVE_EMAIL_PORT, HEXCLAVE_EMAIL_USERNAME, HEXCLAVE_EMAIL_PASSWORD, and HEXCLAVE_EMAIL_SENDER, or configure SMTP in the dashboard after sign-in. Set HEXCLAVE_EMAILABLE_API_KEY to an Emailable key to validate addresses. The default disable_email_validation skips that check.
  • Webhooks. Set HEXCLAVE_SVIX_API_KEY. Leave HEXCLAVE_SVIX_SERVER_URL empty for Svix Cloud. Set it, and NEXT_PUBLIC_HEXCLAVE_SVIX_SERVER_URL when the browser URL differs, for a self-hosted Svix.
  • File storage. Set the HEXCLAVE_S3_* variables.
  • AI dashboard features. Set HEXCLAVE_OPENROUTER_API_KEY.
  • Custom email sending. Set HEXCLAVE_FREESTYLE_API_KEY and HEXCLAVE_FREESTYLE_SNAPSHOT_ID only after that snapshot exists in the same Freestyle account. Bootstrap it from the Hexclave repo with pnpm --filter @hexclave/backend freestyle:bootstrap-snapshot before the first boot that needs it.

Upgrades

  1. Back up the postgres_data and clickhouse_data volumes.
  2. Read the Hexclave release notes and compare the current server env template with your saved environment.
  3. Pick a newer commit tag from stackauth/server. This stack is pinned to stackauth/server:4afea67 (index digest sha256:8a6ea3449cbf29b88c3601ba63e0cc1a67b39dd211ec32038c542ce7645c0789 as of 2026-10-20). latest is a separate, older tag.
  4. Change the image tag in docker-compose.yml, commit, and push.
  5. Confirm https://<api-host>/health?db=1, dashboard sign-in, cron logs, and any email or webhook flow you use.

The image runs migrations on startup. This compose file runs a single Hexclave container, so that startup migration is the upgrade migration. Keep the previous tag in git history so you can point the image back and redeploy.

Cron

cron calls these API routes every 60 seconds with Authorization: Bearer $CRON_SECRET:

  • /api/latest/internal/email-queue-step
  • /api/latest/internal/external-db-sync/sequencer
  • /api/latest/internal/external-db-sync/poller

A non-2xx response is printed as a failure in the cron service logs. Run one cron service per environment.

About

Dokploy Compose stack for self-hosted Hexclave

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors