DigitalOcean
intermediate
30-35 minutes

Custom Domains & Networking

Configure custom domains, DNS, load balancers, VPCs, and SSL certificates on DigitalOcean.

What you'll accomplish

Your application accessible via custom domain with proper networking

Prerequisites

  • Application deployed
  • Domain name you own

Domain Management

DigitalOcean provides free DNS hosting for your domains.

Add a Domain

bash
# Add domain to DigitalOcean
doctl compute domain create example.com

# Point to Droplet
doctl compute domain records create example.com \
  --record-type A \
  --record-name @ \
  --record-data DROPLET_IP \
  --record-ttl 1800

Update Nameservers

At your domain registrar, set nameservers to:

ns1.digitalocean.com
ns2.digitalocean.com
ns3.digitalocean.com

Common DNS Records

bash
# A record (IPv4)
doctl compute domain records create example.com \
  --record-type A \
  --record-name @ \
  --record-data 1.2.3.4

# AAAA record (IPv6)
doctl compute domain records create example.com \
  --record-type AAAA \
  --record-name @ \
  --record-data 2001:db8::1

# CNAME record (alias)
doctl compute domain records create example.com \
  --record-type CNAME \
  --record-name www \
  --record-data @

# MX record (email)
doctl compute domain records create example.com \
  --record-type MX \
  --record-name @ \
  --record-data mail.example.com \
  --record-priority 10

# TXT record (verification)
doctl compute domain records create example.com \
  --record-type TXT \
  --record-name @ \
  --record-data "v=spf1 include:_spf.google.com ~all"

List DNS Records

bash
doctl compute domain records list example.com

Update/Delete Records

bash
# Update record
doctl compute domain records update example.com \
  --record-id RECORD_ID \
  --record-data NEW_IP

# Delete record
doctl compute domain records delete example.com RECORD_ID

App Platform Domains

Add Custom Domain

  1. Control Panel → App → Settings → Domains
  2. Click Add Domain
  3. Enter your domain
  4. Follow DNS instructions

DNS Configuration for App Platform

TypeNameValue
CNAMEwwwyour-app.ondigitalocean.app
CNAME@your-app.ondigitalocean.app

Or use A record if CNAME not supported for apex:

TypeNameValue
A@(IP from DigitalOcean)

SSL Certificates

App Platform provides automatic SSL:

  • Let's Encrypt certificates
  • Automatic renewal
  • Force HTTPS option

Load Balancers

Distribute traffic across multiple Droplets.

Create Load Balancer

bash
# Create load balancer
doctl compute load-balancer create \
  --name mylb \
  --region nyc1 \
  --forwarding-rules "entry_protocol:http,entry_port:80,target_protocol:http,target_port:3000" \
  --health-check "protocol:http,port:3000,path:/health,check_interval_seconds:10,response_timeout_seconds:5,healthy_threshold:3,unhealthy_threshold:3" \
  --droplet-ids DROPLET_ID_1,DROPLET_ID_2

Using Tags

Auto-discover Droplets by tag:

bash
# Tag your Droplets
doctl compute droplet tag DROPLET_ID --tag-name web

# Create LB with tag
doctl compute load-balancer create \
  --name mylb \
  --region nyc1 \
  --tag-name web \
  --forwarding-rules "entry_protocol:http,entry_port:80,target_protocol:http,target_port:3000"

HTTPS Termination

bash
# First, upload certificate
doctl compute certificate create \
  --name mycert \
  --type lets_encrypt \
  --dns-names example.com,www.example.com

# Create HTTPS load balancer
doctl compute load-balancer create \
  --name mylb \
  --region nyc1 \
  --forwarding-rules "entry_protocol:https,entry_port:443,target_protocol:http,target_port:3000,certificate_id:CERT_ID" \
  --forwarding-rules "entry_protocol:http,entry_port:80,target_protocol:http,target_port:3000" \
  --redirect-http-to-https \
  --droplet-ids DROPLET_ID

Health Checks

Configure proper health checks:

bash
doctl compute load-balancer update LB_ID \
  --health-check "protocol:http,port:3000,path:/api/health,check_interval_seconds:10"

Sticky Sessions

bash
doctl compute load-balancer update LB_ID \
  --sticky-sessions "type:cookies,cookie_name:lb_session,cookie_ttl_seconds:3600"

VPC (Virtual Private Cloud)

Isolate your resources in private networks.

Create VPC

bash
# Create VPC
doctl vpcs create \
  --name myvpc \
  --description "Production VPC" \
  --region nyc1 \
  --ip-range 10.10.10.0/24

Create Resources in VPC

bash
# Create Droplet in VPC
doctl compute droplet create myserver \
  --image ubuntu-22-04-x64 \
  --size s-1vcpu-1gb \
  --region nyc1 \
  --vpc-uuid VPC_UUID

VPC Benefits

  • Resources communicate via private IPs
  • No bandwidth charges for VPC traffic
  • Isolated from other customers
  • Secure by default

List VPCs

bash
doctl vpcs list

Cloud Firewalls

Network-level security rules.

Create Firewall

bash
# Create firewall with rules
doctl compute firewall create \
  --name myfw \
  --inbound-rules "protocol:tcp,ports:22,address:YOUR_IP/32" \
  --inbound-rules "protocol:tcp,ports:80,address:0.0.0.0/0,::/0" \
  --inbound-rules "protocol:tcp,ports:443,address:0.0.0.0/0,::/0" \
  --outbound-rules "protocol:tcp,ports:all,address:0.0.0.0/0,::/0" \
  --outbound-rules "protocol:udp,ports:all,address:0.0.0.0/0,::/0" \
  --droplet-ids DROPLET_ID

Rule Examples

bash
# Allow SSH from specific IP
--inbound-rules "protocol:tcp,ports:22,address:1.2.3.4/32"

# Allow HTTP from anywhere
--inbound-rules "protocol:tcp,ports:80,address:0.0.0.0/0,::/0"

# Allow from tag
--inbound-rules "protocol:tcp,ports:3000,tag:web"

# Allow from load balancer
--inbound-rules "protocol:tcp,ports:3000,load_balancer_uid:LB_ID"

# Allow internal VPC traffic
--inbound-rules "protocol:tcp,ports:all,address:10.10.10.0/24"

Apply to Multiple Droplets

bash
# By tag
doctl compute firewall add-tags FW_ID --tag-names web,api

# By Droplet ID
doctl compute firewall add-droplets FW_ID --droplet-ids ID1,ID2

SSL Certificates

Let's Encrypt Certificates

DigitalOcean manages Let's Encrypt certificates:

bash
# Create certificate
doctl compute certificate create \
  --name mycert \
  --type lets_encrypt \
  --dns-names example.com,www.example.com

Requirements:

  • Domain DNS hosted on DigitalOcean
  • Domain points to DigitalOcean resources

Custom Certificates

bash
# Upload custom certificate
doctl compute certificate create \
  --name mycert \
  --type custom \
  --certificate-chain-path /path/to/fullchain.pem \
  --private-key-path /path/to/privkey.pem \
  --leaf-certificate-path /path/to/cert.pem

Use with Load Balancer

bash
# Get certificate ID
CERT_ID=$(doctl compute certificate list --format ID --no-header)

# Create HTTPS forwarding rule
doctl compute load-balancer update LB_ID \
  --forwarding-rules "entry_protocol:https,entry_port:443,target_protocol:http,target_port:3000,certificate_id:$CERT_ID"

Spaces CDN

Accelerate content delivery with the built-in CDN.

Enable CDN

bash
# Via Control Panel:
# Spaces → Your Space → Settings → CDN → Enable

CDN URL

https://space-name.region.cdn.digitaloceanspaces.com/file.jpg

Custom Domain for CDN

  1. Add CNAME record: cdn.example.com → space.region.cdn.digitaloceanspaces.com
  2. Configure in Space settings
  3. SSL automatically provided

Reserved IPs

Static IPs that can move between Droplets.

Create Reserved IP

bash
# Create and assign to Droplet
doctl compute reserved-ip create \
  --region nyc1 \
  --droplet-id DROPLET_ID

Reassign IP

bash
# Unassign
doctl compute reserved-ip-action unassign RESERVED_IP

# Assign to different Droplet
doctl compute reserved-ip-action assign RESERVED_IP DROPLET_ID

Use Cases

  • High availability (failover)
  • Consistent IP for DNS
  • Blue-green deployments

Complete Architecture Example

                    Internet
                       │
                       ▼
            ┌─────────────────────┐
            │   Load Balancer     │
            │   (HTTPS, SSL)      │
            └──────────┬──────────┘
                       │
         ┌─────────────┼─────────────┐
         ▼             ▼             ▼
    ┌─────────┐   ┌─────────┐   ┌─────────┐
    │ web-1   │   │ web-2   │   │ web-3   │
    │(Droplet)│   │(Droplet)│   │(Droplet)│
    └────┬────┘   └────┬────┘   └────┬────┘
         │             │             │
         └─────────────┼─────────────┘
                       │ (VPC)
                       ▼
            ┌─────────────────────┐
            │  Managed Database   │
            │   (PostgreSQL)      │
            └─────────────────────┘

Setup Script

bash
#!/bin/bash
set -e

# Configuration
REGION="nyc1"
PROJECT="myapp"

# Create VPC
VPC_ID=$(doctl vpcs create \
  --name ${PROJECT}-vpc \
  --region $REGION \
  --ip-range 10.10.10.0/24 \
  --output json | jq -r '.[0].id')
echo "VPC: $VPC_ID"

# Create Droplets
for i in 1 2; do
  doctl compute droplet create ${PROJECT}-web-$i \
    --image ubuntu-22-04-x64 \
    --size s-1vcpu-1gb \
    --region $REGION \
    --vpc-uuid $VPC_ID \
    --tag-names ${PROJECT}-web \
    --user-data-file setup.sh
done

# Wait for Droplets
sleep 60

# Create Load Balancer
LB_ID=$(doctl compute load-balancer create \
  --name ${PROJECT}-lb \
  --region $REGION \
  --tag-name ${PROJECT}-web \
  --forwarding-rules "entry_protocol:http,entry_port:80,target_protocol:http,target_port:3000" \
  --health-check "protocol:http,port:3000,path:/health" \
  --output json | jq -r '.[0].id')
echo "Load Balancer: $LB_ID"

# Create Firewall
doctl compute firewall create \
  --name ${PROJECT}-fw \
  --inbound-rules "protocol:tcp,ports:22,address:YOUR_IP/32" \
  --inbound-rules "protocol:tcp,ports:3000,load_balancer_uid:$LB_ID" \
  --outbound-rules "protocol:tcp,ports:all,address:0.0.0.0/0,::/0" \
  --tag-names ${PROJECT}-web

# Get LB IP
LB_IP=$(doctl compute load-balancer get $LB_ID --format IP --no-header)
echo "Load Balancer IP: $LB_IP"
echo "Point your domain to: $LB_IP"

Troubleshooting

DNS Not Propagating

bash
# Check DNS
dig example.com @ns1.digitalocean.com

# Wait up to 48 hours for global propagation
# Use https://dnschecker.org to verify

SSL Certificate Issues

  1. Verify domain points to DigitalOcean
  2. Check DNS is properly configured
  3. Wait for certificate provisioning (up to 24 hours)
  4. Check certificate status in Control Panel

Load Balancer Not Routing

  1. Check health checks are passing
  2. Verify Droplets are listening on target port
  3. Check firewall allows LB traffic
  4. Verify Droplets are in same region
Note

Checkpoint: Configure your custom domain with SSL, verify HTTPS is working, and test load balancer if using multiple backends.