This guide provides step-by-step instructions for deploying StreamSource to a DigitalOcean Droplet using Docker. It is optimized for low-cost, single-droplet production setups and avoids installing Ruby/Node on the host.
- Overview
- Prerequisites
- Initial Droplet Setup
- Docker-First Application Deployment
- SSL/TLS Setup
- GitHub Actions Setup
- Cost Optimization
- Maintenance
- Troubleshooting
- Docker-first: Rails app runs in a container built from the repo Dockerfile
- Database: PostgreSQL 18 (managed or containerized)
- Cache/Sessions: Redis 8 (managed or containerized)
- Reverse Proxy: Nginx/Caddy or a cloud load balancer
- Droplet: ~$6/month (Basic, 1 vCPU, 1GB RAM, 25GB SSD)
- Optional: Managed DB/Redis adds cost but simplifies ops
- DigitalOcean account
- Domain name (recommended for SSL)
- GitHub repository with your StreamSource code
- SSH key pair for secure access
- Docker Engine + Docker Compose plugin (installed on the droplet)
# Via DigitalOcean UI:
# - Choose Ubuntu 24.04 LTS
# - Select Basic plan ($6/month)
# - Choose datacenter closest to users
# - Add your SSH key
# - Enable backups (optional)ssh root@your-droplet-ipInstall Docker using the official Docker docs for your OS. Confirm installation:
docker --version
docker compose versionadduser deploy
usermod -aG sudo deploy
usermod -aG docker deployLog in as the deploy user:
su - deploymkdir -p /var/www
cd /var/www
git clone https://github.com/YOUR_USERNAME/streamsource.git
cd streamsourceCreate a production env file from the template:
cp deploy/.env.production.template .env.production
nano .env.productionUpdate at least:
SECRET_KEY_BASEDATABASE_URLREDIS_URLAPPLICATION_HOST
If your env file lives elsewhere, set STREAMSOURCE_ENV_FILE=/path/to/.env.production when running Compose.
To deploy a registry image, set STREAMSOURCE_IMAGE=ghcr.io/your-org/streamsource:tag.
Start the app against external PostgreSQL/Redis (recommended for production):
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d webIf you want local containers instead, you can start them explicitly:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d web db rediscurl -f http://localhost:3000/healthTerminate TLS at a reverse proxy or a cloud load balancer. Common options:
- DigitalOcean Load Balancer (simplest)
- Nginx on the droplet
- Caddy (automatic HTTPS)
If using Nginx, point it to http://127.0.0.1:3000 and enable HTTPS with Let's Encrypt.
The deploy.yml workflow builds and pushes a Docker image (GHCR) and then SSHes into the droplet to pull and restart
the container with Docker Compose. If the repository is private, run docker login ghcr.io on the droplet using a
PAT that has read access to packages.
A minimal deploy step on the droplet looks like this:
cd /var/www/streamsource
docker compose -f docker-compose.yml -f docker-compose.prod.yml pull web
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d webYou can still use the scheduled power workflows, but update any shutdown scripts to stop containers first:
cd /var/www/streamsource
docker compose -f docker-compose.yml -f docker-compose.prod.yml down
sudo shutdown -h nowFor automated startup, use DigitalOcean's API to power on the droplet, then start containers:
cd /var/www/streamsource
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d web db redis# Update system packages (monthly)
sudo apt-get update && sudo apt-get upgrade
# Pull new image (if using a registry)
docker compose -f docker-compose.yml -f docker-compose.prod.yml pull web
# Recreate containers
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d web# App logs
cd /var/www/streamsource
docker compose -f docker-compose.yml -f docker-compose.prod.yml logs -f webIf you use containerized PostgreSQL:
# Example: run psql inside the container
cd /var/www/streamsource
docker compose -f docker-compose.yml -f docker-compose.prod.yml exec db psql -U streamsource -d streamsource_productiondocker compose -f docker-compose.yml -f docker-compose.prod.yml ps
docker compose -f docker-compose.yml -f docker-compose.prod.yml logs -f web- Confirm
DATABASE_URLis correct - Check Postgres container:
docker compose logs db
- Rebuild the image:
docker compose -f docker-compose.yml -f docker-compose.prod.yml build --no-cache web
If using a registry, pin to a previous image tag:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d web- SSH key authentication only (disable password auth)
- Firewall configured (UFW)
- SSL certificate installed
- Regular security updates
- Backups configured
This guide assumes a Docker-first deployment. The legacy, host-based deploy scripts in deploy/ can be used if you
need them, but they are no longer the recommended path.