Date: February 6, 2026
Overview
Complete migration from self-hosted droplet infrastructure to Digital Ocean App Platform with external services.
Architecture Changes
Before Migration
Single Droplet (209.38.80.86):
├── Backend (PM2 - port 3000)
├── Dashboard (Nginx static files)
├── Builder (PM2)
├── Redis (port 6379)
├── llama.cpp AI (port 11435)
├── Bank accounts worker (PM2)
└── Neto-Xero worker (PM2)
Separate Managed Services:
└── PostgreSQL Database
After Migration
DO App Platform:
├── Backend (fae2d400-6b1d-445f-ac49-7335b8e3b0b3)
│ └── https://rmm-psa-backend-t9f7k.ondigitalocean.app
└── Dashboard (154c7962-2022-49f8-b35d-fe1718b1b428)
└── https://everydaytech.au
External Droplet (209.38.80.86):
├── Redis (port 6379) - ACL user: doapp
├── llama.cpp AI (port 11435)
├── Bank accounts worker (PM2)
└── Neto-Xero worker (PM2)
Managed Services:
└── PostgreSQL Database (655f5c3e-190c-4229-a5df-61978ff5236d)
GitHub:
├── 9 repositories (Independent-Business-Group)
├── GitHub Actions (agent building)
└── GitHub Releases (binary hosting)
Repository Split
Monorepo split into 9 separate repositories:
- rmm-psa-agent - Legacy agent
- rmm-psa-agent-v2 - New agent with GitHub Actions
- rmm-psa-backend - Express.js API
- rmm-psa-builder - Builder utilities
- rmm-psa-dashboard - React frontend
- rmm-psa-database - Database schemas and migrations
- rmm-psa-devops - Infrastructure as code (app specs)
- rmm-psa-docs - Documentation
- rmm-psa-trayicon - System tray application
Deployment Specifications
Backend App Spec
Location: rmm-psa-devops/app-specs/backend-app.yaml
- Region: Sydney (syd)
- Environment: Production
- Auto-deploy: GitHub integration
- Health checks: Extended timeouts (60s)
Dashboard App Spec
Location: rmm-psa-devops/app-specs/dashboard-app.yaml
- Region: Sydney (syd)
- Type: Static site
- Build: Vite (npm run build)
- Custom domain: everydaytech.au
Key Configuration Changes
Redis ACL
Created dedicated user for App Platform:
ACL SETUSER doapp
>H+FRqSXauUIN4aAE45xdjj8tVNAMQaGb882ucUqad60=
+@all ~* &*
Database Firewall
Added App Platform to trusted sources (automatic by DO).
CORS Configuration
Backend allows:
Environment Variables
Backend (production secrets):
- Database credentials
- Redis connection
- AI endpoint
- JWT secret
- GitHub token (for releases)
Dashboard (build-time):
- API URLs
- WebSocket URL
- Feature flags
Cost Analysis
Previous Monthly Costs
- Droplet (4GB): ~$24/month
- Build droplet: ~$12/month
- DO Spaces: ~$5-20/month
- Database: ~$15/month
- Total: ~$56-71/month
Current Monthly Costs
- Backend (App Platform): ~$12/month
- Dashboard (Static site): $0/month
- Droplet (2GB, shared services): ~$6/month
- Database: ~$15/month
- Total: ~$33/month
Savings: ~$23-38/month (~40-50% reduction)
Services Status
Active on App Platform
- ✅ Backend API (port 8080)
- ✅ Dashboard (static site)
Active on Droplet
- ✅ Redis (port 6379)
- ✅ llama.cpp AI (port 11435)
- ✅ Bank accounts worker
- ✅ Neto-Xero worker
Removed from Droplet
- ❌ Backend (PM2) - moved to App Platform
- ❌ Builder (PM2) - replaced with GitHub Actions
Active on GitHub
- ✅ 9 repositories
- ✅ GitHub Actions (agent-v2 builds)
- ✅ GitHub Releases (binary hosting)
Deployment Procedures
Backend Deployment
# Automatic on git push to main
git push origin main
# Manual deployment
doctl apps update fae2d400-6b1d-445f-ac49-7335b8e3b0b3 \
--spec rmm-psa-devops/app-specs/backend-app.yaml
Dashboard Deployment
# Automatic on git push to main
git push origin main
# Manual deployment
doctl apps update 154c7962-2022-49f8-b35d-fe1718b1b428 \
--spec rmm-psa-devops/app-specs/dashboard-app.yaml
Agent Release
# Create and push version tag
git tag -a v2.0.1 -m "Release v2.0.1"
git push origin v2.0.1
# GitHub Actions automatically builds and creates release
Monitoring
Health Checks
Logs
# Backend logs
doctl apps logs fae2d400-6b1d-445f-ac49-7335b8e3b0b3 --type run
# Dashboard logs
doctl apps logs 154c7962-2022-49f8-b35d-fe1718b1b428 --type build
# Droplet services
ssh root@209.38.80.86 'pm2 logs'
GitHub Actions
Monitor builds: https://github.com/Independent-Business-Group/rmm-psa-agent-v2/actions
DNS Configuration
Cloudflare
everydaytech.au
├── Type: CNAME
├── Target: rmm-psa-dashboard-5jyun.ondigitalocean.app
└── Proxy: Optional (orange cloud for CDN)
Security Notes
- All secrets stored in DO App Platform environment variables (encrypted)
- Redis ACL restricts App Platform access
- Database uses managed SSL connections
- GitHub token required for private repository access
- JWT tokens for API authentication
Rollback Procedures
If issues arise:
- Check DO App Platform logs
- Verify environment variables
- Confirm external services (Redis, AI) are accessible
- Check database connectivity
- Review GitHub Actions workflow logs
Next Steps / Improvements
- Fix Linux and macOS builds in GitHub Actions workflow
- Consider enabling Cloudflare proxy for CDN
- Monitor costs and optimize resource allocation
- Set up monitoring/alerting for App Platform services
- Document API endpoints and integrations
References