mirror of
https://github.com/we-promise/sure.git
synced 2026-04-07 14:31:25 +00:00
* Add comprehensive Hetzner Cloud deployment guide * Fix markdown linting issues and backup retention policy - Add missing language identifiers to fenced code blocks (bash) - Fix inconsistent backup retention policy (standardize to 7 days) - Address CodeRabbit review feedback for PR #211
435 lines
10 KiB
Markdown
435 lines
10 KiB
Markdown
# Deploying Sure on Hetzner Cloud
|
|
|
|
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
|
|
|
|
## Step 1: Server Setup and Security
|
|
|
|
Connect to your Hetzner server and set up the basic environment:
|
|
|
|
```bash
|
|
# 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
|
|
```
|
|
|
|
## Step 2: Create Application Directory
|
|
|
|
```bash
|
|
# 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
|
|
```
|
|
|
|
## Step 3: Configure Environment Variables
|
|
|
|
Create a secure environment configuration:
|
|
|
|
```bash
|
|
# Create environment file
|
|
nano .env
|
|
```
|
|
|
|
Add the following content to the `.env` file (replace the values with your own):
|
|
|
|
```bash
|
|
# 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
|
|
|
|
## Step 4: Set Up Reverse Proxy with SSL
|
|
|
|
We'll use Nginx as a reverse proxy with Let's Encrypt SSL certificates:
|
|
|
|
```bash
|
|
# 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):
|
|
|
|
```nginx
|
|
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;
|
|
}
|
|
}
|
|
```
|
|
|
|
```bash
|
|
# 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
|
|
```
|
|
|
|
## Step 5: Deploy the Application
|
|
|
|
Now let's deploy the Sure application:
|
|
|
|
```bash
|
|
# 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
|
|
```
|
|
|
|
## Step 6: Test the Deployment
|
|
|
|
Verify your deployment is working:
|
|
|
|
```bash
|
|
# 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
|
|
|
|
## Step 7: Set Up Automated Backups
|
|
|
|
Create a backup script to protect your data:
|
|
|
|
```bash
|
|
# Create backup script
|
|
nano /opt/sure/backup.sh
|
|
```
|
|
|
|
Add this backup script:
|
|
|
|
```bash
|
|
#!/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"
|
|
```
|
|
|
|
```bash
|
|
# 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:
|
|
```bash
|
|
0 2 * * * /opt/sure/backup.sh >> /var/log/sure-backup.log 2>&1
|
|
```
|
|
|
|
## Step 8: Set Up Basic Monitoring
|
|
|
|
Create a health check script to monitor your application:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
#!/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
|
|
```
|
|
|
|
```bash
|
|
# Make health check executable
|
|
chmod +x /opt/sure/health-check.sh
|
|
|
|
# Add to crontab to run every 5 minutes
|
|
crontab -e
|
|
```
|
|
|
|
Add this line:
|
|
```bash
|
|
*/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:
|
|
```bash
|
|
cd /opt/sure
|
|
docker compose pull
|
|
docker compose up --no-deps -d web worker
|
|
```
|
|
|
|
### View logs:
|
|
```bash
|
|
# All services
|
|
docker compose logs -f
|
|
|
|
# Specific service
|
|
docker compose logs -f web
|
|
docker compose logs -f worker
|
|
docker compose logs -f db
|
|
```
|
|
|
|
### Restart services:
|
|
```bash
|
|
# Restart all services
|
|
docker compose restart
|
|
|
|
# Restart specific service
|
|
docker compose restart web
|
|
```
|
|
|
|
### Check system resources:
|
|
```bash
|
|
# Docker resource usage
|
|
docker stats
|
|
|
|
# System resources
|
|
htop
|
|
df -h
|
|
```
|
|
|
|
### Restore from backup:
|
|
```bash
|
|
# Restore database
|
|
docker compose exec -T db psql -U sure_user sure_production < /opt/sure/backups/db_backup_YYYYMMDD_HHMMSS.sql
|
|
|
|
# Restore application data
|
|
docker compose exec -T web tar -xzf /opt/sure/backups/storage_backup_YYYYMMDD_HHMMSS.tar.gz -C /
|
|
```
|
|
|
|
## 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
|
|
|
|
**Application won't start:**
|
|
```bash
|
|
# Check logs for errors
|
|
docker compose logs -f
|
|
|
|
# Check if ports are available
|
|
netstat -tulpn | grep :3000
|
|
```
|
|
|
|
**Database connection issues:**
|
|
```bash
|
|
# Check database container
|
|
docker compose logs db
|
|
|
|
# Test database connection
|
|
docker compose exec db psql -U sure_user -d sure_production -c "SELECT 1;"
|
|
```
|
|
|
|
**SSL certificate issues:**
|
|
```bash
|
|
# Renew certificates
|
|
certbot renew --dry-run
|
|
|
|
# Check certificate status
|
|
certbot certificates
|
|
```
|
|
|
|
**Out of disk space:**
|
|
```bash
|
|
# 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
|
|
```
|
|
|
|
**Application is slow:**
|
|
```bash
|
|
# 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):
|
|
```bash
|
|
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](#troubleshooting) 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](https://github.com/we-promise/sure/discussions)
|
|
|
|
## 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`
|