diff --git a/README.md b/README.md index 33a1249..916ef91 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Dograh AI -

If you find value in this project, PLEASE STAR the Github repository to help others discover our FOSS platform!

+

If you find value in this project, please STAR the Github repository to help others discover our FOSS platform!

@@ -37,11 +37,14 @@ The only command you need to run: -##### Download and setup Dograh on your local machine +##### Download and setup Dograh on your Local Machine > **Note** > We collect anonymous usage data to improve the product. You can opt out by setting the `ENABLE_TELEMETRY` to `false` in the below command. +> **Note** +> If you wish to run the platform on a remote server instead, checkout our [Documentation](https://docs.dograh.com/deployment/docker#option-2:-remote-server-deployment) + ```bash curl -o docker-compose.yaml https://raw.githubusercontent.com/dograh-hq/dograh/main/docker-compose.yaml && REGISTRY=ghcr.io/dograh-hq ENABLE_TELEMETRY=true docker compose up --pull always ``` diff --git a/docs/deployment/custom-domain.mdx b/docs/deployment/custom-domain.mdx index 5109c32..073b080 100644 --- a/docs/deployment/custom-domain.mdx +++ b/docs/deployment/custom-domain.mdx @@ -1,9 +1,9 @@ --- -title: "Custom Domain (Coming Soon)" -description: "Deploy Dograh AI with custom domain names and proper SSL certificates" +title: "Custom Domain" +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. +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) ## What is Custom Domain Deployment? @@ -14,20 +14,231 @@ Custom domain deployment allows you to run Dograh AI with a personalized domain - **Professional Setup**: Production-ready configuration for business use - **Easy Sharing**: Share a clean URL with your team and customers -## Benefits +## Prerequisites -- **Better User Experience**: Clean, memorable URLs for your voice AI applications -- **SSL Security**: Proper HTTPS certificates that browsers trust -- **Professional Image**: Custom domains enhance your brand presence -- **Easy Management**: Simplified access and sharing across your organization +Before starting, ensure you have: -## Coming Soon +- A domain name you own (e.g., `yourcompany.com`) +- Access to your domain's DNS settings (usually through your domain registrar) +- Dograh AI already running on your server via the [remote deployment](docker#option-2%3A-remote-server-deployment) guide +- Your server's public IP address -Detailed documentation for custom domain deployment will be available soon. This will include: +## Step 1: Configure DNS Records -- Step-by-step domain configuration -- Automated SSL certificate setup -- Production deployment best practices -- Custom domain routing configuration +You need to create a DNS record that points your domain to your server's IP address. + +### Add an A Record + +Log in to your domain registrar or DNS provider and add an A record: + +| Setting | Value | +|---------|-------| +| Type | A | +| Name/Host | `voice` (or `@` for root domain) | +| Value/Points to | Your server's IP address (e.g., `203.0.113.50`) | +| TTL | 300 (or default) | + + +DNS changes can take anywhere from a few minutes to 48 hours to propagate, though most changes take effect within 5-30 minutes. You can check if your DNS has propagated using tools like [dnschecker.org](https://dnschecker.org). + + +### Verify DNS Propagation + +Before proceeding, verify that your domain points to your server: + +```bash +nslookup voice.yourcompany.com +``` + +You should see your server's IP address in the response. + +## Step 2: Quick Setup (Recommended) + +Once your DNS is configured, run the automated setup script that handles the rest: + +```bash +curl -o setup_custom_domain.sh https://raw.githubusercontent.com/dograh-hq/dograh/main/scripts/setup_custom_domain.sh && chmod +x setup_custom_domain.sh && sudo ./setup_custom_domain.sh +``` + +The script will prompt you for: +- Your domain name +- An email address for Let's Encrypt notifications + +It will automatically: +- Verify DNS configuration +- Install Certbot +- Generate Let's Encrypt SSL certificates +- Update nginx configuration +- Configure automatic certificate renewal +- Restart Dograh services + +Once complete, your application will be available at `https://voice.yourcompany.com`. + + +If you prefer to set things up manually, continue with the steps below. + + +--- + +## Manual Setup + +If you prefer to configure everything manually, follow these steps instead of using the automated script. + +### Install Certbot + +Certbot is the official Let's Encrypt client that automates SSL certificate generation. + +**Ubuntu/Debian:** + +```bash +sudo apt update +sudo apt install certbot -y +``` + +**Amazon Linux/RHEL:** + +```bash +sudo yum install certbot -y +``` + +### Stop Dograh Services + +Before generating certificates, stop the running Dograh services to free up port 80: + +```bash +cd dograh +sudo docker compose --profile remote down +``` + +### Generate SSL Certificates + +Run Certbot to obtain SSL certificates for your domain: + +```bash +sudo certbot certonly --standalone -d voice.yourcompany.com +``` + +Replace `voice.yourcompany.com` with your actual domain name. + +Certbot will: +1. Verify that you control the domain +2. Generate SSL certificates +3. Store them in `/etc/letsencrypt/archive/voice.yourcompany.com/` + + +You'll be prompted to enter an email address for renewal notifications and agree to the terms of service. + + +### Copy Certificates to Dograh Directory + +Copy the generated certificates to the dograh certs directory: + +```bash +cd dograh +sudo cp /etc/letsencrypt/archive/voice.yourcompany.com/fullchain1.pem certs/local.crt +sudo cp /etc/letsencrypt/archive/voice.yourcompany.com/privkey1.pem certs/local.key +sudo chmod 644 certs/local.crt certs/local.key +``` + +### Update nginx Configuration + +Update the nginx configuration to use your domain name. Open the nginx configuration file: + +```bash +nano dograh/nginx.conf +``` + +Update the `server_name` directive with your domain: + +```nginx +server { + listen 443 ssl; + server_name voice.yourcompany.com; + + ssl_certificate /etc/nginx/certs/local.crt; + ssl_certificate_key /etc/nginx/certs/local.key; + + # ... rest of the configuration remains the same +} +``` + +### Start Dograh Services + +Start Dograh with the updated configuration: + +```bash +cd dograh +sudo docker compose --profile remote up -d --pull always +``` + +### Access Your Application + +Your application is now available at: + +``` +https://voice.yourcompany.com +``` + +You should see a valid SSL certificate (green padlock) in your browser. + +### Set Up Certificate Renewal + +Let's Encrypt certificates expire after 90 days. Set up automatic renewal. + +Create a renewal hook script that copies the new certificates: + +```bash +sudo nano /etc/letsencrypt/renewal-hooks/deploy/dograh-reload.sh +``` + +Add the following content (replace paths as needed): + +```bash +#!/bin/bash +# Copy renewed certificates to dograh certs directory +cp /etc/letsencrypt/archive/voice.yourcompany.com/fullchain1.pem /home/ubuntu/dograh/certs/local.crt +cp /etc/letsencrypt/archive/voice.yourcompany.com/privkey1.pem /home/ubuntu/dograh/certs/local.key +chmod 644 /home/ubuntu/dograh/certs/local.crt /home/ubuntu/dograh/certs/local.key + +# Restart nginx to load new certificates +cd /home/ubuntu/dograh +docker compose --profile remote restart nginx +``` + +Make the script executable: + +```bash +sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/dograh-reload.sh +``` + +Test that renewal works: + +```bash +sudo certbot renew --dry-run +``` + +## Troubleshooting + +### Certificate Generation Fails + +If Certbot fails to generate certificates: + +1. **Port 80 blocked**: Ensure port 80 is open in your firewall and no service is using it +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 + +### SSL Certificate Errors in Browser + +If you see SSL errors after setup: + +1. Verify the certificates were copied correctly: `ls -la dograh/certs/` +2. Check that `nginx.conf` points to `/etc/nginx/certs/local.crt` and `/etc/nginx/certs/local.key` +3. Restart the nginx container: `sudo docker compose --profile remote restart nginx` + +### WebRTC Connection Issues + +If voice calls don't connect after domain setup: + +1. Ensure TCP/UDP ports 3478, 5349, and UDP 49152-49200 are still open +2. Update the `.env` file with your domain name if needed for TURN server configuration -For early access or assistance with custom domain deployment, please [join our Slack community](https://join.slack.com/t/dograh-community/shared_invite/zt-3czr47sw5-MSg1J0kJ7IMPOCHF~03auQ) and let us know about your use case. \ No newline at end of file diff --git a/docs/deployment/docker.mdx b/docs/deployment/docker.mdx index a849eb8..2936f0a 100644 --- a/docs/deployment/docker.mdx +++ b/docs/deployment/docker.mdx @@ -74,12 +74,12 @@ After the setup script completes, start Dograh: ```bash cd dograh -docker compose --profile remote up -d +sudo docker compose --profile remote up --pull always ``` ### Access Your Application -Your application will be available at: +Your application will be available at ``` https://YOUR_SERVER_IP ``` @@ -88,6 +88,8 @@ https://YOUR_SERVER_IP Since we are using a self-signed certificate, your browser will show a security warning. You can safely accept it to proceed. +You should be able to create and test a voice agent now. + ### Configuration Notes - The remote deployment includes an nginx reverse proxy for HTTPS termination @@ -109,3 +111,6 @@ The setup script creates the following files in the `dograh/` directory: | `certs/local.crt` | Self-signed SSL certificate | | `certs/local.key` | SSL private key | | `.env` | Environment variables for TURN server | + +### Next Steps +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. diff --git a/scripts/setup_custom_domain.sh b/scripts/setup_custom_domain.sh new file mode 100755 index 0000000..4b6e2b4 --- /dev/null +++ b/scripts/setup_custom_domain.sh @@ -0,0 +1,295 @@ +#!/bin/bash +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +echo -e "${BLUE}" +echo "╔══════════════════════════════════════════════════════════════╗" +echo "║ Dograh Custom Domain Setup ║" +echo "║ Automated Let's Encrypt SSL certificate setup ║" +echo "╚══════════════════════════════════════════════════════════════╝" +echo -e "${NC}" + +# Check if running as root or with sudo +if [[ $EUID -ne 0 ]]; then + echo -e "${RED}Error: This script must be run as root or with sudo${NC}" + exit 1 +fi + +# Check if dograh directory exists +if [[ ! -d "dograh" ]]; then + echo -e "${RED}Error: 'dograh' directory not found.${NC}" + echo -e "${YELLOW}Please run this script from the directory containing your Dograh installation.${NC}" + echo -e "${YELLOW}If you haven't set up Dograh yet, run the remote setup first:${NC}" + echo -e "${BLUE} 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${NC}" + exit 1 +fi + +# Get the domain name +echo -e "${YELLOW}Enter your domain name (e.g., voice.yourcompany.com):${NC}" +read -p "> " DOMAIN_NAME + +if [[ -z "$DOMAIN_NAME" ]]; then + echo -e "${RED}Error: Domain name cannot be empty${NC}" + exit 1 +fi + +# Basic domain validation +if ! [[ "$DOMAIN_NAME" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*\.[a-zA-Z]{2,}$ ]]; then + echo -e "${RED}Error: Invalid domain name format${NC}" + exit 1 +fi + +# Get email for Let's Encrypt notifications +echo -e "${YELLOW}Enter your email address for SSL certificate notifications:${NC}" +read -p "> " EMAIL_ADDRESS + +if [[ -z "$EMAIL_ADDRESS" ]]; then + echo -e "${RED}Error: Email address cannot be empty (required by Let's Encrypt)${NC}" + exit 1 +fi + +echo "" +echo -e "${GREEN}Configuration:${NC}" +echo -e " Domain: ${BLUE}$DOMAIN_NAME${NC}" +echo -e " Email: ${BLUE}$EMAIL_ADDRESS${NC}" +echo "" + +# Verify DNS is pointing to this server +echo -e "${BLUE}[1/7] Verifying DNS configuration...${NC}" +SERVER_IP=$(curl -s ifconfig.me || curl -s icanhazip.com || echo "") +RESOLVED_IP=$(dig +short "$DOMAIN_NAME" | tail -1) + +if [[ -z "$SERVER_IP" ]]; then + echo -e "${YELLOW}Warning: Could not detect server's public IP${NC}" +elif [[ "$RESOLVED_IP" != "$SERVER_IP" ]]; then + echo -e "${YELLOW}Warning: Domain '$DOMAIN_NAME' resolves to '$RESOLVED_IP' but this server's IP is '$SERVER_IP'${NC}" + echo -e "${YELLOW}Make sure your DNS A record points to this server before proceeding.${NC}" + echo "" + read -p "Continue anyway? (y/N) > " CONTINUE + if [[ ! "$CONTINUE" =~ ^[Yy]$ ]]; then + echo -e "${RED}Setup cancelled. Please configure DNS and try again.${NC}" + exit 1 + fi +else + echo -e "${GREEN}✓ DNS is correctly configured (${RESOLVED_IP})${NC}" +fi + +# Detect package manager and install certbot +echo -e "${BLUE}[2/7] Installing Certbot...${NC}" +if command -v apt-get &> /dev/null; then + apt-get update -qq + apt-get install -y -qq certbot +elif command -v yum &> /dev/null; then + yum install -y -q certbot +elif command -v dnf &> /dev/null; then + dnf install -y -q certbot +else + echo -e "${RED}Error: Could not detect package manager. Please install certbot manually.${NC}" + exit 1 +fi +echo -e "${GREEN}✓ Certbot installed${NC}" + +# Stop Dograh services to free port 80 +echo -e "${BLUE}[3/7] Stopping Dograh services...${NC}" +cd dograh +if docker compose --profile remote ps --quiet 2>/dev/null | grep -q .; then + docker compose --profile remote down + echo -e "${GREEN}✓ Dograh services stopped${NC}" +else + echo -e "${YELLOW}⚠ No running services found${NC}" +fi + +# Generate SSL certificate +echo -e "${BLUE}[4/7] Generating Let's Encrypt SSL certificate...${NC}" +CERTBOT_OUTPUT=$(certbot certonly --standalone \ + --non-interactive \ + --agree-tos \ + --email "$EMAIL_ADDRESS" \ + -d "$DOMAIN_NAME" 2>&1) || { + echo -e "${RED}✗ Certificate generation failed${NC}" + echo "" + + # Check for common errors and provide helpful hints + if echo "$CERTBOT_OUTPUT" | grep -qi "timeout\|firewall\|connection"; then + echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}" + echo -e "${YELLOW} Port 80 appears to be blocked by a firewall.${NC}" + echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}" + echo "" + echo -e "Let's Encrypt needs to connect to port 80 to verify domain ownership." + echo "" + echo -e "${BLUE}If using AWS EC2:${NC}" + echo " 1. Go to AWS Console → EC2 → Security Groups" + echo " 2. Find the security group for your instance" + echo " 3. Add inbound rule: HTTP | TCP | Port 80 | 0.0.0.0/0" + echo "" + echo -e "${BLUE}If using another cloud provider:${NC}" + echo " • Ensure port 80 (TCP) is open for inbound traffic from all sources" + echo "" + elif echo "$CERTBOT_OUTPUT" | grep -qi "too many\|rate.limit"; then + echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}" + echo -e "${YELLOW} Let's Encrypt rate limit reached.${NC}" + echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}" + echo "" + echo "You've requested too many certificates recently." + echo "Please wait before trying again (usually 1 hour)." + echo "" + elif echo "$CERTBOT_OUTPUT" | grep -qi "dns\|resolve\|NXDOMAIN"; then + echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}" + echo -e "${YELLOW} DNS resolution failed.${NC}" + echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}" + echo "" + echo "The domain '$DOMAIN_NAME' does not resolve to this server." + echo "Please verify your DNS A record is correctly configured." + echo "" + else + echo -e "${YELLOW}Certbot output:${NC}" + echo "$CERTBOT_OUTPUT" + echo "" + fi + + echo -e "After fixing the issue, re-run this script:" + echo -e " ${BLUE}sudo ./setup_custom_domain.sh${NC}" + echo "" + exit 1 +} +echo -e "${GREEN}✓ SSL certificate generated${NC}" + +# Verify and display certificate location +CERT_PATH="/etc/letsencrypt/live/$DOMAIN_NAME" +echo "" +echo -e "${BLUE}Certificate location:${NC}" +echo -e " ${CERT_PATH}/" +if [[ -f "$CERT_PATH/fullchain.pem" ]]; then + echo -e " ${GREEN}✓${NC} fullchain.pem exists" +else + echo -e " ${RED}✗${NC} fullchain.pem NOT FOUND" +fi +if [[ -f "$CERT_PATH/privkey.pem" ]]; then + echo -e " ${GREEN}✓${NC} privkey.pem exists" +else + echo -e " ${RED}✗${NC} privkey.pem NOT FOUND" +fi +echo "" + +# Copy certificates to dograh/certs directory +cp /etc/letsencrypt/archive/$DOMAIN_NAME/fullchain1.pem certs/local.crt +cp /etc/letsencrypt/archive/$DOMAIN_NAME/privkey1.pem certs/local.key +chmod 644 certs/local.crt certs/local.key +echo -e "${GREEN}✓${NC} Certificates copied to certs/ directory" +echo "" + +# Update nginx.conf +echo -e "${BLUE}[5/7] Updating nginx configuration...${NC}" +cat > nginx.conf << NGINX_EOF +server { + listen 80; + server_name $DOMAIN_NAME; + + # Redirect all HTTP to HTTPS + return 301 https://\$host\$request_uri; +} + +server { + listen 443 ssl; + server_name $DOMAIN_NAME; + + ssl_certificate /etc/nginx/certs/local.crt; + ssl_certificate_key /etc/nginx/certs/local.key; + + # TLS settings + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; + + location / { + proxy_pass http://ui:3010; + proxy_http_version 1.1; + + # Important for WebSockets / hot reload etc. + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + + # Rewrite localhost MinIO URLs in API responses to use current domain + sub_filter 'http://localhost:9000/voice-audio/' 'https://\$host/voice-audio/'; + sub_filter_once off; + sub_filter_types application/json text/html; + } + + location /voice-audio/ { + proxy_pass http://minio:9000/voice-audio/; + + proxy_http_version 1.1; + + # Headers for file downloads from MinIO + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + + # Allow large file downloads + proxy_buffering off; + client_max_body_size 100M; + } +} +NGINX_EOF +echo -e "${GREEN}✓ nginx.conf updated${NC}" + +# Setup auto-renewal +echo -e "${BLUE}[6/7] Setting up automatic certificate renewal...${NC}" +DOGRAH_PATH=$(pwd) + +# Create renewal hook script that copies new certificates and restarts nginx +cat > /etc/letsencrypt/renewal-hooks/deploy/dograh-reload.sh << HOOK_EOF +#!/bin/bash +# Copy renewed certificates to dograh certs directory +cp /etc/letsencrypt/archive/$DOMAIN_NAME/fullchain1.pem $DOGRAH_PATH/certs/local.crt +cp /etc/letsencrypt/archive/$DOMAIN_NAME/privkey1.pem $DOGRAH_PATH/certs/local.key +chmod 644 $DOGRAH_PATH/certs/local.crt $DOGRAH_PATH/certs/local.key + +# Restart nginx to load new certificates +cd $DOGRAH_PATH +docker compose --profile remote restart nginx 2>/dev/null || true +HOOK_EOF +chmod +x /etc/letsencrypt/renewal-hooks/deploy/dograh-reload.sh + +# Test renewal +certbot renew --dry-run --quiet && echo -e "${GREEN}✓ Auto-renewal configured and tested${NC}" || echo -e "${YELLOW}⚠ Auto-renewal test had issues, but certificates are installed${NC}" + +# Start Dograh services +echo "" +echo -e "${BLUE}[7/7] Starting Dograh services...${NC}" +docker compose --profile remote up -d --pull always + +echo "" +echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}" +echo -e "${GREEN}║ Custom Domain Setup Complete! ║${NC}" +echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}" +echo "" +echo -e "${YELLOW}Your application is now available at:${NC}" +echo "" +echo -e " ${BLUE}https://$DOMAIN_NAME${NC}" +echo "" +echo -e "${GREEN}SSL Certificate Details:${NC}" +echo -e " Certificate: $DOGRAH_PATH/certs/local.crt" +echo -e " Private Key: $DOGRAH_PATH/certs/local.key" +echo -e " Auto-renewal: Enabled (certificates renew automatically)" +echo "" +echo -e "${YELLOW}Files modified:${NC}" +echo " - dograh/nginx.conf (updated with domain name)" +echo " - dograh/certs/local.crt (SSL certificate)" +echo " - dograh/certs/local.key (SSL private key)" +echo " - /etc/letsencrypt/renewal-hooks/deploy/dograh-reload.sh (renewal hook)" +echo "" +echo -e "${GREEN}Your SSL certificate will automatically renew before expiration.${NC}" +echo "" diff --git a/scripts/setup_remote.sh b/scripts/setup_remote.sh index 002b670..f35284f 100755 --- a/scripts/setup_remote.sh +++ b/scripts/setup_remote.sh @@ -160,7 +160,7 @@ echo " - .env" echo "" echo -e "${YELLOW}To start Dograh, run:${NC}" echo "" -echo -e " ${BLUE}docker compose --profile remote up -d${NC}" +echo -e " ${BLUE}sudo docker compose --profile remote up --pull always${NC}" echo "" echo -e "${YELLOW}Your application will be available at:${NC}" echo ""