{"slug": "deploying-typebot-open-source-conversational-form-builder", "title": "Deploying Typebot - Open-Source Conversational Form Builder", "summary": "A developer published a step-by-step guide for self-hosting Typebot, an open-source conversational form and chatbot builder, on a Linux server using Docker Compose. The deployment stacks PostgreSQL, Redis, Traefik for reverse proxy and TLS termination, and Mailpit for email, with host-mounted volumes for persistence and an ENCRYPTION_SECRET used to encrypt stored credentials and bot content. The setup yields a working Typebot instance with a published bot embedded on a sample page.", "body_md": "[Typebot](https://typebot.io/) is an open-source, visually-driven conversational form and chatbot builder. It serves as a self-hosted alternative to hosted form and chatbot builders, giving you full data ownership and control over integrations and embedding. This guide deploys Typebot on a Linux server using Docker Compose with PostgreSQL, Redis, and Traefik for reverse proxy and TLS termination. By the end, you'll have a working Typebot instance with a published bot embedded on a sample page.\n\nBefore you begin, you need to:\n\n`sudo` privileges.`builder.example.com` and `viewer.example.com`.\nTo prevent data loss during container restarts or updates, the deployment relies on host-mounted volumes for PostgreSQL, Redis, and TLS certificates. Docker Compose reads secrets, URLs, and credentials from a `.env` file in the project directory and substitutes them into the service definitions at startup.\n\n**1. Create a project directory for the Typebot deployment:**\n\n``` bash\n$ mkdir -p ~/typebot/{pgdata,redisdata,letsencrypt,data}\n```\n\nThe command creates four subdirectories:\n\n`pgdata`: Persists PostgreSQL database files.` redisdata`: Stores Redis data used by Typebot's Redis-backed features, such as sign-in rate limiting and media uploads.`letsencrypt`: Stores Traefik ACME certificates for automatic HTTPS renewal.`data`: Stores Mailpit local email data.\n**2. Navigate to the project directory:**\n\n``` bash\n$ cd ~/typebot\n```\n\n**3. Generate a strong random encryption secret that is used to encrypt sensitive data such as credentials and bot content:**\n\n``` bash\n$ openssl rand -base64 24\n```\n\nCopy the output. Use this value for the `ENCRYPTION_SECRET` variable in the next steps when creating the `.env` file.\n\nStore this value securely and never change it once the deployment starts handling real data. Typebot uses `ENCRYPTION_SECRET` to encrypt stored credentials, and rotating it makes any previously encrypted data unreadable.\n\n**4. Create a `.env` file to store the environment variables:**\n\n``` bash\n$ nano .env\n```\n\n**5. Add the following variables:**\n\n```\nDOMAIN_BUILDER=builder.example.com\nDOMAIN_VIEWER=viewer.example.com\nLETSENCRYPT_EMAIL=admin@example.com\n\nENCRYPTION_SECRET=YOUR_GENERATED_SECRET\n\nPOSTGRES_DB=typebot\nPOSTGRES_USER=typebot\nPOSTGRES_PASSWORD=STRONG_DATABASE_PASSWORD\nDATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}\n\nREDIS_URL=redis://redis:6379\n\nNEXTAUTH_URL=https://${DOMAIN_BUILDER}\nNEXT_PUBLIC_VIEWER_URL=https://${DOMAIN_VIEWER}\n\nADMIN_EMAIL=admin@example.com\nDEFAULT_WORKSPACE_PLAN=UNLIMITED\nDISABLE_SIGNUP=false\n\nSMTP_HOST=mailpit\nSMTP_PORT=1025\nSMTP_SECURE=false\nNEXT_PUBLIC_SMTP_FROM=\"Typebot Notifications <notifications@example.com>\"\nSMTP_IGNORE_TLS=true\nSMTP_USERNAME=YOUR_SMTP_USERNAME\nSMTP_PASSWORD=YOUR_SMTP_PASSWORD\n\nTYPEBOT_DEBUG=false\nAUTH_TRUST_HOST=true\n```\n\n`DEFAULT_WORKSPACE_PLAN=UNLIMITED` applies the unlimited plan to every new workspace, not only the administrator's. Signup stays open until later in this guide, so anyone who registers during that window also receives an unlimited workspace.\n\nReplace the following:\n\n`admin@example.com` with your email for Let's Encrypt and admin access.`YOUR_GENERATED_SECRET` with the output from the openssl command.`STRONG_DATABASE_PASSWORD` with a secure password for PostgreSQL.`YOUR_SMTP_USERNAME` with your username.`YOUR_SMTP_PASSWORD` with a strong, secure password for your mail.`notifications@example.com` in `NEXT_PUBLIC_SMTP_FROM` with a sender address on your own domain.\nSave and close the file.\n\nDocker Compose orchestrates the full Typebot stack: Traefik for reverse proxy and HTTPS, PostgreSQL for persistent storage, Redis for sessions and caching, the Builder and Viewer services, and Mailpit for email. This configuration is adapted from the [official Typebot Docker setup](https://docs.typebot.com/self-hosting/deploy/docker) to use Traefik and persistent volumes.\n\n**1. Create the Docker Compose manifest:**\n\n``` bash\n$ nano docker-compose.yaml\n```\n\n**2. Add the following content:**\n\n```\nservices:\n  traefik:\n    image: traefik:v3.7.8\n    container_name: traefik\n    restart: unless-stopped\n    command:\n      - \"--providers.docker=true\"\n      - \"--providers.docker.exposedbydefault=false\"\n      - \"--entrypoints.web.address=:80\"\n      - \"--entrypoints.websecure.address=:443\"\n      - \"--entrypoints.web.http.redirections.entrypoint.to=websecure\"\n      - \"--entrypoints.web.http.redirections.entrypoint.scheme=https\"\n      - \"--certificatesresolvers.letsencrypt.acme.httpchallenge=true\"\n      - \"--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web\"\n      - \"--certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}\"\n      - \"--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json\"\n    ports:\n      - \"80:80\"\n      - \"443:443\"\n    volumes:\n      - \"./letsencrypt:/letsencrypt\"\n      - \"/var/run/docker.sock:/var/run/docker.sock:ro\"\n\n  postgres:\n    image: postgres:16-alpine\n    container_name: typebot-postgres\n    restart: unless-stopped\n    environment:\n      POSTGRES_DB: ${POSTGRES_DB}\n      POSTGRES_USER: ${POSTGRES_USER}\n      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}\n    volumes:\n      - \"./pgdata:/var/lib/postgresql/data\"\n    healthcheck:\n      test: [\"CMD\", \"pg_isready\", \"-d\", \"${POSTGRES_DB}\", \"-U\", \"${POSTGRES_USER}\"]\n      interval: 10s\n      timeout: 5s\n      retries: 5\n\n  redis:\n    image: redis:8-alpine\n    container_name: typebot-redis\n    restart: unless-stopped\n    command: [\"redis-server\", \"--appendonly\", \"yes\"]\n    volumes:\n      - \"./redisdata:/data\"\n    healthcheck:\n      test: [\"CMD\", \"redis-cli\", \"ping\"]\n      interval: 10s\n      timeout: 5s\n      retries: 3\n\n  typebot-builder:\n    image: baptistearno/typebot-builder:3.17.2\n    container_name: typebot-builder\n    restart: unless-stopped\n    env_file:\n      - .env\n    depends_on:\n      postgres:\n        condition: service_healthy\n      redis:\n        condition: service_healthy\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.typebot-builder.rule=Host(`${DOMAIN_BUILDER}`)\"\n      - \"traefik.http.routers.typebot-builder.entrypoints=websecure\"\n      - \"traefik.http.routers.typebot-builder.tls.certresolver=letsencrypt\"\n      - \"traefik.http.services.typebot-builder.loadbalancer.server.port=3000\"\n\n  typebot-viewer:\n    image: baptistearno/typebot-viewer:3.17.2\n    container_name: typebot-viewer\n    restart: unless-stopped\n    env_file:\n      - .env\n    depends_on:\n      postgres:\n        condition: service_healthy\n      redis:\n        condition: service_healthy\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.typebot-viewer.rule=Host(`${DOMAIN_VIEWER}`)\"\n      - \"traefik.http.routers.typebot-viewer.entrypoints=websecure\"\n      - \"traefik.http.routers.typebot-viewer.tls.certresolver=letsencrypt\"\n      - \"traefik.http.services.typebot-viewer.loadbalancer.server.port=3000\"\n\n  mailpit:\n    image: axllent/mailpit:v1.30.5\n    container_name: mailpit\n    restart: unless-stopped\n    ports:\n      - \"127.0.0.1:8025:8025\"\n      - \"127.0.0.1:1025:1025\"\n    environment:\n      MP_MAX_MESSAGES: 5000\n      MP_DATABASE: /data/mailpit.db\n      MP_SMTP_AUTH_ACCEPT_ANY: 1\n      MP_SMTP_AUTH_ALLOW_INSECURE: 1\n    volumes:\n      - ./data:/data\n```\n\n`traefik`\n\n`LETSENCRYPT_EMAIL`.`./letsencrypt` directory.\n`postgres`\n\n`.env` file.`./pgdata` directory on the host.\n`redis`\n\n`./redisdata` directory.\n`typebot-builder`\n\n`typebot-viewer`\n\n`mailpit`\n\n`127.0.0.1` so it is not exposed publicly.`8025` and the SMTP service on port `1025` locally.`./data` directory.`http://localhost:8025` via an SSH tunnel after deployment.\nMailpit only captures mail locally. It never delivers to a real inbox, so it is not a production email path. To send real email, either request that your provider unblock outbound port 25 on this instance and self-host a mail delivery service such as [Postal](https://docs.postalserver.io/), pointing `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, and `SMTP_PASSWORD` at it, or route outbound mail through an authenticated relay on port 587 or 465. Many cloud providers block outbound port 25 by default on new instances, so check with your provider before choosing a self-hosted mail path.\n\n**3. Validate the syntax of the file:**\n\n``` bash\n$ docker compose config\n```\n\n**4. Start the services in detached mode:**\n\n``` bash\n$ docker compose up -d\n```\n\n**5. Verify that the containers are running and healthy:**\n\n``` bash\n$ docker compose ps\n```\n\nAll six containers should show a status of `Up`, with `mailpit`, `typebot-postgres`, and `typebot-redis` also showing `(healthy)`.\n\n**6. View the logs for the Builder service to ensure it connected successfully to the database and Redis:**\n\n``` bash\n$ docker compose logs typebot-builder\n```\n\n**7. View the logs for the Viewer service to ensure it connected successfully to the database and Redis:**\n\n``` bash\n$ docker compose logs typebot-viewer\n```\n\nTypebot requires email-based verification instead of a password for the first sign-in, which this deployment routes through Mailpit. This section confirms the administrator account, verifies that both the Builder and Viewer domains are reachable, and closes public registration.\n\n```\n   https://builder.example.com\n```\n\nReplace `builder.example.com` with the actual domain you set in the `.env` file for the Builder.\n\n`ADMIN_EMAIL` variable. A six-digit verification code is sent to your Mailpit email server.\n\n``` bash\n   $ ssh -N -L 8025:localhost:8025 USERNAME@YOUR_SERVER_IP\n```\n\nReplace `USERNAME` with your server's username and `YOUR_SERVER_IP` with your server's IP. If your server uses key-based SSH authentication, add `-i /path/to/your-private-key` before `-N`. The `-N` flag tells SSH to only forward the port instead of opening a remote shell.\n\nOpen your local web browser and navigate to the Mailpit inbox at `http://localhost:8025`.\n\nOpen the Mailpit inbox and copy the verification code sent by Typebot.\n\nReturn to the Builder tab and enter the code to complete sign-in.\n\nReturn to the terminal running the SSH tunnel and press Ctrl+C to close it, since Mailpit access is no longer needed until the next sign-in.\n\nOpen the Viewer domain in a new tab.\n\n```\n   https://viewer.example.com\n```\n\nReplace `viewer.example.com` with the domain you configured in the `.env` file.\n\nOpen your `.env` file to disable public registrations now that your admin account is created.\n\n``` bash\n$ nano .env\n```\n\nUpdate the signup configuration.\n\n```\nDISABLE_SIGNUP=true\n```\n\nSave and close the file, then apply the changes to the Builder container.\n\n``` bash\n$ docker compose up -d --force-recreate typebot-builder\n```\n\nThis prevents unauthorized users from registering new accounts on your public Builder instance.\n\nTypebot publishes each bot as a hosted page on the Viewer domain and provides a JavaScript snippet that embeds that page into any website. Publishing a bot makes it reachable at that public link before you add it to a page.\n\nIn the Builder tab still open from the previous section, click **Create a typebot**.\n\nSelect **Start from scratch** to create a new bot manually.\n\nFrom the top left corner, change the typebot name to your preferred title, for example, **My first bot**.\n\nIn the visual editor, drag a **Text** bubble block onto the canvas and enter a welcome message, for example, \"Hello! How can I help you today?\"\n\nDrag a connection line from the **Start** block's output dot to the **Text** bubble block so the flow begins there.\n\nDrag an Input block, for example **Text**, and connect it to the previous block.\n\nClick **Publish** in the top-right corner.\n\nUnder **Embed your typebot**, click **Iframe**.\n\nCopy the `<iframe>` snippet shown in the dialog.\n\nOpen the main HTML file of your sample website or any page where you want to add the bot.\n\nPaste the snippet just before the closing `</body>` tag.\n\n```\n<iframe\n    title=\"Typebot\"\n    src=\"https://viewer.example.com/your-bot-id\"\n    style=\"border: none; width: 100%; height: 600px\"\n></iframe>\n```\n\nReplace `viewer.example.com/your-bot-id` with the link shown in the Iframe dialog.\n\nSave the file and open your website in a browser to test the bot.\n\nReturn to the Typebot Builder, open the **Results** tab, and verify that responses are being captured.\n\nTypebot's built-in templates route respondents through a Choice input block, so each button ends its own path through the flow instead of all leading to the same message. The Results tab records which option a respondent picked as its own column, alongside any text or email fields the flow collects.\n\nFor the full guide with additional tips, visit the original article on **[Vultr Docs](https://docs.vultr.com/how-to-deploy-typebot-open-source-conversational-form-builder)**.", "url": "https://wpnews.pro/news/deploying-typebot-open-source-conversational-form-builder", "canonical_source": "https://dev.to/vultr/deploying-typebot-open-source-conversational-form-builder-52j3", "published_at": "2026-09-23 19:27:14+00:00", "updated_at": "2026-09-23 19:58:49.952947+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "ai-products"], "entities": ["Typebot", "Docker Compose", "PostgreSQL", "Redis", "Traefik", "Mailpit", "Let's Encrypt"], "alternates": {"html": "https://wpnews.pro/news/deploying-typebot-open-source-conversational-form-builder", "markdown": "https://wpnews.pro/news/deploying-typebot-open-source-conversational-form-builder.md", "text": "https://wpnews.pro/news/deploying-typebot-open-source-conversational-form-builder.txt", "jsonld": "https://wpnews.pro/news/deploying-typebot-open-source-conversational-form-builder.jsonld"}}