mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-28 08:49:42 +02:00
feat(scripts): free trusted HTTPS via sslip.io for public-IP remote i… (#460)
* feat(scripts): free trusted HTTPS via sslip.io for public-IP remote installs Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: refactor setup scripts * chore: generate sdk * chore: fix messaging for setup_remote script * fix: fix ffmpeg download url * feat: centralise and simplify the url configuration * fix: force script run as sudo * fix: fix documentation --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3309face2c
commit
78427817a6
30 changed files with 838 additions and 392 deletions
File diff suppressed because one or more lines are too long
|
|
@ -5,6 +5,10 @@ description: "Deploy Dograh AI with custom domain names and SSL certificates"
|
|||
|
||||
Deploy Dograh AI with your own custom domain name for a professional production setup. By now, you should be able to create and test a voice agent by following the previous guide to setup the platform on a remote server using [Docker](docker#option-2%3A-remote-server-deployment)
|
||||
|
||||
<Tip>
|
||||
**You don't need to own a domain just to remove the browser warning.** If your server has a public IP, the [remote setup](docker#option-2%3A-remote-server-deployment) already issues a free, auto-renewing Let's Encrypt certificate via [sslip.io](https://sslip.io) (e.g. `https://203-0-113-10.sslip.io`) — no DNS configuration required. Follow this Custom Domain guide only when you want your **own** domain name (e.g. `voice.yourcompany.com`).
|
||||
</Tip>
|
||||
|
||||
## What is Custom Domain Deployment?
|
||||
|
||||
Custom domain deployment allows you to run Dograh AI with a personalized domain name (like `voice.yourcompany.com`) instead of using IP addresses. This setup includes:
|
||||
|
|
@ -109,65 +113,50 @@ sudo apt install certbot -y
|
|||
sudo yum install certbot -y
|
||||
```
|
||||
|
||||
### Stop Dograh Services
|
||||
### Point `.env` at your domain
|
||||
|
||||
Before generating certificates, stop the running Dograh services to free up port 80:
|
||||
Update `.env` so the canonical remote settings use your domain — `dograh-init` reads these to render nginx's `server_name`. Replace `voice.yourcompany.com` with your actual domain throughout:
|
||||
|
||||
```bash
|
||||
cd dograh
|
||||
sudo docker compose --profile remote down
|
||||
sed -i "s/^PUBLIC_HOST=.*/PUBLIC_HOST=voice.yourcompany.com/" .env
|
||||
sed -i "s|^PUBLIC_BASE_URL=.*|PUBLIC_BASE_URL=https://voice.yourcompany.com|" .env
|
||||
```
|
||||
|
||||
### Generate SSL Certificates
|
||||
### Start services so nginx can answer the ACME challenge
|
||||
|
||||
Run Certbot to obtain SSL certificates for your domain:
|
||||
Bring the stack up (or recreate it) through the validated wrapper. nginx serves the Let's Encrypt HTTP-01 challenge from `certs/.well-known/acme-challenge/` on port 80, so the stack must be **running** during issuance — there's no need to stop it:
|
||||
|
||||
```bash
|
||||
sudo certbot certonly --standalone -d voice.yourcompany.com
|
||||
./remote_up.sh
|
||||
```
|
||||
|
||||
Replace `voice.yourcompany.com` with your actual domain name.
|
||||
### Generate the SSL certificate (webroot)
|
||||
|
||||
Issue the certificate using the webroot challenge served by the running nginx:
|
||||
|
||||
```bash
|
||||
sudo certbot certonly --webroot -w "$(pwd)/certs" -d voice.yourcompany.com
|
||||
```
|
||||
|
||||
Certbot will:
|
||||
1. Verify that you control the domain
|
||||
2. Generate SSL certificates
|
||||
3. Store them in `/etc/letsencrypt/live/voice.yourcompany.com/`
|
||||
1. Write a challenge file under `certs/.well-known/acme-challenge/`
|
||||
2. Have Let's Encrypt fetch it over HTTP (port 80) to verify you control the domain
|
||||
3. Store the certificate in `/etc/letsencrypt/live/voice.yourcompany.com/`
|
||||
|
||||
<Note>
|
||||
You'll be prompted to enter an email address for renewal notifications and agree to the terms of service.
|
||||
You'll be prompted for an email address (for renewal notices) and to agree to the terms of service. Because nginx keeps serving traffic throughout, issuance and renewal happen with **no downtime** — unlike the older `--standalone` flow, which had to stop the stack to free port 80.
|
||||
</Note>
|
||||
|
||||
### Copy Certificates to Dograh Directory
|
||||
### Copy the certificate and load it
|
||||
|
||||
Copy the generated certificates to the dograh certs directory:
|
||||
Copy the issued certificate into the `certs/` directory nginx reads, then restart nginx to load it:
|
||||
|
||||
```bash
|
||||
cd dograh
|
||||
sudo cp /etc/letsencrypt/live/voice.yourcompany.com/fullchain.pem certs/local.crt
|
||||
sudo cp /etc/letsencrypt/live/voice.yourcompany.com/privkey.pem certs/local.key
|
||||
sudo chmod 644 certs/local.crt certs/local.key
|
||||
```
|
||||
|
||||
### Update Canonical Public URL Settings
|
||||
|
||||
Update `.env` so the canonical remote settings point at your domain:
|
||||
|
||||
```bash
|
||||
nano dograh/.env
|
||||
```
|
||||
|
||||
```bash
|
||||
PUBLIC_HOST=voice.yourcompany.com
|
||||
PUBLIC_BASE_URL=https://voice.yourcompany.com
|
||||
```
|
||||
|
||||
### Start Dograh Services
|
||||
|
||||
Start Dograh through the validated startup wrapper so `dograh-init` regenerates nginx and coturn runtime config before Docker starts:
|
||||
|
||||
```bash
|
||||
cd dograh
|
||||
./remote_up.sh
|
||||
sudo docker compose --profile remote restart nginx
|
||||
```
|
||||
|
||||
### Access Your Application
|
||||
|
|
@ -222,7 +211,7 @@ sudo certbot renew --dry-run
|
|||
|
||||
If Certbot fails to generate certificates:
|
||||
|
||||
1. **Port 80 blocked**: Ensure port 80 is open in your firewall and no service is using it
|
||||
1. **Port 80 blocked**: Ensure port 80 is open in your firewall and reachable from the internet. With the webroot flow nginx must be **running** and serving the challenge on port 80 (don't stop the stack)
|
||||
2. **DNS not propagated**: Wait for DNS changes to propagate and verify with `nslookup`
|
||||
3. **Rate limits**: Let's Encrypt has rate limits. If you've exceeded them, wait before retrying
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ The script will prompt you for:
|
|||
It creates `docker-compose.yaml`, a `.env` file with JWT and TURN credentials, and the small helper bundle that `dograh-init` uses to render coturn config at startup. 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
|
||||
docker compose --profile local-turn --profile tunnel up --pull always
|
||||
```
|
||||
|
||||
The application is still available at `http://localhost:3010`.
|
||||
|
|
@ -123,13 +123,14 @@ Watch the video tutorial below for a step-by-step walkthrough of deploying Dogra
|
|||
allowFullScreen
|
||||
></iframe>
|
||||
|
||||
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**.
|
||||
Deploy Dograh AI on a remote server to make it accessible from anywhere. If your server has a **public IP**, setup obtains a free, trusted HTTPS certificate automatically via [sslip.io](https://sslip.io) and Let's Encrypt — no domain name or DNS configuration required, and no browser warning. On a private/reserved IP it falls back to a self-signed certificate. **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>
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- A server with Docker and Docker Compose installed. It should have minimum of 8 GB RAM and 4 vCPUs.
|
||||
- Root (`sudo`) access on the server — the setup script must be run as root and exits early otherwise.
|
||||
- Public IP address for your server. You can also access the server using a local IP address in your VPC as long as its reachable from your browser.
|
||||
- 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)
|
||||
|
||||
|
|
@ -140,9 +141,13 @@ Deploy Dograh AI on a remote server to make it accessible from anywhere using yo
|
|||
Run the automated setup script that will configure everything for you:
|
||||
|
||||
```bash
|
||||
curl -o setup_remote.sh https://raw.githubusercontent.com/dograh-hq/dograh/main/scripts/setup_remote.sh && chmod +x setup_remote.sh && ./setup_remote.sh
|
||||
curl -o setup_remote.sh https://raw.githubusercontent.com/dograh-hq/dograh/main/scripts/setup_remote.sh && chmod +x setup_remote.sh && sudo ./setup_remote.sh
|
||||
```
|
||||
|
||||
<Note>
|
||||
Run with `sudo` — the script must run as root (it provisions Docker, binds ports 80/443, and installs a Let's Encrypt certificate with a system renewal hook) and exits early if it isn't. On a public IP it obtains and auto-renews a trusted certificate; on a private IP it falls back to a self-signed one, since Let's Encrypt can't validate a private address. Optional environment-variable overrides: `CERT_MODE=self-signed` forces a self-signed cert, `ACME_DOMAIN_SUFFIX=nip.io` switches to the nip.io pool if sslip.io is rate-limited, and `LETSENCRYPT_EMAIL=you@example.com` sets the address for expiry notices.
|
||||
</Note>
|
||||
|
||||
The script will prompt you for:
|
||||
- Your server's public IP address
|
||||
- A password for the TURN server (optional, press Enter for default)
|
||||
|
|
@ -152,7 +157,8 @@ The script will prompt you for:
|
|||
It will automatically:
|
||||
- Get the source — `docker-compose.yaml` only (prebuilt mode), or clone the full repo (build mode)
|
||||
- Download the validated remote deployment helper bundle
|
||||
- Generate SSL certificates
|
||||
- Obtain a free trusted Let's Encrypt certificate via sslip.io and configure auto-renewal (public IP), or generate a self-signed certificate (private IP / no root)
|
||||
- For a public IP, also start the stack and print your ready-to-use `https://…sslip.io` URL
|
||||
- Create an environment file with TURN server configuration
|
||||
- Validate the runtime config that `dograh-init` will render from `.env`
|
||||
- Write a `docker-compose.override.yaml` with build directives (build mode only)
|
||||
|
|
@ -163,7 +169,7 @@ It will automatically:
|
|||
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.
|
||||
</Note>
|
||||
|
||||
After the setup script completes, start Dograh. The script prints the exact command to run at the end — it differs slightly between modes:
|
||||
After the setup script completes, start Dograh. For a **public-IP install the trusted-certificate flow already started the stack** and printed your `https://…sslip.io` URL — you can skip to [Access Your Application](#access-your-application). For a self-signed install, start it yourself (the script prints the exact command at the end — it differs slightly between modes):
|
||||
|
||||
<CodeGroup>
|
||||
```bash Prebuilt mode
|
||||
|
|
@ -180,13 +186,13 @@ First boot in build mode takes several minutes — Docker has to build both the
|
|||
|
||||
### Access Your Application
|
||||
|
||||
Your application will be available at
|
||||
```
|
||||
https://YOUR_SERVER_IP
|
||||
```
|
||||
Your application will be available at the URL the setup script printed at the end:
|
||||
|
||||
- **Public IP (trusted certificate):** `https://<your-ip-with-dashes>.sslip.io` — for example `https://203-0-113-10.sslip.io`. No browser warning.
|
||||
- **Self-signed (private IP):** `https://YOUR_SERVER_IP`
|
||||
|
||||
<Note>
|
||||
Since we are using a self-signed certificate, your browser will show a security warning. You can safely accept it to proceed.
|
||||
With a self-signed certificate your browser shows a security warning you can safely accept. With the sslip.io Let's Encrypt certificate there is no warning.
|
||||
</Note>
|
||||
|
||||
You should be able to create and test a voice agent now.
|
||||
|
|
@ -196,7 +202,7 @@ You should be able to create and test a voice agent now.
|
|||
- The remote deployment includes an nginx reverse proxy for HTTPS termination
|
||||
- File downloads (transcripts, recordings) are automatically routed through nginx
|
||||
- WebSocket connections for real-time features are properly proxied
|
||||
- The setup uses self-signed certificates - browsers will show a security warning that you can safely accept for testing
|
||||
- Public-IP installs get a trusted Let's Encrypt certificate (via sslip.io) that renews automatically; private-IP installs use a self-signed certificate (browser warning)
|
||||
- The TURN server (coturn) is configured for WebRTC NAT traversal
|
||||
- For production deployments with proper SSL and domain names, see the [Custom Domain](custom-domain) documentation
|
||||
|
||||
|
|
@ -213,7 +219,7 @@ The setup script creates the following files in the `dograh/` directory:
|
|||
| `scripts/lib/setup_common.sh` | Shared deployment helper library |
|
||||
| `deploy/templates/` | nginx and coturn runtime config templates |
|
||||
| `generate_certificate.sh` | Script to regenerate SSL certificates |
|
||||
| `certs/local.crt` | Self-signed SSL certificate |
|
||||
| `certs/local.crt` | SSL certificate (Let's Encrypt via sslip.io, or self-signed) |
|
||||
| `certs/local.key` | SSL private key |
|
||||
| `.env` | Single source of truth for deployment settings (TURN secret, JWT secret, FastAPI worker count, public host/base URL) |
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ Number of FastAPI workers (uvicorn processes nginx will load-balance):
|
|||
Press Enter for the default (`4`) or enter a different positive integer. Non-interactive callers (cloud-init, CI, Terraform) can set the value via environment variable instead:
|
||||
|
||||
```bash
|
||||
SERVER_IP=... TURN_SECRET=... FASTAPI_WORKERS=8 ./setup_remote.sh
|
||||
sudo SERVER_IP=... TURN_SECRET=... FASTAPI_WORKERS=8 ./setup_remote.sh
|
||||
```
|
||||
|
||||
The script stores the value in **`.env`** (`FASTAPI_WORKERS=N`). The supported startup path (`./remote_up.sh`) preflights the `dograh-init` render from that value before every remote start, so nginx and the API worker count stay aligned.
|
||||
|
|
|
|||
|
|
@ -65,7 +65,9 @@ Set these when `AUTH_PROVIDER=stack` to delegate sign-in to [Stack Auth](https:/
|
|||
|
||||
| Variable | Default | Description |
|
||||
|---|---|---|
|
||||
| `BACKEND_API_ENDPOINT` | `http://localhost:8000` | Internal URL of the backend API |
|
||||
| `PUBLIC_BASE_URL` | `null` | Canonical public origin for the deployment (scheme + host, e.g. `https://203-0-113-10.sslip.io`). For a standard single-host install this is the only endpoint value you set — `BACKEND_API_ENDPOINT` and `MINIO_PUBLIC_ENDPOINT` derive from it |
|
||||
| `PUBLIC_HOST` | `null` | Public host without scheme (e.g. `203-0-113-10.sslip.io`); `TURN_HOST` derives from it |
|
||||
| `BACKEND_API_ENDPOINT` | `PUBLIC_BASE_URL`, else `http://localhost:8000` | Public URL the backend builds webhook / callback / embed links from. Set explicitly only to override the value derived from `PUBLIC_BASE_URL` |
|
||||
| `UI_APP_URL` | `http://localhost:3010` | URL of the frontend application |
|
||||
| `MPS_API_URL` | `https://services.dograh.com` | Dograh Managed Platform Services URL |
|
||||
| `DOGRAH_MPS_SECRET_KEY` | `null` | **Required for non-OSS deployments.** Secret key for authenticating with MPS |
|
||||
|
|
@ -82,7 +84,7 @@ Dograh uses **MinIO by default**, which is bundled with the self-hosted deployme
|
|||
| Variable | Default | Description |
|
||||
|---|---|---|
|
||||
| `MINIO_ENDPOINT` | `localhost:9000` | MinIO server host and port |
|
||||
| `MINIO_PUBLIC_ENDPOINT` | `null` | Publicly accessible MinIO URL (for download links) |
|
||||
| `MINIO_PUBLIC_ENDPOINT` | `PUBLIC_BASE_URL`, else `http://localhost:9000` | Publicly accessible MinIO URL for download links. Derives from `PUBLIC_BASE_URL`; set explicitly only for a separate object-storage origin |
|
||||
| `MINIO_ACCESS_KEY` | N/A | **Required for OSS deployments.** MinIO access key. Must be set to a secure value in production |
|
||||
| `MINIO_SECRET_KEY` | N/A | **Required for OSS deployments.** MinIO secret key. Must be set to a secure value in production |
|
||||
| `MINIO_BUCKET` | `voice-audio` | Bucket name for audio files |
|
||||
|
|
@ -128,7 +130,7 @@ Presigned URLs point at `S3_ENDPOINT_URL`, so that host must be reachable from t
|
|||
|
||||
| Variable | Default | Description |
|
||||
|---|---|---|
|
||||
| `TURN_HOST` | `localhost` | TURN server hostname for WebRTC NAT traversal |
|
||||
| `TURN_HOST` | `PUBLIC_HOST`, else `localhost` | TURN server hostname for WebRTC NAT traversal. Derives from `PUBLIC_HOST`; set explicitly only when TURN runs on a separate host |
|
||||
| `TURN_PORT` | `3478` | TURN server port |
|
||||
| `TURN_TLS_PORT` | `5349` | TURN server TLS port |
|
||||
| `TURN_SECRET` | `null` | **Required for WebRTC.** Shared secret for TURN credential generation |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue