mirror of
https://github.com/we-promise/sure.git
synced 2026-04-19 03:54:08 +00:00
Add comprehensive Hetzner Cloud deployment guide (#211)
* 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
This commit is contained in:
committed by
GitHub
parent
eaa17fe9be
commit
3aea1513d1
434
docs/hosting/hetzner.md
Normal file
434
docs/hosting/hetzner.md
Normal file
@@ -0,0 +1,434 @@
|
||||
# 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`
|
||||
Reference in New Issue
Block a user