# Instalação TypeBot docker

Link: [https://docs.typebot.io/self-hosting/deploy/docker](https://docs.typebot.io/self-hosting/deploy/docker) em 06/06/2025

<header class="relative" id="bkmrk-"></header>The easiest way to get started with Typebot is with [the official managed service in the Cloud](https://app.typebot.io/). You’ll have high availability, backups, security, and maintenance all managed for you by me, Baptiste, Typebot’s founder. The cloud version can save a substantial amount of developer time and resources. For most sites this ends up being the best value option and the revenue goes to funding the maintenance and further development of Typebot. So you’ll be supporting fair source software and getting a great service!

<div class="absolute" id="bkmrk-%E2%80%8B" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#requirements)</div>## <span class="cursor-pointer">Requirements</span>

You need a server with Docker installed. If your server doesn’t come with Docker pre-installed, you can follow [their docs](https://docs.docker.com/engine/install/#server) to install it.

<div class="absolute" id="bkmrk-%E2%80%8B-1" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#installation)</div>## <span class="cursor-pointer">Installation</span>

<div class="absolute" id="bkmrk-%E2%80%8B-2" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#1-download-the-compose-file)</div>### <span class="cursor-pointer">1. Download the compose file</span>

On your server, download the latest `docker-compose.yml` and the starter `.env` file:

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-copy" style="text-align: justify;"><div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent language-sh"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div></div>```
wget https://raw.githubusercontent.com/baptisteArno/typebot.io/latest/docker-compose.yml
 wget https://raw.githubusercontent.com/baptisteArno/typebot.io/latest/.env.example -O .env
```

<div class="absolute" id="bkmrk-%E2%80%8B-3" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#2-add-the-required-configuration)</div>### <span class="cursor-pointer">2. Add the required configuration</span>

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-you%E2%80%99ll-first-need-a-" style="text-align: justify;">1. You’ll first need a random 32-character secret key which will be used to encrypt sensitive data. Here is a simple way to generate one:
    
    <div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent language-sh"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div>```
    openssl rand -base64 24 | tr -d '\n' ; echo
    ```
2. Fill the `.env` file with your values.
3. Configure at least one authentication provider (Email, Google, GitHub, Facebook or GitLab). More info here: [Configuration](https://docs.typebot.io/self-hosting/configuration).

</div>By default the compose file will pull the latest stable Typebot images: `baptistearno/typebot-builder:latest` and `baptistearno/typebot-viewer:latest`. You can decide to replace `latest` with a specific version. You can find all the existing tags [here](https://hub.docker.com/r/baptistearno/typebot-builder/tags)

<div class="absolute" id="bkmrk-%E2%80%8B-4" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#3-start-the-server)</div>### <span class="cursor-pointer">3. Start the server</span>

Once you’ve added your configuration to the compose file, you’re ready to start up the server:

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-copy-1" style="text-align: justify;"><div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent language-sh"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div></div>```
docker-compose up -d
```

When you run this command, by default, it does the following:

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-create-a-database-ru" style="text-align: justify;">- Create a database
- Run the migrations
- Start the builder on port 8080
- Start the viewer on port 8081
- All Typebot’s data is stored in the `.typebot` folder in the current directory

</div>You can now navigate to `http://typebot.domain.com:8080` and see the login screen. Login with the admin email to have access to a Team plan workspace automatically.

Typebot server itself does not perform SSL termination. It only runs on unencrypted HTTP. If you want to run on HTTPS you also need to set up a reverse proxy in front of the server. See below instructions.

<div class="absolute" id="bkmrk-%E2%80%8B-5" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#update-typebot)</div>### <span class="cursor-pointer">Update Typebot</span>

Typebot is updated regularly, but it is up to you to apply these updates on your server. By virtue of using Docker, these updates are safe and easy to apply.

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-pull-the-new-images%3A" style="text-align: justify;">1. Pull the new images:
    
    <div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent language-sh"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div>```
    docker-compose pull typebot-builder
    docker-compose pull typebot-viewer
    ```
    
    Alternatively, you can pull specific versions:
    
    <div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent language-sh"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div>```
    docker-compose pull typebot-builder:3.4.2
     docker-compose pull typebot-viewer:3.4.2
    ```
2. Stop the server:
    
    <div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent language-sh"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div>```
    docker-compose down
    ```
3. Start the server (with the new images):
    
    <div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent language-sh"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div>```
    docker-compose up -d
    ```

</div>The self-hosted version is somewhat of a LTS, only getting the changes (~ once per month) after they have been battle tested on the cloud version. If you want features as soon as they are available, consider becoming a [cloud user](https://app.typebot.io/).

<div class="absolute" id="bkmrk-%E2%80%8B-6" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#optional-extras)</div>## <span class="cursor-pointer">Optional extras</span>

<div class="absolute" id="bkmrk-%E2%80%8B-7" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#reverse-proxy)</div>### <span class="cursor-pointer">Reverse proxy</span>

By default, Typebot runs on unencrypted HTTP on ports 8080 for the builder and 8081 for the viewer. We recommend running it on HTTPS behind a reverse proxy of some sort. You may or may not already be running a reverse proxy on your host, let’s look at both options:

<div class="absolute" id="bkmrk-%E2%80%8B-8" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#no-existing-reverse-proxy)</div>#### <span class="cursor-pointer">No existing reverse proxy</span>

If your DNS is managed by a service that offers a proxy option with automatic SSL management, feel free to use that. For example, you could use Cloudflare as a reverse proxy in front of Typebot.

Alternatively, you can run your Caddy server as a reverse proxy. This way your SSL certificate will be stored on the host machine and managed by Let’s Encrypt. The Caddy server will expose port 443, terminate SSL traffic and proxy the requests to your Typebot server.

Here is an example of a docker-compose file using Caddy as a reverse proxy:

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-copy-2" style="text-align: justify;"><div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent language-yml"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div></div>```
services:
  caddy-gen:
    container_name: caddy-gen
    image: 'wemakeservices/caddy-gen:latest'
    restart: always
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - {$PWD}/.typebot/caddy-certificates:/data/caddy
    ports:
      - '80:80'
      - '443:443'
    depends_on:
      - typebot-builder
      - typebot-viewer

  typebot-builder:
    labels:
      virtual.host: 'typebot.domain.com' # change to your domain name
      virtual.port: '3000'
      virtual.tls-email: 'admin@example.com' # change to your email

  typebot-viewer:
    labels:
      virtual.host: 'bot.domain.com' # change to your domain name
      virtual.port: '3000'
      virtual.tls-email: 'admin@example.com' # change to your email
      # Necessary to enable message streaming
      virtual.proxy.directives: |
        flush_interval -1
```

This config requires you to add the following DNS entry:

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-copy-3" style="text-align: justify;"><div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div></div>```
typebot IN A <server_ip>
bot IN A <server_ip>
```

You can merge this compose file with the first one. Make sure that `NEXTAUTH_URL` is set to `https://typebot.domain.com` and `NEXT_PUBLIC_VIEWER_URL` is set to `https://bot.domain.com`.

When running the compose file, it should automatically enable SSL on your server and you should be able to navigate to:

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-https%3A%2F%2Ftypebot.doma" style="text-align: justify;">- `https://typebot.domain.com` for the builder
- `https://bot.domain.com` for the viewer

</div><div class="absolute" id="bkmrk-%E2%80%8B-9" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#existing-reverse-proxy)</div>#### <span class="cursor-pointer">Existing reverse proxy</span>

If you’re already running a reverse proxy, the most important things to note are:

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-configure-the-virtua" style="text-align: justify;">1. Configure the virtual hosts to match the `NEXTAUTH_URL` and `NEXT_PUBLIC_VIEWER_URL` in your `docker-compose` configuration.
2. Proxy the traffic to `127.0.0.1:8080` or `{ip-address}:8080` and to `127.0.0.1:8081` or `{ip-address}:8081` if running on a remote machine

</div><div class="absolute" id="bkmrk-%E2%80%8B-10" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#smtp)</div>### <span class="cursor-pointer">SMTP</span>

I highly recommend using an external SMTP service. There are tons of options out there, including [SendInBlue](https://www.sendinblue.com/), [Mailgun](https://www.mailgun.com/) and [SendGrid](https://sendgrid.com/). It will avoid severe headaches 😅. Then, you will only need to add the required [SMTP configuration variables](https://docs.typebot.io/self-hosting/configuration#email-auth-notifications).

If, however, you don’t want to, you can instantiate an SMTP server in the docker-compose file.

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-copy-4" style="text-align: justify;"><div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent language-yml"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div></div>```
services:
  mail:
    image: bytemark/smtp
    restart: always
```

And add the following variables to your `.env` file:

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-copy-5" style="text-align: justify;"><div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div></div>```
SMTP_HOST=mail
NEXT_PUBLIC_SMTP_FROM=notifications@typebot.domain.com
```

You will probably need to make sure that `typebot.domain.com` has a valid SPF record and that your server IP has a rDNS set up.

You can merge this compose file with the main one.

<div class="absolute" id="bkmrk-%E2%80%8B-11" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#s3-storage)</div>### <span class="cursor-pointer">S3 storage</span>

If you don’t already have an S3 storage available, you could include it in your docker-compose file:

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-copy-6" style="text-align: justify;"><div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent language-yml"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div></div>```
services:
  minio:
    image: minio/minio
    command: server /data
    ports:
      - '9000:9000'
    environment:
      MINIO_ROOT_USER: minio
      MINIO_ROOT_PASSWORD: minio123
    volumes:
      - s3-data:/data
  # This service just makes sure a bucket with the right policies is created
  createbuckets:
    image: minio/mc
    depends_on:
      - minio
    entrypoint: >
      /bin/sh -c "
      sleep 10;
      /usr/bin/mc config host add minio http://minio:9000 minio minio123;
      /usr/bin/mc mb minio/typebot;
      /usr/bin/mc anonymous set public minio/typebot/public;
      exit 0;
      "

volumes:
  s3-data:
```

And add the following variables to your `.env` file:

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-copy-7" style="text-align: justify;"><div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div></div>```
S3_ACCESS_KEY=minio
S3_SECRET_KEY=minio123
S3_BUCKET=typebot
S3_ENDPOINT=storage.domain.com
```

This config requires you to add the following DNS entry:

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-copy-8" style="text-align: justify;"><div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div></div>```
storage IN A <server_ip>
```

You can merge this compose file with the main one.

<div class="absolute" id="bkmrk-%E2%80%8B-12" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#config-example-with-all-the-extras)</div>## <span class="cursor-pointer">Config example with all the extras</span>

Here is a config example that spins up Typebot with HTTPS, SMTP and S3 storage.

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-copy-9" style="text-align: justify;"><div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent language-yml"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div></div>```
services:
  caddy-gen:
    image: 'wemakeservices/caddy-gen:latest'
    restart: always
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - {$PWD}/.typebot/caddy-certificates:/data/caddy
    ports:
      - '80:80'
      - '443:443'
    depends_on:
      - typebot-builder
      - typebot-viewer
  typebot-db:
    image: postgres:16
    restart: always
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=typebot
      - POSTGRES_PASSWORD=typebot
    healthcheck:
        test: ["CMD-SHELL", "pg_isready -U postgres"]
        interval: 5s
        timeout: 5s
        retries: 5
  typebot-builder:
    labels:
      virtual.host: 'typebot.domain.com' # change to your domain
      virtual.port: '3000'
      virtual.tls-email: 'admin@example.com' # change to your email
    image: baptistearno/typebot-builder:latest
    depends_on:
      typebot-db:
        condition: service_healthy
    restart: always
    extra_hosts:
      - 'host.docker.internal:host-gateway'
    # See https://docs.typebot.io/self-hosting/configuration for more configuration options
    env_file:
      - .env
  typebot-viewer:
    labels:
      virtual.host: 'bot.domain.com' # change to your domain
      virtual.port: '3000'
      virtual.tls-email: 'admin@example.com' # change to your email
      # Necessary to enable message streaming
      virtual.proxy.directives: |
        flush_interval -1
    image: baptistearno/typebot-viewer:latest
    depends_on:
      typebot-db:
        condition: service_healthy
    restart: always
    # See https://docs.typebot.io/self-hosting/configuration for more configuration options
    env_file:
      - .env
  mail:
    image: bytemark/smtp
    restart: always
  minio:
    labels:
      virtual.host: 'storage.domain.com' # change to your domain
      virtual.port: '9000'
      virtual.tls-email: 'admin@example.com' # change to your email
    image: minio/minio
    command: server /data
    ports:
      - '9000:9000'
    environment:
      MINIO_ROOT_USER: minio
      MINIO_ROOT_PASSWORD: minio123
    volumes:
      - s3-data:/data
  # This service just make sure a bucket with the right policies is created
  createbuckets:
    image: minio/mc
    depends_on:
      - minio
    entrypoint: >
      /bin/sh -c "
      sleep 10;
      /usr/bin/mc config host add minio http://minio:9000 minio minio123;
      /usr/bin/mc mb minio/typebot;
      /usr/bin/mc anonymous set public minio/typebot/public;
      exit 0;
      "

volumes:
  db-data:
  s3-data:
```

<div class="absolute" id="bkmrk-%E2%80%8B-13" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#build-your-own-images)</div>## <span class="cursor-pointer">Build your own images</span>

To build your own builder Docker image

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-copy-10" style="text-align: justify;"><div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent language-sh"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div></div>```
docker build -t typebot-builder --build-arg SCOPE=builder .
```

To build your own viewer Docker image

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-copy-11" style="text-align: justify;"><div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent language-sh"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div></div>```
docker build -t typebot-viewer --build-arg SCOPE=viewer .
```

<div class="absolute" id="bkmrk-%E2%80%8B-14" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#troubleshooting)</div>## <span class="cursor-pointer">Troubleshooting</span>

<div class="absolute" id="bkmrk-%E2%80%8B-15" style="text-align: justify;">[​ <div class="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover:brightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20"><svg fill="gray" height="12px" viewbox="0 0 576 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg></div>](https://docs.typebot.io/self-hosting/deploy/docker#avoiding-network-issues-when-migrating-in-portainer)</div>### <span class="cursor-pointer">Avoiding network issues when migrating in Portainer</span>

If you migrate a Typebot stack between Portainer instances, hostname resolution may fail, causing `typebot-viewer` to be unable to connect to `typebot-db`.

Before deploying the stack in Portainer, ensure the network is **explicitly defined as attachable** in `docker-compose.yml`:

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk-copy-12" style="text-align: justify;"><div class="code-block mt-5 mb-8 not-prose rounded-2xl relative group p-0.5 text-gray-950 dark:text-gray-50 codeblock-light border border-gray-950/10 dark:border-white/10 bg-transparent dark:bg-transparent language-yml"><div class="z-10 absolute top-3 right-4"><button aria-label="Copy the contents from the code block" class="h-7 w-7 flex items-center justify-center rounded-md backdrop-blur peer group/copy-button" data-testid="copy-code-button"><svg class="w-4 h-4 text-gray-400 group-hover/copy-button:text-gray-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60" fill="none" height="18" viewbox="0 0 18 18" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg></button><div aria-hidden="true" class="absolute top-11 left-1/2 transform -translate-x-1/2 -translate-y-1/2 peer-hover:opacity-100 opacity-0 text-white rounded-lg px-1.5 py-0.5 text-xs bg-primary-dark">Copy</div></div><div class="min-w-full max-w-full dark:bg-codeblock rounded-[14px] relative text-sm leading-6 children:!my-0 children:!shadow-none children:!bg-transparent transition-[height] duration-300 ease-in-out overflow-x-auto py-3.5 px-4 h-full [&_*]:ring-0 [&_*]:outline-none [&_*]:focus:ring-0 [&_*]:focus:outline-none [&_pre>code]:pr-[3rem] [&_pre>code>span.line-highlight]:min-w-[calc(100%+3rem)] bg-white overflow-y-hidden scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-black/15 hover:scrollbar-thumb-black/20 active:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/20 dark:hover:scrollbar-thumb-white/25 dark:active:scrollbar-thumb-white/25" data-component-part="code-block-root" style="box-sizing: border-box; --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; --tw-rotate: 0; --tw-skew-x: 0; --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgba(59,130,246,.5); --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; position: relative; height: auto; min-width: 100%; max-width: 100%; overflow: auto hidden; border-radius: 14px; --tw-bg-opacity: 1; background-color: rgb(11, 12, 14); padding: 0.875rem 1rem; font-size: 0.875rem; line-height: 1.5rem; transition-property: height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.3s; --scrollbar-thumb: hsla(0,0%,100%,.2) !important; --scrollbar-thumb-radius: 0.25rem; animation-duration: 0.3s; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --scrollbar-thumb-hover: hsla(0,0%,100%,.25) !important; --scrollbar-thumb-active: hsla(0,0%,100%,.25) !important; font-weight: 400; font-variant-ligatures: none; border: 0px solid rgb(230, 225, 223);" tabindex="-1"><div tabindex="-1"></div></div></div></div>```
networks:
  typebot_network:
    driver: bridge
    attachable: true

services:
  typebot-db:
    ...
    networks:
      - typebot_network
  typebot-builder:
    ...
    networks:
      - typebot_network
  typebot-viewer:
    ...
    networks:
      - typebot_network
```

When deploying the stack, Portainer will automatically create the network with the correct settings. This prevents hostname resolution issues after migration.

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk--1" style="text-align: justify;"><div class="callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10" data-callout-type="note"><div class="mt-0.5 w-4" data-component-part="callout-icon"><svg aria-label="Note" class="w-4 h-4 text-sky-500" fill="currentColor" height="14" viewbox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z" fill-rule="evenodd"></path></svg></div><div class="text-sm prose min-w-0 w-full text-sky-900 dark:text-sky-200" data-component-part="callout-content">  
</div></div></div>If you’re self-hosting Typebot, [sponsoring me](https://github.com/sponsors/baptisteArno) is a great way to give back to the community and to contribute to the long-term sustainability of the project. It also comes with some perks like priority support and private workshops. ❤️

<div class="mdx-content relative mt-8 prose prose-gray dark:prose-invert" id="bkmrk--2" style="text-align: justify;"><div class="callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10" data-callout-type="note"><div class="text-sm prose min-w-0 w-full text-sky-900 dark:text-sky-200" data-component-part="callout-content">  
</div></div><div class="callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10" data-callout-type="note"><div class="mt-0.5 w-4" data-component-part="callout-icon"><svg aria-label="Note" class="w-4 h-4 text-sky-500" fill="currentColor" height="14" viewbox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z" fill-rule="evenodd"></path></svg></div><div class="text-sm prose min-w-0 w-full text-sky-900 dark:text-sky-200" data-component-part="callout-content">  
</div></div></div>This doc has been inspired by [Plausible docs](https://plausible.io/docs). They have a similar self-hosting solutions, and their documentation is 🔥.

<div class="leading-6 mt-14" id="bkmrk--3"><div class="feedback-toolbar pb-16 w-full"><div class="flex flex-col gap-y-4 xl:flex-col xl:gap-6 min-[1400px]:flex-row"><div class="flex flex-row gap-3 justify-end" style="text-align: justify;">[<svg class="h-3.5 w-3.5 block fill-current" viewbox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="M58.57 323.5L362.7 19.32C387.7-5.678 428.3-5.678 453.3 19.32L492.7 58.75C495.8 61.87 498.5 65.24 500.9 68.79C517.3 93.63 514.6 127.4 492.7 149.3L188.5 453.4C187.2 454.7 185.9 455.1 184.5 457.2C174.9 465.7 163.5 471.1 151.1 475.6L30.77 511C22.35 513.5 13.24 511.2 7.03 504.1C.8198 498.8-1.502 489.7 .976 481.2L36.37 360.9C40.53 346.8 48.16 333.9 58.57 323.5L58.57 323.5zM82.42 374.4L59.44 452.6L137.6 429.6C143.1 427.7 149.8 424.2 154.6 419.5L383 191L320.1 128.1L92.51 357.4C91.92 358 91.35 358.6 90.8 359.3C86.94 363.6 84.07 368.8 82.42 374.4L82.42 374.4z"></path></svg>](https://github.com/baptistearno/typebot.io/edit/main/apps/docs/self-hosting/deploy/docker.mdx)</div></div></div></div>