6.9 KiB
6.9 KiB
Deployment Guide
Complete setup for deploying the portfolio site with Docker, Caddy, and Oracle Cloud VPS.
Architecture
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Cloudflare │────▶│ Oracle VPS │────▶│ Vite Dev │
│ (DNS + Proxy) │ │ (Caddy) │ │ Server │
│ │ │ Port 80/443 │────▶│ Port 5173 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ Docker │
│ (Caddy) │
└─────────────────┘
Prerequisites
- Oracle Cloud VPS (or similar)
- Domain name (Cloudflare recommended)
- Docker + Docker Compose installed
- Git access to repository
Server Setup
1. Provision VPS
Oracle Cloud Free Tier:
- Create instance (Ubuntu 22.04/24.04 ARM or AMD)
- Add ingress rules for ports 22, 80, 443
- Note the public IP
Open Ports in Oracle Console:
- Networking → Virtual Cloud Networks
- Click your VCN → Subnets
- Security Lists → Default Security List
- Add Ingress Rules:
- TCP 80 from 0.0.0.0/0
- TCP 443 from 0.0.0.0/0
- TCP 22 from your IP (SSH)
2. Install Dependencies
# Update system
sudo apt update && sudo apt upgrade -y
# Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker
# Install Node.js 22
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
# Verify
node -v # Should be 20.19+ or 22.12+
npm -v
docker --version
3. Clone Repository
sudo mkdir -p /opt/peters-portfolio-site
sudo chown $USER:$USER /opt/peters-portfolio-site
cd /opt/peters-portfolio-site
git clone https://git.dustin.coffee/hobokenchicken/peters-portfolio-site.git .
4. Configure Caddy
Create directory structure:
mkdir -p docker_configs/caddy/conf
mkdir -p docker_configs/caddy/site
mkdir -p docker_configs/caddy/caddy_data
mkdir -p docker_configs/caddy/caddy_config
mkdir -p docker_configs/caddy/logs
Create docker_configs/caddy/conf/Caddyfile:
pwlmyers.org {
reverse_proxy 172.20.1.232:5173
log {
output file /var/log/caddy/access.log
format json
}
# Optional: Add headers
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
X-XSS-Protection "1; mode=block"
}
}
Note: Adjust 172.20.1.232 to match your Vite server's IP (check with ip addr show)
5. Docker Compose for Caddy
Create compose.caddy.yaml:
services:
caddy:
image: caddy:latest
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./docker_configs/caddy/conf:/etc/caddy
- ./docker_configs/caddy/site:/srv
- ./docker_configs/caddy/caddy_data:/data
- ./docker_configs/caddy/caddy_config:/config
- ./docker_configs/caddy/logs:/var/log/caddy
networks:
- caddy_network
networks:
caddy_network:
driver: bridge
6. DNS Configuration (Cloudflare)
-
Log into Cloudflare dashboard
-
Select your domain
-
DNS tab → Add records:
- Type:
A - Name:
@(root) orwww - Content:
150.136.209.11(your VPS IP) - Proxy status: 🟠 Orange cloud (proxied) or ⚪ Gray cloud (DNS only)
- TTL: Auto
- Type:
-
SSL/TLS tab:
- Mode: Full (strict) or Full
- Always Use HTTPS: On
7. Deploy Application
cd /opt/peters-portfolio-site
# Copy docs to public
cp -r docs/* public/docs/
# Install dependencies
npm install
# Start Vite dev server (background)
nohup npm run dev > vite.log 2>&1 &
# Start Caddy
docker compose -f compose.caddy.yaml up -d
8. Verify Deployment
# Check Caddy is running
docker ps | grep caddy
# Check Vite is running
ps aux | grep vite
curl http://172.20.1.232:5173/
# Test from VPS
curl -H "Host: pwlmyers.org" http://localhost/
# Test HTTPS (after DNS propagates)
curl -v https://pwlmyers.org/
Updates
Pull and Update
cd /opt/peters-portfolio-site
# Pull latest changes
git pull
# Reinstall if package.json changed
npm install
# Copy any new docs
cp -r docs/* public/docs/
# Restart Vite
pkill -f vite || true
nohup npm run dev > vite.log 2>&1 &
# Restart Caddy if config changed
docker compose -f compose.caddy.yaml restart
View Logs
# Vite logs
tail -f vite.log
# Caddy logs
docker logs -f ubuntu-caddy-1
tail -f docker_configs/caddy/logs/access.log
Troubleshooting
SSL Certificate Issues
If Caddy fails to get Let's Encrypt certificate:
# Check Cloudflare proxy status
dig pwlmyers.org +short
# Should return your VPS IP, not Cloudflare IPs
# If using Cloudflare proxy (orange cloud):
# - Use Cloudflare Origin Certificate
# - Or switch to DNS only (gray cloud) for Let's Encrypt
Port Already in Use
# Find what's using port 80/443
sudo netstat -tlnp | grep -E ':(80|443)'
# Stop conflicting service
sudo systemctl stop nginx apache2
Vite Not Accessible
# Check Vite is listening on all interfaces
netstat -tlnp | grep 5173
# Should show 0.0.0.0:5173, not 127.0.0.1:5173
# Check allowedHosts in vite.config.ts
cat vite.config.ts
Docker Network Issues
# Check Caddy can reach Vite
docker exec ubuntu-caddy-1 wget -qO- http://172.20.1.232:5173/
# If using Docker network instead of host IP:
docker network ls
docker network inspect caddy_caddy_network
Alternative: Systemd Service
Instead of nohup, create a systemd service for Vite:
sudo tee /etc/systemd/system/peters-portfolio.service > /dev/null <<'EOF'
[Unit]
Description=Peter's Portfolio Vite Dev Server
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/opt/peters-portfolio-site
ExecStart=/usr/bin/npm run dev
Restart=always
RestartSec=10
Environment=NODE_ENV=development
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable peters-portfolio
sudo systemctl start peters-portfolio
sudo systemctl status peters-portfolio
Security Notes
- Keep
node_modulesupdated:npm audit fix - Use Cloudflare proxy for DDoS protection
- Consider fail2ban for SSH brute force protection
- Regular backups of
docs/directory
Support
For issues with:
- Application code: Check README.md troubleshooting section
- Server/Docker: Check logs with commands above
- DNS/SSL: Verify Cloudflare settings and Oracle firewall rules