Deploy an Astro Site to DigitalOcean With Nginx and Let's Encrypt
This is the exact setup running agenticoutputs.com. Ubuntu 24.04, Nginx, Certbot, and a simple rsync deploy script. No Docker, no CI/CD pipeline — just a fast, reliable static site on infrastructure you control.
Prerequisites
- A DigitalOcean droplet (Ubuntu 24.04 LTS, any size — the $6/mo Basic works)
- A domain with DNS pointed at your droplet IP
- An Astro project ready to build (
npm run buildoutputs todist/) - SSH access to the droplet
1. Provision the Droplet
When creating the droplet, add your SSH public key. Once it’s live:
ssh root@YOUR_DROPLET_IP
Create a non-root deploy user:
adduser deploy
usermod -aG sudo deploy
mkdir -p /home/deploy/.ssh
cp ~/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys
Disable root login:
sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
systemctl restart sshd
2. Install Nginx
apt update && apt install -y nginx
systemctl enable nginx
systemctl start nginx
3. Create the Web Root
mkdir -p /var/www/agenticoutputs/public
chown -R deploy:deploy /var/www/agenticoutputs
4. Configure the Nginx Virtual Host
nano /etc/nginx/sites-available/agenticoutputs.com
server {
listen 80;
server_name agenticoutputs.com www.agenticoutputs.com;
root /var/www/agenticoutputs/public;
index index.html;
location / {
try_files $uri $uri.html $uri/ =404;
}
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|webp|svg|ico|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Gzip
gzip on;
gzip_types text/plain text/css application/javascript image/svg+xml;
}
ln -s /etc/nginx/sites-available/agenticoutputs.com /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
5. Issue SSL Certificate
apt install -y certbot python3-certbot-nginx
certbot --nginx -d agenticoutputs.com -d www.agenticoutputs.com
Certbot will modify your Nginx config to add SSL and set up auto-renewal. Verify renewal works:
certbot renew --dry-run
6. Write the Deploy Script
On your local machine, at the root of your Astro project:
# scripts/deploy.sh
#!/bin/bash
set -e
echo "Building..."
npm run build
echo "Deploying..."
rsync -avz --delete dist/ deploy@YOUR_DROPLET_IP:/var/www/agenticoutputs/public/
echo "Done. https://agenticoutputs.com"
chmod +x scripts/deploy.sh
Add your droplet to ~/.ssh/config for cleaner commands:
Host droplet
HostName YOUR_DROPLET_IP
User deploy
IdentityFile ~/.ssh/id_rsa
Now update deploy.sh to use the alias:
rsync -avz --delete dist/ droplet:/var/www/agenticoutputs/public/
7. Ship It
bash scripts/deploy.sh
First deploy will take a few seconds (full sync). Subsequent deploys only transfer changed files — typically under 5 seconds for a content update.
Firewall
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
The Result
A static Astro site on infrastructure you own, with:
- Nginx serving pre-built HTML/CSS/JS directly (no Node.js process running)
- SSL via Let’s Encrypt with auto-renewal
- A one-command deploy from local to live
- Total monthly cost: $6
For a publication or portfolio, this beats managed hosting platforms on cost, performance, and control.