This guide will get demo.everydayoffice.au live in ~15 minutes.
Prerequisites
- ✅ DigitalOcean API token (in .env)
- ✅ Cloudflare API key (in .env)
- ✅ Managed PostgreSQL database (provisioned)
- ✅ Database migrations applied
- ✅ Root tenant/admin initialized
Step 1: Provision Droplet (2 minutes)
cd devops/digitalocean
./provision_droplet.sh
Output: Droplet IP address (save this!)
Wait 2-3 minutes for cloud-init to finish installing Node.js, NGINX, etc.
Step 2: Add Droplet to Database Firewall (30 seconds)
# The provision script outputs this command - copy and run it:
curl -X PUT -H "Authorization: Bearer $DO_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"trusted_sources":[{"type":"ip_addr","source":"<DROPLET_IP>"}]}' \
https://api.digitalocean.com/v2/databases/655f5c3e-190c-4229-a5df-61978ff5236d/firewall
Step 3: SSH into Droplet
Step 4: Create Environment Files on Droplet
# Create backend .env
mkdir -p /opt/apps && cd /opt/apps
git clone https://github.com/dablackfox/IBG_HUB.git
cd IBG_HUB/rmm-psa-platform/backend
cat > .env <<'ENV'
DATABASE_URL=postgresql://doadmin:AVNS_J8RJAmsEwsHFG52_-F2@rmm-psa-db-do-user-28531160-0.i.db.ondigitalocean.com:25060/defaultdb
JWT_SECRET=aFzl7P9UDEgc2hK7xLXGVj5tI1vTDsyRXSOEdBj55wA=
PORT=3000
ENV
Step 5: Deploy Application (3 minutes)
cd /opt/apps/IBG_HUB/rmm-psa-platform/devops/digitalocean
chmod +x deploy_to_droplet.sh
./deploy_to_droplet.sh
This will:
- Install backend dependencies
- Start backend with PM2
- Build dashboard (static files)
- Configure NGINX
Test locally:
curl http://localhost:3000/ # Backend health
curl http://localhost/ # Dashboard
Step 6: Setup Cloudflare Tunnel (5 minutes)
Still on the droplet:
# Authenticate Cloudflare
cloudflared tunnel login
# This will print a URL - open it in your browser and authorize
# Create tunnel
cloudflared tunnel create rmm-psa-demo
# Configure tunnel
mkdir -p /etc/cloudflared
cat > /etc/cloudflared/config.yml <<'TUNNEL'
tunnel: rmm-psa-demo
credentials-file: /root/.cloudflared/<TUNNEL_ID>.json
ingress:
- hostname: demo.everydayoffice.au
service: http://localhost:80
- service: http_status:404
TUNNEL
# Get tunnel ID
TUNNEL_ID=$(cloudflared tunnel list | grep rmm-psa-demo | awk '{print $1}')
echo "Tunnel ID: $TUNNEL_ID"
# Update config with actual tunnel ID
sed -i "s/<TUNNEL_ID>/$TUNNEL_ID/g" /etc/cloudflared/config.yml
# Install as system service
cloudflared service install
systemctl enable cloudflared
systemctl start cloudflared
systemctl status cloudflared
Step 7: Create DNS Record (1 minute)
Back on your local machine:
cd /home/cw/Documents/IBG_HUB/rmm-psa-platform/devops/cloudflare
# Get tunnel CNAME from droplet
ssh root@<DROPLET_IP> "cloudflared tunnel list | grep rmm-psa-demo | awk '{print \$4}'"
# Example output: abc123.cfargotunnel.com
# Create DNS record
./create_dns_for_demo.sh <TUNNEL_CNAME>
# Example: ./create_dns_for_demo.sh abc123.cfargotunnel.com
Step 8: Test!
Wait 1-2 minutes for DNS propagation, then:
curl https://demo.everydayoffice.au/
Open in browser:
Login with:
Troubleshooting
Backend not starting
Dashboard 404
ls -la /opt/apps/IBG_HUB/rmm-psa-platform/dashboard/dist/
nginx -t
Tunnel not routing
systemctl status cloudflared
journalctl -u cloudflared -f
Database connection error
# Test from droplet
curl https://api.digitalocean.com/v2/databases/655f5c3e-190c-4229-a5df-61978ff5236d/firewall \
-H "Authorization: Bearer $DO_API_TOKEN"
# Ensure droplet IP is in trusted_sources
Ongoing Maintenance
Auto-updates (already configured)
systemctl status rmm-auto-update.timer
Manual update
cd /opt/apps/IBG_HUB/rmm-psa-platform
git pull
cd backend && npm install --production && pm2 restart rmm-backend
cd ../dashboard && npm install && npm run build
View logs
pm2 logs rmm-backend # Backend logs
tail -f /var/log/nginx/access.log # NGINX access
tail -f /var/log/nginx/error.log # NGINX errors
Backup database
# DigitalOcean automatically backs up managed databases daily
# Manual export:
pg_dump "postgresql://doadmin:AVNS_J8RJAmsEwsHFG52_-F2@rmm-psa-db-do-user-28531160-0.i.db.ondigitalocean.com:25060/defaultdb?sslmode=require" > backup.sql
Cost Summary
- Droplet (1GB): $6/month
- Managed PostgreSQL (1GB): $15/month
- Total: $21/month
Security Notes
- ✅ Cloudflare proxy hides origin IP
- ✅ Database firewall (droplet IP only)
- ✅ UFW firewall on droplet
- ✅ SSL via Cloudflare
- ⚠️ Consider adding fail2ban for SSH protection
- ⚠️ Enable unattended-upgrades for security patches