Documentation Index Fetch the complete documentation index at: https://mintlify.com/egeuysall/ryva-archive/llms.txt
Use this file to discover all available pages before exploring further.
This guide covers deploying Ryva to production environments using Docker containers.
Overview
Ryva uses a containerized architecture with:
Backend : Go API in Alpine Linux container
Caddy : Reverse proxy with SSL, rate limiting, and security headers
GitHub Container Registry (GHCR) : Pre-built production images
Architecture
┌─────────────┐
│ Internet │
└──────┬──────┘
│
▼
┌─────────────────┐
│ Caddy (Port 80/443) │
│ - SSL/TLS │
│ - Rate Limiting│
│ - CORS Headers │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Backend:8080 │
│ (Go API) │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ PostgreSQL │
│ (Supabase) │
└─────────────────┘
Prerequisites
Server Requirements
OS : Ubuntu 22.04+ or similar Linux distribution
RAM : Minimum 1GB (2GB+ recommended)
CPU : 1 vCPU minimum (2+ recommended)
Disk : 10GB+ available space
Docker : 24.0+ installed
Docker Compose : 2.0+ installed
Domain Requirements
Domain name (e.g., ryva.dev)
DNS A record pointing to your server IP
Subdomain for API (e.g., api.ryva.dev)
External Services
Supabase project with PostgreSQL database
(Optional) Sentry account for error tracking
(Optional) Stripe account for payments
Production Setup
Step 1: Server Preparation
Install Docker
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Add user to docker group
sudo usermod -aG docker $USER
# Log out and back in for group changes to take effect
Install Docker Compose
# Docker Compose is included with Docker by default
# Verify installation
docker compose version
Configure firewall
# Allow SSH, HTTP, and HTTPS
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
# Verify firewall status
sudo ufw status
Step 2: Clone Repository
# Clone the repository
git clone https://github.com/egeuysall/ryva.git
cd ryva
# Checkout the production branch (or specific version tag)
git checkout master
For production, always use tagged releases (e.g., git checkout v1.0.0) rather than branch heads.
Step 3: Environment Configuration
Create API environment file
# Create .env from example
cp apps/api/.env.example apps/api/.env
# Or use the make command
make setup-vps
Configure API environment variables
Edit apps/api/.env with production values: Required Configuration :# Application
GO_ENV = production
PORT = 8080
# Supabase
SUPABASE_URL = https://your-project.supabase.co
SUPABASE_ANON_KEY = your-production-anon-key
SUPABASE_SERVICE_ROLE_KEY = your-production-service-role-key
DATABASE_URL = postgresql://postgres:[password ]@db.your-project.supabase.co:5432/postgres
# JWT
JWT_SECRET = your-secure-random-secret-min-32-chars
JWT_EXPIRY = 24h
# CORS
ALLOWED_ORIGINS = https://ryva.dev,https://www.ryva.dev
# Sentry (optional)
SENTRY_DSN = https://your-sentry-dsn@sentry.io/project-id
SENTRY_ENVIRONMENT = production
# Email (Resend)
RESEND_API_KEY = re_your_api_key
RESEND_FROM_EMAIL = noreply@ryva.dev
RESEND_FROM_NAME = Ryva
# Stripe (optional)
STRIPE_SECRET_KEY = sk_live_your_key
STRIPE_WEBHOOK_SECRET = whsec_your_secret
Use strong, randomly generated secrets for JWT_SECRET in production:
Configure Docker environment
Create environment file for Docker Compose: # GitHub Container Registry settings
GITHUB_REPOSITORY_OWNER = egeuysall
IMAGE_TAG = latest
CADDY_IMAGE_TAG = latest
Update Caddyfile with your domain
Edit infra/caddy/Caddyfile: nano infra/caddy/Caddyfile
Update the domain and email: {
email your-email@example.com # For Let's Encrypt notifications
grace_period 30s
admin off
}
# Your API domain
api.yourdomain.com {
# ... rest of configuration
}
Update CORS origins
In the same Caddyfile, update CORS headers: Access-Control-Allow-Origin "https://yourdomain.com"
Step 5: Deploy with Docker Compose
Pull production images
# Pull latest images from GHCR
docker compose pull
Start services
# Start containers in detached mode
docker compose up -d
# Or use make command
make docker-up
Verify deployment
# Check container status
docker compose ps
# View logs
docker compose logs -f
# Check backend health
curl https://api.yourdomain.com/health
Local Docker Development
For testing Docker setup locally:
# Use local compose file that builds from source
docker compose -f docker-compose.local.yml up -d
# View logs
docker compose -f docker-compose.local.yml logs -f
# Stop services
docker compose -f docker-compose.local.yml down
Local development uses Caddyfile.local which works with localhost domains.
Docker Commands Reference
Container Management
# Start containers
make docker-up
# or
docker compose up -d
# Stop containers
make docker-down
# or
docker compose down
# Restart containers
docker compose restart
# View container status
docker compose ps
# View resource usage
docker stats
Logs and Debugging
# View all logs
make docker-logs
# or
docker compose logs -f
# View specific service logs
docker compose logs -f backend
docker compose logs -f caddy
# View last 100 lines
docker compose logs --tail=100 backend
# Execute command in running container
docker compose exec backend sh
Updates and Rebuilds
# Pull latest images
docker compose pull
# Rebuild and restart
docker compose up -d --build
# Build specific service
docker compose build backend
# Remove unused images
docker image prune -a
Multi-stage Docker Build
Ryva’s backend uses a multi-stage Dockerfile for optimal image size:
# Stage 1: Build
FROM golang:1.25-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags= "-s -w" -o api ./cmd/server/main.go
# Stage 2: Runtime
FROM alpine:3.20
RUN apk add --no-cache ca-certificates curl
RUN adduser -D -s /bin/sh appuser
USER appuser
WORKDIR /app
COPY --from=builder /app/api .
CMD [ "./api" ]
Benefits :
Small final image (~20MB vs 300MB+)
No build tools in production
Runs as non-root user
Includes health check
Container Resource Limits
Production containers have resource limits configured:
services :
backend :
mem_limit : 512m # Maximum 512MB RAM
cpus : 0.5 # Maximum 50% of 1 CPU core
Adjust these limits based on your server resources and application needs.
Health Checks
Both services include health checks:
Backend Health Check
healthcheck :
test : [ 'CMD' , 'wget' , '--quiet' , '--tries=1' , '-O' , '-' , 'http://localhost:8080/health' ]
interval : 10s
timeout : 5s
retries : 3
start_period : 10s
Caddy Health Check
Caddy monitors backend health and stops routing traffic to unhealthy instances:
reverse_proxy backend:8080 {
health_uri /health
health_interval 10s
health_timeout 5s
health_status 2xx
}
SSL/TLS Configuration
Caddy automatically obtains and renews SSL certificates from Let’s Encrypt:
Automatic SSL
Caddy handles SSL automatically when you use a domain name:
Obtains certificates on first request
Renews certificates automatically before expiry
Enforces HTTPS redirects
Verify SSL
# Test SSL certificate
curl -vI https://api.yourdomain.com
# Check certificate expiry
echo | openssl s_client -connect api.yourdomain.com:443 2> /dev/null | openssl x509 -noout -dates
Zero-Downtime Deployments
For production updates with minimal downtime:
Restart with rolling update
# Stop and remove old containers
docker compose down
# Start new containers
docker compose up -d
Verify deployment
# Check all containers are healthy
docker compose ps
# Monitor logs during startup
docker compose logs -f backend
# Test API endpoint
curl https://api.yourdomain.com/health
For true zero-downtime deployments, consider using container orchestration platforms like Kubernetes or Docker Swarm.
Monitoring and Logs
Log Configuration
Logs are configured with rotation to prevent disk space issues:
logging :
driver : json-file
options :
max-size : '10m' # Maximum 10MB per log file
max-file : '3' # Keep 3 rotated files
Caddy Access Logs
Caddy logs are stored in the caddy_logs volume:
# View Caddy access logs
docker compose exec caddy cat /var/log/caddy/api-access.log
# Follow Caddy logs
docker compose exec caddy tail -f /var/log/caddy/api-access.log
Application Logs
# Backend application logs
docker compose logs -f backend
# Filter logs by time
docker compose logs --since 1h backend
# Save logs to file
docker compose logs backend > backend.log
Backup and Recovery
Volume Backup
# Backup Caddy data (SSL certs, etc.)
docker run --rm \
-v ryva_caddy_data:/data \
-v $( pwd ) :/backup \
alpine tar czf /backup/caddy-data-backup.tar.gz -C /data .
Database Backup
Since Ryva uses Supabase (managed PostgreSQL), backups are handled by Supabase:
Automatic daily backups
Point-in-time recovery
Manual backups via Supabase dashboard
Troubleshooting
# Check container logs
docker compose logs backend
# Check container status
docker compose ps
# Inspect container
docker inspect ryva-backend
# Common issues:
# - Missing .env file
# - Invalid environment variables
# - Port conflicts
# - Database connection issues
# Check Caddy logs
docker compose logs caddy
# Common issues:
# - DNS not pointing to server
# - Firewall blocking port 443
# - Domain not accessible from internet
# - Rate limits from Let's Encrypt
# Force certificate renewal
docker compose exec caddy caddy reload --config /etc/caddy/Caddyfile
# Check resource usage
docker stats
# Adjust memory limits in docker-compose.yml
# backend:
# mem_limit: 1g # Increase to 1GB
# Restart containers
docker compose down && docker compose up -d
Database migrations not running
# Check backend logs for migration errors
docker compose logs backend | grep migration
# Run migrations manually
docker compose exec backend ./api migrate-up
# Verify DATABASE_URL is correct
docker compose exec backend env | grep DATABASE_URL
Security Best Practices
Environment Variables
Never commit .env files to git
Use strong random secrets (32+ characters)
Rotate secrets regularly
Use different secrets for each environment
Container Security
Run containers as non-root user
Keep images updated
Scan images for vulnerabilities
Use minimal base images (Alpine)
Network Security
Enable firewall (ufw)
Use HTTPS only
Configure CORS properly
Implement rate limiting
Monitoring
Monitor container health
Set up alerts for failures
Review logs regularly
Use Sentry for error tracking
Next Steps
Database Migrations Manage database schema changes in production
Environment Variables Complete environment configuration reference