Deploy to DigitalOcean
Deploy your Bunty application to DigitalOcean using Droplets (VPS) or the App Platform (PaaS).
Option 1: App Platform (Recommended)
DigitalOcean App Platform is the easiest way to deploy with zero DevOps.
Quick Deploy
-
Connect Repository
- Go to cloud.digitalocean.com/apps
- Click βCreate Appβ
- Connect your GitHub/GitLab repository
-
Configure App
# .do/app.yaml
name: bunty-app
region: nyc
services:
- name: api
github:
repo: yourusername/bunty-app
branch: main
deploy_on_push: true
build_command: bun install
run_command: bun run src/main.ts
environment_slug: node-js
instance_count: 2
instance_size_slug: basic-xs
http_port: 3000
routes:
- path: /
envs:
- key: NODE_ENV
value: production
- key: PORT
value: "3000"
- key: DATABASE_URL
scope: RUN_TIME
type: SECRET
health_check:
http_path: /health
initial_delay_seconds: 30
period_seconds: 10
databases:
- name: bunty-db
engine: PG
production: true
version: "15"
- name: bunty-redis
engine: REDIS
production: true
version: "7"
workers:
- name: worker
github:
repo: yourusername/bunty-app
branch: main
build_command: bun install
run_command: bun run src/worker.ts
instance_count: 1
instance_size_slug: basic-xs
envs:
- key: NODE_ENV
value: production
jobs:
- name: cleanup
kind: PRE_DEPLOY
github:
repo: yourusername/bunty-app
branch: main
run_command: bun run migrate
Deploy via CLI
# Install doctl
# macOS
brew install doctl
# Linux
cd ~
wget https://github.com/digitalocean/doctl/releases/download/v1.94.0/doctl-1.94.0-linux-amd64.tar.gz
tar xf doctl-1.94.0-linux-amd64.tar.gz
sudo mv doctl /usr/local/bin
# Authenticate
doctl auth init
# Create app
doctl apps create --spec .do/app.yaml
# List apps
doctl apps list
# Deploy update
doctl apps update <app-id> --spec .do/app.yaml
# View logs
doctl apps logs <app-id>
Using Dockerfile
# .do/app.yaml
services:
- name: api
dockerfile_path: Dockerfile
source_dir: /
github:
repo: yourusername/bunty-app
branch: main
Option 2: Droplets (VPS)
Create Droplet
# Create droplet via CLI
doctl compute droplet create bunty-app \
--size s-2vcpu-2gb \
--image ubuntu-22-04-x64 \
--region nyc1 \
--ssh-keys <your-ssh-key-id> \
--enable-monitoring \
--wait
# Get droplet IP
doctl compute droplet list
Setup Droplet
# SSH into droplet
ssh root@your-droplet-ip
# Update system
apt update && apt upgrade -y
# Install Bun
curl -fsSL https://bun.sh/install | bash
source ~/.bashrc
# Install Node.js (optional)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
apt-get install -y nodejs
# Install PM2
npm install -g pm2
# Create deployment user
adduser --disabled-password deploy
usermod -aG sudo deploy
su - deploy
Deploy Application
# As deploy user
cd /home/deploy
# Clone repository
git clone https://github.com/yourusername/bunty-app.git
cd bunty-app
# Install dependencies
bun install --production
# Set up environment
nano .env.production
# Add your environment variables
# Start with PM2
pm2 start ecosystem.config.js --env production
# Save PM2 configuration
pm2 save
pm2 startup
# Setup Nginx
sudo apt install nginx -y
Configure Nginx
sudo nano /etc/nginx/sites-available/bunty-app
server {
listen 80;
server_name your-domain.com www.your-domain.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
# Enable site
sudo ln -s /etc/nginx/sites-available/bunty-app /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
# Install SSL with Let's Encrypt
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d your-domain.com -d www.your-domain.com
Managed Databases
Create PostgreSQL Database
# Via doctl
doctl databases create bunty-db \
--engine pg \
--region nyc1 \
--size db-s-1vcpu-1gb \
--version 15
# Get connection details
doctl databases connection bunty-db
# Create database
doctl databases db create bunty-db bunty
Create Redis Cluster
# Create Redis cluster
doctl databases create bunty-cache \
--engine redis \
--region nyc1 \
--size db-s-1vcpu-1gb \
--version 7
# Get connection string
doctl databases connection bunty-cache
Use in Application
import { DatabaseModule } from '@bunty/orm';
@Module({
imports: [
DatabaseModule.forRoot({
host: 'bunty-db-do-user-xxx.db.ondigitalocean.com',
port: 25060,
database: 'bunty',
user: 'doadmin',
password: process.env.DB_PASSWORD,
ssl: {
rejectUnauthorized: true,
ca: process.env.DB_CA_CERT,
},
}),
],
})
export class AppModule {}
Spaces (Object Storage)
Create Space
# Create Space (S3-compatible)
doctl compute spaces create bunty-uploads --region nyc3
# List spaces
doctl compute spaces list
Use in Application
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
const s3 = new S3Client({
endpoint: 'https://nyc3.digitaloceanspaces.com',
region: 'us-east-1', // Can be any region
credentials: {
accessKeyId: process.env.SPACES_KEY,
secretAccessKey: process.env.SPACES_SECRET,
},
});
async function upload(key: string, body: Buffer) {
await s3.send(new PutObjectCommand({
Bucket: 'bunty-uploads',
Key: key,
Body: body,
ACL: 'public-read',
}));
return `https://bunty-uploads.nyc3.digitaloceanspaces.com/${key}`;
}
Load Balancer
Create Load Balancer
# Create load balancer
doctl compute load-balancer create \
--name bunty-lb \
--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 \
--droplet-ids <droplet-id-1>,<droplet-id-2>
Configure SSL
# Add 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>
Container Registry
Push to Container Registry
# Create registry
doctl registry create bunty-registry
# Login
doctl registry login
# Build and tag
docker build -t bunty-app .
docker tag bunty-app registry.digitalocean.com/bunty-registry/bunty-app:latest
# Push
docker push registry.digitalocean.com/bunty-registry/bunty-app:latest
Kubernetes (DOKS)
Create Kubernetes Cluster
# Create cluster
doctl kubernetes cluster create bunty-k8s \
--region nyc1 \
--node-pool "name=workers;size=s-2vcpu-2gb;count=3;auto-scale=true;min-nodes=2;max-nodes=5"
# Get kubeconfig
doctl kubernetes cluster kubeconfig save bunty-k8s
# Deploy
kubectl apply -f k8s/
Monitoring
Enable Monitoring
# Create monitoring alert
doctl monitoring alert create \
--type v1/insights/droplet/cpu \
--compare GreaterThan \
--value 80 \
--window 5m \
--emails your@email.com
# View metrics
doctl monitoring metrics cpu <droplet-id>
Install Monitoring Agent
# On droplet
curl -sSL https://repos.insights.digitalocean.com/install.sh | sudo bash
# Verify
systemctl status do-agent
Automated Deployments
GitHub Actions
# .github/workflows/deploy.yml
name: Deploy to DigitalOcean
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install doctl
uses: digitalocean/action-doctl@v2
with:
token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
- name: Build and push to DOCR
run: |
doctl registry login
docker build -t registry.digitalocean.com/bunty-registry/bunty-app:${{ github.sha }} .
docker push registry.digitalocean.com/bunty-registry/bunty-app:${{ github.sha }}
- name: Update App Platform
run: |
doctl apps update ${{ secrets.APP_ID }} \
--image registry.digitalocean.com/bunty-registry/bunty-app:${{ github.sha }}
Deploy Script
#!/bin/bash
# deploy.sh
echo "Deploying to DigitalOcean..."
# Pull latest code
git pull origin main
# Install dependencies
bun install --production
# Run migrations
bun run migrate
# Reload PM2
pm2 reload bunty-app --update-env
echo "Deployment complete!"
Firewall
Create Firewall
# Create firewall
doctl compute firewall create \
--name bunty-firewall \
--inbound-rules "protocol:tcp,ports:22,sources:addresses:0.0.0.0/0,sources:addresses:::/0 protocol:tcp,ports:80,sources:addresses:0.0.0.0/0,sources:addresses:::/0 protocol:tcp,ports:443,sources:addresses:0.0.0.0/0,sources:addresses:::/0" \
--outbound-rules "protocol:tcp,ports:all,destinations:addresses:0.0.0.0/0,destinations:addresses:::/0" \
--droplet-ids <droplet-id>
Backups
Enable Droplet Backups
# Enable backups
doctl compute droplet-action enable-backups <droplet-id>
# List backups
doctl compute droplet-action snapshots <droplet-id>
Database Backups
# Get backup info
doctl databases backups list bunty-db
# Restore from backup
doctl databases restore bunty-db <backup-id>
Cost Optimization
- Use App Platform for variable workloads ($5-12/month)
- Start with smaller droplets ($6/month)
- Use auto-scaling
- Enable database backups
- Use Spaces instead of block storage when possible
Next Steps
- Set up CI/CD pipeline
- Configure monitoring
- Add CDN
- Implement caching