ποΈSelf-hosting
Run your own copy of Dapta Forms: the two apps, the Docker images, PostgreSQL in production, the handful of settings that matter and what changes when you leave the hosted forms.dapta.ai.
Dapta Forms is deployment agnostic: it is plain Node, with no host-only APIs, so it runs on Docker, Kubernetes, a single virtual machine or anything in between. This page is a map. The authoritative instructions live in the repository and are kept up to date with the code.
The local development loop: clone, install, run. No database or accounts required.
The production guide: building the images, the full environment reference, the database, reverse proxy and TLS, sign in, email, upgrades, rollback and troubleshooting.
Every setting with inline notes and its default.
A production shaped reference stack you can bring up in one command.

SELF-HOSTING.md in the repository is the production guide. Start there.The two apps
A Dapta Forms deployment is two containers plus a database.
Web (
apps/web): the public form pages and the dashboard. Listens on port3000.API (
apps/api): the public submission endpoints and the dashboard endpoints. Listens on port4000, and exposes/healthand/health/readyfor your load balancer.
The web app never talks to the database directly, it calls the API over HTTP. That is why the two can be scaled and deployed independently.
Both Dockerfiles take the repository root as the build context:
β οΈ Note: Every
NEXT_PUBLIC_*value is baked into the web image at build time, not read when the container starts. If you move the API or change any of those values, rebuild the web image.
The database
PostgreSQL is the production database. The repository also supports a SQLite file so you can clone the project and have it running in a minute, but that path is for evaluation and local development only.
Point
DATABASE_URLat your PostgreSQL instance.Run the migrations before the API starts. The API image does not migrate on boot on purpose, so scaling to several replicas never has several of them migrating at once. The reference stack does it with a one-shot
migrateservice that runs and exits.Migrations only add things (new tables, new nullable columns), so an upgrade never drops data from a running deployment.
The settings that matter
Everything has a safe default, so a bare deployment boots. These are the ones you will actually set for a real deployment. The full list is in SELF-HOSTING.md and .env.example.
NODE_ENV
production for any real deployment.
DATABASE_URL
Your PostgreSQL connection string.
PUBLIC_APP_URL
Your public base URL, for example https://forms.example.com. It is the trusted origin used to build sign in redirects and the default list of allowed browser origins.
NEXT_PUBLIC_API_URL
Where the browser reaches your API. Build time value, so it is baked into the web image.
AUTH_PROVIDER
Which sign in adapter the dashboard uses. The default is an unauthenticated development stub, and the API refuses to boot with it in production. See Auth options in SELF-HOSTING.md for the production value and the secrets it needs.
EMAIL_PROVIDER
log-only by default, which prints submission notices to the API log instead of sending them. Switch to SMTP or an HTTP mail API to actually send, and set MAIL_FROM_EMAIL and MAIL_FROM_NAME.
CORS_ORIGINS
The extra domains allowed to call your API from a browser. Set it when you embed forms on other sites.
TRUST_PROXY_HOPS
How many trusted proxies sit in front of the API. It decides which address the rate limiter counts, so get it right or you will throttle everyone as one client.
HUBSPOT_PRIVATE_APP_TOKEN
Optional. Set it and HubSpot works for the whole deployment. Leave it unset and the HubSpot destination reports a clear disabled state.
Server settings are validated when the API starts, and a bad value fails loudly with a message naming the offending variable.
Sign in, TLS and email
Put a reverse proxy in front of both apps and terminate TLS there. Any proxy works: nginx, Caddy, Traefik, a cloud load balancer. Forward to web on
3000and API on4000.Public form pages are always open. Sign in only protects the dashboard, and it is a pluggable adapter: the default local stub is fine for evaluation, and a real deployment points it at your own identity service.
SELF-HOSTING.mdhas the exact values and secrets.Email delivery is also pluggable. Submission notifications are queued and retried with backoff, so a slow or unreachable mail provider never fails a respondent's submission.
What is different from forms.dapta.ai
You sign in with your Dapta account.
You wire your own sign in, or run the open development stub for evaluation.
Workspaces, members, roles and invitations come from your Dapta account.
There are no Dapta workspaces. Membership comes from whatever identity service you connect.
HubSpot and Calendly are connected per account from Connections.
Same screen, but you supply the tokens, and you can also set one HubSpot token for the whole deployment.
Submission emails are sent for you.
Nothing is sent until you configure a mail provider. Until then, notices are written to the API log.
Dapta runs backups, upgrades and uptime.
You do: database backups, migrations, image upgrades and rollbacks are yours.
Support and bug reports go through Dapta.
Support is the repository: issues and pull requests on GitHub.
Everything else, the editor, logic, scoring, design, webhooks, submissions and analytics, is the same product.
What's next
Public API & rate limits: the endpoints your deployment exposes.
Feature flags & environment: the settings that change what your users see.
Connections (account level): the screen where HubSpot and Calendly are connected.
Last updated