DEV Community

Cover image for Deploying Typebot - Open-Source Conversational Form Builder
Sanskriti Harmukh for Vultr

Posted on with Aashish Chaurasiya Originally published at docs.vultr.com

Deploying Typebot - Open-Source Conversational Form Builder

Typebot 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.


Prerequisites

Before you begin, you need to:

  • Have access to a Linux-based server as a non-root user with sudo privileges.
  • Install Docker and Docker Compose.
  • Configure two domain A records pointing to your server, such as builder.example.com and viewer.example.com.
  • Have an email address for Let's Encrypt certificate registration.

Set Up the Directory Structure and Environment Variables

To 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.

1. Create a project directory for the Typebot deployment:

$ mkdir -p ~/typebot/{pgdata,redisdata,letsencrypt,data}
Enter fullscreen mode Exit fullscreen mode

The command creates four subdirectories:

  • 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.

2. Navigate to the project directory:

$ cd ~/typebot
Enter fullscreen mode Exit fullscreen mode

3. Generate a strong random encryption secret that is used to encrypt sensitive data such as credentials and bot content:

$ openssl rand -base64 24
Enter fullscreen mode Exit fullscreen mode

Copy the output. Use this value for the ENCRYPTION_SECRET variable in the next steps when creating the .env file.

Store 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.

4. Create a .env file to store the environment variables:

$ nano .env
Enter fullscreen mode Exit fullscreen mode

5. Add the following variables:

DOMAIN_BUILDER=builder.example.com
DOMAIN_VIEWER=viewer.example.com
LETSENCRYPT_EMAIL=admin@example.com

ENCRYPTION_SECRET=YOUR_GENERATED_SECRET

POSTGRES_DB=typebot
POSTGRES_USER=typebot
POSTGRES_PASSWORD=STRONG_DATABASE_PASSWORD
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}

REDIS_URL=redis://redis:6379

NEXTAUTH_URL=https://${DOMAIN_BUILDER}
NEXT_PUBLIC_VIEWER_URL=https://${DOMAIN_VIEWER}

ADMIN_EMAIL=admin@example.com
DEFAULT_WORKSPACE_PLAN=UNLIMITED
DISABLE_SIGNUP=false

SMTP_HOST=mailpit
SMTP_PORT=1025
SMTP_SECURE=false
NEXT_PUBLIC_SMTP_FROM="Typebot Notifications <notifications@example.com>"
SMTP_IGNORE_TLS=true
SMTP_USERNAME=YOUR_SMTP_USERNAME
SMTP_PASSWORD=YOUR_SMTP_PASSWORD


TYPEBOT_DEBUG=false
AUTH_TRUST_HOST=true
Enter fullscreen mode Exit fullscreen mode

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.

Replace the following:

  • builder.example.com and viewer.example.com with your actual domains pointing to the server.
  • 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.

Save and close the file.

Deploy with Docker Compose

Docker 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 to use Traefik and persistent volumes.

1. Create the Docker Compose manifest:

$ nano docker-compose.yaml
Enter fullscreen mode Exit fullscreen mode

2. Add the following content:

services:
  traefik:
    image: traefik:v3.7.8
    container_name: traefik
    restart: unless-stopped
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
      - "--certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  postgres:
    image: postgres:16-alpine
    container_name: typebot-postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - "./pgdata:/var/lib/postgresql/data"
    healthcheck:
      test: ["CMD", "pg_isready", "-d", "${POSTGRES_DB}", "-U", "${POSTGRES_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:8-alpine
    container_name: typebot-redis
    restart: unless-stopped
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - "./redisdata:/data"
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

  typebot-builder:
    image: baptistearno/typebot-builder:3.17.2
    container_name: typebot-builder
    restart: unless-stopped
    env_file:
      - .env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.typebot-builder.rule=Host(`${DOMAIN_BUILDER}`)"
      - "traefik.http.routers.typebot-builder.entrypoints=websecure"
      - "traefik.http.routers.typebot-builder.tls.certresolver=letsencrypt"
      - "traefik.http.services.typebot-builder.loadbalancer.server.port=3000"

  typebot-viewer:
    image: baptistearno/typebot-viewer:3.17.2
    container_name: typebot-viewer
    restart: unless-stopped
    env_file:
      - .env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.typebot-viewer.rule=Host(`${DOMAIN_VIEWER}`)"
      - "traefik.http.routers.typebot-viewer.entrypoints=websecure"
      - "traefik.http.routers.typebot-viewer.tls.certresolver=letsencrypt"
      - "traefik.http.services.typebot-viewer.loadbalancer.server.port=3000"

  mailpit:
    image: axllent/mailpit:v1.30.5
    container_name: mailpit
    restart: unless-stopped
    ports:
      - "127.0.0.1:8025:8025"
      - "127.0.0.1:1025:1025"
    environment:
      MP_MAX_MESSAGES: 5000
      MP_DATABASE: /data/mailpit.db
      MP_SMTP_AUTH_ACCEPT_ANY: 1
      MP_SMTP_AUTH_ALLOW_INSECURE: 1
    volumes:
      - ./data:/data
Enter fullscreen mode Exit fullscreen mode
  • traefik

    • Acts as a reverse proxy and HTTPS termination layer for both the Builder and Viewer.
    • Listens on ports 80 and 443 for incoming web traffic and automatically redirects HTTP to HTTPS.
    • Requests and renews TLS certificates from Let's Encrypt using the email address defined in LETSENCRYPT_EMAIL.
    • Stores certificates persistently in the ./letsencrypt directory.
  • postgres

    • Runs PostgreSQL 16 as the primary database to store all bots, user responses, workspaces, and configuration data.
    • Uses database credentials defined in the .env file.
    • Persists database files in the ./pgdata directory on the host.
    • Includes a health check to ensure the database is fully initialized before the Typebot services start.
  • redis

    • Runs Redis 8 (Alpine), a required dependency for the Builder and Viewer services to start.
    • Supports sign-in rate limiting by IP and multiple media uploads on WhatsApp.
    • Persists data in the ./redisdata directory.
    • Includes a health check to verify Redis is responsive.
  • typebot-builder

    • Runs the official Typebot Builder application (the visual editor).
    • Loads all configuration and secrets from the .env file.
    • Connects to both PostgreSQL and Redis, waiting for their health checks to pass before starting.
    • Registers itself with Traefik using Docker labels so it can be securely accessed via your builder domain.
  • typebot-viewer

    • Runs the official Typebot Viewer application (the public-facing bot runtime).
    • Loads all configuration and secrets from the .env file.
    • Connects to both PostgreSQL and Redis, waiting for their health checks to pass before starting.
    • Registers itself with Traefik using Docker labels so published bots can be accessed and embedded via your viewer domain.
  • mailpit

    • Runs Mailpit as a local email testing tool, bound to 127.0.0.1 so it is not exposed publicly.
    • Exposes the web UI on port 8025 and the SMTP service on port 1025 locally.
    • Stores email data in the ./data directory.
    • Lets Typebot send sign-in verification codes to a local inbox instead of a real mailbox.
    • Lets you read messages in your local browser at http://localhost:8025 via an SSH tunnel after deployment.

    Mailpit 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, 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.

Save and close the file.

3. Validate the syntax of the file:

$ docker compose config
Enter fullscreen mode Exit fullscreen mode

4. Start the services in detached mode:

$ docker compose up -d
Enter fullscreen mode Exit fullscreen mode

5. Verify that the containers are running and healthy:

$ docker compose ps
Enter fullscreen mode Exit fullscreen mode

All six containers should show a status of Up, with mailpit, typebot-postgres, and typebot-redis also showing (healthy).

6. View the logs for the Builder service to ensure it connected successfully to the database and Redis:

$ docker compose logs typebot-builder
Enter fullscreen mode Exit fullscreen mode

7. View the logs for the Viewer service to ensure it connected successfully to the database and Redis:

$ docker compose logs typebot-viewer
Enter fullscreen mode Exit fullscreen mode

Access and Configure Typebot

Typebot 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.

  1. Open your web browser and navigate to the Builder domain using HTTPS.
   https://builder.example.com
Enter fullscreen mode Exit fullscreen mode

Replace builder.example.com with the actual domain you set in the .env file for the Builder.

  1. Sign in with the email address defined in the ADMIN_EMAIL variable. A six-digit verification code is sent to your Mailpit email server.

Typebot email sign-in verification screen

  1. Because Mailpit is bound to 127.0.0.1 and not exposed publicly, access its web interface by setting up an SSH local port forwarding tunnel from your local terminal.
   $ ssh -N -L 8025:localhost:8025 USERNAME@YOUR_SERVER_IP
Enter fullscreen mode Exit fullscreen mode

Replace 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.

  1. Open your local web browser and navigate to the Mailpit inbox at http://localhost:8025.

  2. Open the Mailpit inbox and copy the verification code sent by Typebot.

Viewing the sign-in verification code inside the Mailpit inbox

  1. Return to the Builder tab and enter the code to complete sign-in.

  2. Return 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.

  3. Open the Viewer domain in a new tab.

   https://viewer.example.com
Enter fullscreen mode Exit fullscreen mode

Replace viewer.example.com with the domain you configured in the .env file.

  1. Click the dashboard link on the Viewer page to verify that it opens the Builder interface.

Typebot viewer landing page displaying the dashboard link

  1. Open your .env file to disable public registrations now that your admin account is created.

    $ nano .env
    
  2. Update the signup configuration.

    DISABLE_SIGNUP=true
    
  3. Save and close the file, then apply the changes to the Builder container.

    $ docker compose up -d --force-recreate typebot-builder
    

    This prevents unauthorized users from registering new accounts on your public Builder instance.

Create and Embed a Typebot

Typebot 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.

  1. In the Builder tab still open from the previous section, click Create a typebot.

  2. Select Start from scratch to create a new bot manually.

Selecting start from scratch on the Typebot creation screen

  1. From the top left corner, change the typebot name to your preferred title, for example, My first bot.

  2. In 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?"

  3. Drag a connection line from the Start block's output dot to the Text bubble block so the flow begins there.

  4. Drag an Input block, for example Text, and connect it to the previous block.

Connecting a text block and input block in the Typebot visual editor

  1. Click Publish in the top-right corner.

  2. Under Embed your typebot, click Iframe.

  3. Copy the <iframe> snippet shown in the dialog.

  4. Open the main HTML file of your sample website or any page where you want to add the bot.

  5. Paste the snippet just before the closing </body> tag.

    <iframe
        title="Typebot"
        src="https://viewer.example.com/your-bot-id"
        style="border: none; width: 100%; height: 600px"
    ></iframe>
    

    Replace viewer.example.com/your-bot-id with the link shown in the Iframe dialog.

  6. Save the file and open your website in a browser to test the bot.

  7. Return to the Typebot Builder, open the Results tab, and verify that responses are being captured.

Test a Bot

Typebot'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.

  1. Click Create a typebot.
  2. Select Start from template.
  3. Choose the Customer Support template from the left pane, then click Use this template.
  4. Click Publish.
  5. Open the link shown under Your typebot links.
  6. Click one of the response options, for example I have a feature request. Verify that the bot responds with a follow-up message and a link, then click Restart to return to the beginning.
  7. Return to the Typebot Builder, open the Results tab, and verify that the option you clicked appears under the Menu column.

Next Steps

  • Connect a real SMTP provider so sign-in codes and notifications reach real inboxes
  • Explore Typebot's integrations, such as Google Sheets, webhooks, and Zapier
  • Build a multi-step lead qualification or support triage flow using Choice and Condition blocks
  • Set up scheduled backups of the PostgreSQL volume before handling production traffic

For the full guide with additional tips, visit the original article on Vultr Docs.

Top comments (0)