Decision from 12-expert alignment dialogue on single-user scale. Implements Option E with modifications: - t4g.small spot instance (~$5/mo) - k3s with Traefik for ingress + Let's Encrypt TLS - SQLite database for Forgejo - S3 backups with 30-day lifecycle - EBS gp3 20GB encrypted - Admin SSH on port 2222, Git SSH on port 22 Total cost: ~$7.50/month Includes: - terraform/minimal/ - full terraform configuration - terraform/bootstrap/ - state backend (already applied) - docs/spikes/0001-single-user-scale.md - decision documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
174 lines
5.5 KiB
Markdown
174 lines
5.5 KiB
Markdown
# Hearth Minimal Deployment
|
|
|
|
Single EC2 + k3s infrastructure for ~1 user. Cost: ~$7.50/month.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Internet │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
│
|
|
┌─────────┴─────────┐
|
|
│ Elastic IP │
|
|
│ git.beyond... │
|
|
└─────────┬─────────┘
|
|
│
|
|
┌───────────────┼───────────────┐
|
|
│ │ │
|
|
:22 (git) :443 (https) :2222 (admin ssh)
|
|
│ │ │
|
|
┌─────────────┴───────────────┴───────────────┴─────────────┐
|
|
│ EC2 t4g.small (spot) │
|
|
│ │
|
|
│ ┌──────────────────────────────────────────────────────┐ │
|
|
│ │ k3s │ │
|
|
│ │ ┌─────────────┐ ┌─────────────┐ ┌──────────────┐ │ │
|
|
│ │ │ Traefik │ │ Forgejo │ │ SQLite │ │ │
|
|
│ │ │ (ingress) │ │ (git) │ │ (data) │ │ │
|
|
│ │ └─────────────┘ └─────────────┘ └──────────────┘ │ │
|
|
│ └──────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ EBS gp3 20GB │
|
|
└────────────────────────────────────────────────────────────┘
|
|
│
|
|
Daily Backup to S3
|
|
```
|
|
|
|
## Cost Breakdown
|
|
|
|
| Component | Monthly |
|
|
|-----------|---------|
|
|
| EC2 t4g.small spot | ~$5 |
|
|
| EBS gp3 20GB | ~$2 |
|
|
| Elastic IP | $0 (attached) |
|
|
| S3 backups | ~$0.50 |
|
|
| **Total** | **~$7.50** |
|
|
|
|
## Prerequisites
|
|
|
|
1. AWS CLI configured with `hearth` profile
|
|
2. Terraform >= 1.5.0
|
|
3. Domain with DNS access
|
|
|
|
## Deployment
|
|
|
|
```bash
|
|
# 1. Initialize terraform
|
|
cd terraform/minimal
|
|
terraform init
|
|
|
|
# 2. Review configuration
|
|
vim terraform.tfvars # Set your domain and email
|
|
|
|
# 3. Plan
|
|
terraform plan
|
|
|
|
# 4. Apply
|
|
terraform apply
|
|
|
|
# 5. Note the outputs
|
|
terraform output
|
|
|
|
# 6. Configure DNS
|
|
# Add A record: git.yourdomain.com -> <elastic_ip>
|
|
|
|
# 7. Wait for DNS propagation (5-30 minutes)
|
|
|
|
# 8. Visit https://git.yourdomain.com to complete Forgejo setup
|
|
```
|
|
|
|
## Post-Deployment
|
|
|
|
### SSH Access
|
|
|
|
```bash
|
|
# Admin SSH (system access)
|
|
ssh -p 2222 ec2-user@<elastic_ip>
|
|
|
|
# Check k3s status
|
|
sudo kubectl get pods -A
|
|
|
|
# View Forgejo logs
|
|
sudo kubectl logs -n forgejo deploy/forgejo
|
|
```
|
|
|
|
### Git Access
|
|
|
|
```bash
|
|
# Clone a repo (after creating it in web UI)
|
|
git clone git@git.yourdomain.com:org/repo.git
|
|
```
|
|
|
|
### Backups
|
|
|
|
Automatic daily backups to S3 at 3 AM UTC.
|
|
|
|
```bash
|
|
# Manual backup
|
|
sudo /usr/local/bin/backup-forgejo.sh hearth-backups-<account_id>
|
|
|
|
# List backups
|
|
aws s3 ls s3://hearth-backups-<account_id>/backups/
|
|
```
|
|
|
|
### Restore from Backup
|
|
|
|
```bash
|
|
# Download backup
|
|
aws s3 cp s3://hearth-backups-<account_id>/backups/backup-TIMESTAMP.tar.gz /tmp/
|
|
|
|
# Extract
|
|
tar -xzf /tmp/backup-TIMESTAMP.tar.gz -C /tmp/restore
|
|
|
|
# Stop Forgejo
|
|
sudo kubectl scale deploy/forgejo -n forgejo --replicas=0
|
|
|
|
# Restore database
|
|
sudo cp /tmp/restore/gitea.db /data/forgejo/gitea/gitea.db
|
|
sudo chown 1000:1000 /data/forgejo/gitea/gitea.db
|
|
|
|
# Start Forgejo
|
|
sudo kubectl scale deploy/forgejo -n forgejo --replicas=1
|
|
```
|
|
|
|
## Upgrade Path
|
|
|
|
When you outgrow this setup:
|
|
|
|
1. **More resources**: Change instance type in terraform.tfvars
|
|
2. **High availability**: Migrate to EKS using the same manifests
|
|
3. **Multiple users**: Add authentication via Keycloak
|
|
|
|
The Kubernetes manifests are portable to any k8s cluster.
|
|
|
|
## Troubleshooting
|
|
|
|
### Forgejo not starting
|
|
|
|
```bash
|
|
sudo kubectl describe pod -n forgejo
|
|
sudo kubectl logs -n forgejo deploy/forgejo
|
|
```
|
|
|
|
### TLS not working
|
|
|
|
```bash
|
|
# Check Traefik logs
|
|
sudo kubectl logs -n traefik deploy/traefik
|
|
|
|
# Verify DNS is pointing to correct IP
|
|
dig git.yourdomain.com
|
|
```
|
|
|
|
### Spot instance interrupted
|
|
|
|
The instance will automatically restart. Data is preserved on EBS.
|
|
Check instance status in AWS console.
|
|
|
|
## Security Notes
|
|
|
|
1. **Restrict admin access**: Update `admin_cidr_blocks` in terraform.tfvars
|
|
2. **SSH keys**: Add your public key to `~/.ssh/authorized_keys` on the instance
|
|
3. **Forgejo admin**: Create admin account during initial setup
|
|
4. **Updates**: Automatic security updates enabled via dnf-automatic
|