Skip to main content
This guide will help you deploy Sure on a Hetzner Cloud server with Docker Compose, including SSL certificates, security hardening, and automated backups.

Prerequisites

Before starting, ensure you have:
  • A Hetzner Cloud server (recommended: 4GB RAM, 2 CPU cores minimum)
  • A domain name pointing to your server’s IP address
  • SSH access to your server
  • Basic familiarity with Linux command line
1

Server Setup and Security

Connect to your Hetzner server and set up the basic environment:
# Connect to your server (replace with your server's IP)
ssh root@YOUR_SERVER_IP

# Update the system
apt update && apt upgrade -y

# Install essential packages
apt install -y curl wget git ufw fail2ban

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh

# Install Docker Compose
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

# Add your user to docker group (replace 'your_username' with your actual username)
# If you are using root, you can skip this step
if [ "$(whoami)" != "root" ]; then
    usermod -aG docker "$(whoami)"
fi

# Configure firewall
ufw allow ssh
ufw allow 80
ufw allow 443
ufw --force enable

# Configure fail2ban for SSH protection
systemctl enable fail2ban
systemctl start fail2ban
2

Create Application Directory

# Create directory for the application
mkdir -p /opt/sure
cd /opt/sure

# Download the Docker Compose configuration
curl -o compose.yml https://raw.githubusercontent.com/we-promise/sure/main/compose.example.yml
3

Configure Environment Variables

Create a secure environment configuration:
# Create environment file
nano .env
Add the following content to the .env file (replace the values with your own):
# Generate a secure secret key
SECRET_KEY_BASE="$(openssl rand -hex 64)"

# Database configuration
POSTGRES_USER="sure_user"
POSTGRES_PASSWORD="$(openssl rand -base64 32)"
POSTGRES_DB="sure_production"

# Optional: OpenAI integration (add your API key if you want AI features)
# OPENAI_ACCESS_TOKEN="your_openai_api_key_here"
Important Security Notes:
  • Never use the default values from the example file in production
  • Keep your .env file secure and never commit it to version control
  • The SECRET_KEY_BASE is critical for Rails security - keep it secret
4

Set Up Reverse Proxy with SSL

We’ll use Nginx as a reverse proxy with Let’s Encrypt SSL certificates:
# Install Nginx and Certbot
apt install -y nginx certbot python3-certbot-nginx

# Create Nginx configuration for your domain
nano /etc/nginx/sites-available/sure
Add this Nginx configuration (replace yourdomain.com with your actual domain):
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    location / {
        proxy_pass http://localhost:3000;
        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_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
    }
}
# Enable the site
ln -s /etc/nginx/sites-available/sure /etc/nginx/sites-enabled/
rm /etc/nginx/sites-enabled/default

# Test Nginx configuration
nginx -t

# Start Nginx
systemctl enable nginx
systemctl start nginx

# Get SSL certificate
certbot --nginx -d yourdomain.com -d www.yourdomain.com
5

Deploy the Application

Now let’s deploy the Sure application:
# Navigate to the application directory
cd /opt/sure

# Pull the latest Docker images
docker compose pull

# Start the application
docker compose up -d

# Check if everything is running
docker compose ps

# View logs to ensure everything started correctly
docker compose logs -f
6

Test the Deployment

Verify your deployment is working:
# Check if the application is accessible
curl -I https://yourdomain.com

# Check Docker container health
docker compose ps
Now you can:
  1. Visit your application: Go to https://yourdomain.com in your browser
  2. Create your admin account: Click “Create your account” on the login page
  3. Set up your first family: Follow the onboarding process
7

Set Up Automated Backups

Create a backup script to protect your data:
# Create backup script
nano /opt/sure/backup.sh
Add this backup script:
#!/bin/bash
BACKUP_DIR="/opt/sure/backups"
DATE=$(date +%Y%m%d_%H%M%S)

# Create backup directory
mkdir -p $BACKUP_DIR

# Backup database
docker compose exec -T db pg_dump -U sure_user sure_production > $BACKUP_DIR/db_backup_$DATE.sql

# Backup application data
docker compose exec -T web tar -czf - /rails/storage > $BACKUP_DIR/storage_backup_$DATE.tar.gz

# Keep only last 7 days of backups
find $BACKUP_DIR -name "*.sql" -mtime +7 -delete
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete

echo "Backup completed: $DATE"
# Make backup script executable
chmod +x /opt/sure/backup.sh

# Add to crontab for daily backups at 2 AM
crontab -e
Add this line to crontab:
0 2 * * * /opt/sure/backup.sh >> /var/log/sure-backup.log 2>&1
8

Set Up Basic Monitoring

Create a health check script to monitor your application:
# Install htop for system monitoring
apt install -y htop

# Create a simple health check script
nano /opt/sure/health-check.sh
Add this health check script:
#!/bin/bash
# Check if the application is responding
if curl -f -s https://yourdomain.com > /dev/null; then
    echo "$(date): Application is healthy"
else
    echo "$(date): Application is down - restarting"
    cd /opt/sure
    docker compose restart web worker
fi
# Make health check executable
chmod +x /opt/sure/health-check.sh

# Add to crontab to run every 5 minutes
crontab -e
Add this line:
*/5 * * * * /opt/sure/health-check.sh >> /var/log/sure-health.log 2>&1

Maintenance Commands

Here are the essential commands for maintaining your deployment:

Update the application

cd /opt/sure
docker compose pull
docker compose up --no-deps -d web worker

View logs

docker compose logs -f

Restart services

docker compose restart

Check system resources

docker stats

Restore from backup

docker compose exec -T db psql -U sure_user sure_production < /opt/sure/backups/db_backup_YYYYMMDD_HHMMSS.sql

Security Features

Your deployment includes several security measures:
  1. Firewall: Only ports 22 (SSH), 80 (HTTP), and 443 (HTTPS) are open
  2. Fail2ban: Protects against brute force attacks on SSH
  3. SSL/TLS: Automatic HTTPS with Let’s Encrypt certificates
  4. Environment variables: Sensitive data stored securely in .env file
  5. Non-root containers: Application runs as non-root user
  6. Regular updates: Keep your system and Docker images updated

Troubleshooting

Common Issues and Solutions

# Check logs for errors
docker compose logs -f

# Check if ports are available
netstat -tulpn | grep :3000
# Check database container
docker compose logs db

# Test database connection
docker compose exec db psql -U sure_user -d sure_production -c "SELECT 1;"
# Renew certificates
certbot renew --dry-run

# Check certificate status
certbot certificates
# Check disk usage
df -h

# Clean up Docker images
docker system prune -a

# Clean up old backups
find /opt/sure/backups -name "*.sql" -mtime +7 -delete
# Check system resources
htop
docker stats

# Check if containers are healthy
docker compose ps

Performance Optimization

For better performance on Hetzner Cloud:
  1. Use SSD storage: Hetzner Cloud provides NVMe SSD storage by default
  2. Choose appropriate server size:
    • Minimum: CX21 (2 vCPU, 4GB RAM)
    • Recommended: CX31 (2 vCPU, 8GB RAM) for multiple users
  3. Enable swap (if needed):
    fallocate -l 2G /swapfile
    chmod 600 /swapfile
    mkswap /swapfile
    swapon /swapfile
    echo '/swapfile none swap sw 0 0' >> /etc/fstab
    

Backup Strategy

Your backup strategy includes:
  1. Daily automated backups of database and application data
  2. 7-day retention of backup files
  3. Separate backup directory at /opt/sure/backups
  4. Logging of backup operations
Consider additional backup options:
  • Off-site backups: Copy backups to external storage (AWS S3, Google Cloud, etc.)
  • Database replication: Set up PostgreSQL streaming replication
  • Snapshot backups: Use Hetzner Cloud snapshots for full system backups

Next Steps

After successful deployment:
  1. Create your admin account at https://yourdomain.com
  2. Set up your first family in the application
  3. Configure bank connections (if using Plaid integration)
  4. Set up additional users as needed
  5. Monitor your deployment using the health check logs

Support

If you encounter issues:
  1. Check the troubleshooting section above
  2. Review the application logs: docker compose logs -f
  3. Check system resources: htop and df -h
  4. Open a discussion in our GitHub repository

Security Reminders

  • Keep your server updated: apt update && apt upgrade
  • Monitor your logs regularly: /var/log/sure-backup.log and /var/log/sure-health.log
  • Use strong passwords for all accounts
  • Consider setting up SSH key authentication instead of password authentication
  • Regularly review your firewall rules: ufw status
  • Monitor your SSL certificate expiration: certbot certificates

Build docs developers (and LLMs) love