- **Option 2**: For remote server deployment with HTTPS (using IP address). If you also have a custom domain, you can first deploy Dograh stack on your server using steps in this document and then proceed to the [Custom Domain](deployment/custom-domain) section.
The Quick Start above relies on direct peer-to-peer WebRTC between your browser and the API container. On most single-machine setups this works without any extra configuration. If you hit any of the following, you likely need a TURN server in the path:
- The call connects but no audio flows in either direction
- The browser console reports `iceConnectionState: failed`
- The host browsers should use to reach TURN (press Enter for `127.0.0.1`; use your LAN IP if testing from another device on the same network)
- A shared secret for the TURN server (press Enter to generate a random one)
It creates `docker-compose.yaml`, `turnserver.conf`, and a `.env` file with TURN credentials. Start the stack with the `local-turn` profile so coturn comes up alongside the other services:
```bash
docker compose --profile local-turn up --pull always
```
The application is still available at `http://localhost:3010`.
<Note>
To verify that media is actually traversing TURN (and not silently falling back to a direct path), set `FORCE_TURN_RELAY=true` in `.env` and restart the API. The browser will then only use relay ICE candidates — if TURN is misconfigured or unreachable, the call fails cleanly with `ICE failed` in the console instead of appearing to work. Set it back to `false` once you have verified connectivity.
Deploy Dograh AI on a remote server to make it accessible from anywhere using your server's IP address. This setup includes HTTPS support via nginx reverse proxy with self-signed certificates. **We need to serve the application over HTTPS, since modern browsers only allow microphone permissions for websites being served over HTTPS**.
<Warning>We highly recommend you set up the platform on a fresh server, so that there are less chances of confliciting dependencies, and ports from other applications.</Warning>
- TCP Ports 80, 443, 3478, 5349 and UDP Ports 3478, 5349 and 49152:49200 reachable from Internet (Port 80 and 443 to access the UI and rest of the ports for WebRTC Signaling)
<Note>IMPORTANT: Please double check the ports on your firewall. Please refer to your server hosting provider's documentaion on how you can open these ports in the firewall of the server.</Note>
- Deployment mode — press Enter for **prebuilt** (pulls official images, the recommended default) or pick **build** to compile images from source. Use **build** when you maintain a fork or want to deploy local customizations — see [Building from source](#building-from-source) below.
- Number of FastAPI workers (uvicorn processes nginx will load-balance) — press Enter for the default of `4`, or pick a value that suits your server's CPU count. See [Scaling](/deployment/scaling) for sizing guidance and how to change this on a running stack.
Please ensure that Docker Compose is installed on your machine before proceeding further. You can check whether its installed by running `docker compose version` command. If its not installed, please install it by following your server provider documentation.
If you maintain a fork or want to ship local code changes without waiting for an official image release, pick **build** when the setup script prompts for deployment mode.
In this mode the script:
1. Clones the repo into `dograh/` (default: `dograh-hq/dograh@main`; the script will ask for an `owner/name` and `branch` so a fork can point at its own).
2. If you run the script from inside an existing dograh checkout, offers to use that checkout instead of cloning.
3. Generates a `docker-compose.override.yaml` next to `docker-compose.yaml` that swaps the `image:` directives for local `build:` directives. Docker Compose auto-loads the override file — you don't need to pass any `-f` flags.
#### Updating after a code change
Whenever the codebase changes — a `git pull`, a local edit, or a submodule bump — rebuild the `api` and `ui` images and recreate the running containers so they pick up the new code.
**TL;DR (rebuilds both services and restarts in one shot):**
```bash
cd dograh
sudo docker compose --profile remote up -d --build
```
`--build` rebuilds any service whose `build:` context has changed (both `api` and `ui` are wired through the `docker-compose.override.yaml` written by `setup_remote.sh`), and `up -d` recreates the affected containers so they run off the new image.
**Step-by-step** — use this when you're pulling fresh code from a remote, or want to be explicit:
# 3. Recreate the running containers so they use the new images.
sudo docker compose --profile remote up -d
```
<Warning>If you update `pipecat` submodule, you must do `git submodule update --init --recursive`, or the Docker build step will not pick up `pipecat` changes</Warning>
**Rebuild a single service** — faster when you only changed one side:
sudo docker compose --profile remote up -d api # or: up -d ui
```
**Force a clean rebuild** — needed when a base image changed, a `pip install` was added, or you suspect a stale layer:
```bash
sudo docker compose --profile remote build --no-cache api ui
sudo docker compose --profile remote up -d
```
**Verify the containers were actually recreated** — check the `CREATED` column shows a recent timestamp, not minutes/hours ago:
```bash
sudo docker compose --profile remote ps
```
To revert to pulling official images, delete `docker-compose.override.yaml` and start the stack with `--pull always` as in the [prebuilt flow](#start-the-application).
<Note>
Build mode is for **fork maintainers and self-hosters who want to deploy customized images** — not for active development on the code itself. For day-to-day contributor work (fast reload, IDE/LSP integration), use the [contributor setup](/contribution/setup) instead.
Now that you are able to create and test a voice agent, you can setup a custom domain and setup SSL using letsencrypt. Checkout [Custom Domain](custom-domain) for instructions on how to do that.