hearth/docs/spikes/0001-single-user-scale.md
Eric Garcia b1065ca887 feat(minimal): Add k3s-on-EC2 infrastructure for single user
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>
2026-01-24 06:21:55 -05:00

277 lines
5.7 KiB
Markdown

# Spike: Single-User Infrastructure Scale
**Date:** 2026-01-24
**Status:** Decided
## Decision
**Chosen: Option E (k3s on EC2)** with modifications from 12-expert alignment dialogue.
Key decisions:
- t4g.small spot instance (~$5/mo)
- k3s with Traefik for ingress + Let's Encrypt TLS
- SQLite database (simpler than PostgreSQL for single user)
- S3 for backups with lifecycle policies
- EBS gp3 20GB with encryption
- Admin SSH on port 2222, Git SSH on port 22
Implementation: `terraform/minimal/`
Cost: ~$7.50/month
## Problem
Current design targets production scale (~$100-150/mo). For ~1 user, we need something much smaller.
## Current Design Cost Breakdown
| Component | Monthly | Purpose |
|-----------|---------|---------|
| EKS Control Plane | $73 | Kubernetes API |
| NAT Gateways (3x) | $96 | Private subnet internet |
| NLB | $16 | Load balancing |
| EFS | $5+ | Shared storage |
| S3 | $5 | Backups, blobs |
| Spot nodes | $10-50 | Compute |
| **Total** | **$205-245** | |
That's absurd for 1 user running Forgejo.
## Options
### Option A: Single EC2 + Docker (~$5-15/mo)
**Architecture:**
```
Internet → EC2 (t4g.small) → Docker → Forgejo
→ SQLite (local)
→ Local disk
```
**Cost:**
- t4g.small spot: ~$3-5/mo
- EBS gp3 20GB: ~$2/mo
- Elastic IP: $0 (if attached)
- **Total: ~$5-7/mo**
**Pros:**
- Dead simple
- Can SSH directly
- Easy to understand and debug
- Can grow later
**Cons:**
- Single point of failure
- Manual updates
- No k8s experience
**Implementation:**
```bash
# User data script
docker run -d \
--name forgejo \
-p 80:3000 -p 22:22 \
-v /data/forgejo:/data \
--restart always \
codeberg.org/forgejo/forgejo:9
```
### Option B: Lightsail Container (~$7/mo)
**Architecture:**
```
Internet → Lightsail Container Service → Forgejo
→ Lightsail Storage
```
**Cost:**
- Nano container: $7/mo (includes 512MB RAM, 0.25 vCPU)
- Storage: included
- HTTPS: included
- **Total: ~$7/mo**
**Pros:**
- Managed TLS
- Simple deployment
- AWS-native
- Easy scaling path
**Cons:**
- Limited resources on nano
- Lightsail-specific
- Less control
### Option C: Fargate Spot (~$10-20/mo)
**Architecture:**
```
Internet → ALB → Fargate Spot → Forgejo
→ EFS (minimal)
```
**Cost:**
- Fargate Spot (0.25 vCPU, 0.5GB): ~$3-5/mo
- ALB: ~$16/mo (overkill, but required)
- EFS: ~$1/mo (minimal usage)
- **Total: ~$20/mo**
**Pros:**
- Serverless containers
- Auto-restart on failure
- Path to EKS later
**Cons:**
- ALB cost dominates
- More complex than EC2
### Option D: EKS Minimal (~$85/mo)
**Architecture:**
```
Internet → NLB → EKS (Fargate only) → Forgejo
→ EFS
```
**Cost:**
- EKS Control Plane: $73
- Fargate pod: ~$5
- NLB: ~$0 (use NodePort + instance IP)
- EFS: ~$5
- **Total: ~$83/mo**
**Pros:**
- Real Kubernetes
- Can scale up cleanly
- Production-like
**Cons:**
- Still expensive for 1 user
- $73 floor just for control plane
### Option E: k3s on EC2 (~$8-15/mo)
**Architecture:**
```
Internet → EC2 (t4g.small) → k3s → Forgejo
→ SQLite
→ Local storage
```
**Cost:**
- t4g.small spot: ~$5/mo
- EBS: ~$2/mo
- **Total: ~$7/mo**
**Pros:**
- Real Kubernetes (k3s)
- Can use same manifests as EKS
- Cheap
- Learning path to EKS
**Cons:**
- Self-managed k8s
- Single node
- Updates are manual
## Comparison Matrix
| Option | Cost/mo | Complexity | Scaling Path | K8s Compatible |
|--------|---------|------------|--------------|----------------|
| A: EC2+Docker | $5-7 | Low | Manual | No |
| B: Lightsail | $7 | Low | Limited | No |
| C: Fargate | $20 | Medium | Good | Partial |
| D: EKS Minimal | $83 | High | Excellent | Yes |
| E: k3s on EC2 | $7-10 | Medium | Good | Yes |
## Recommendation
**For 1 user who wants Forgejo NOW:** Option A (EC2 + Docker)
- Get running in 10 minutes
- $5-7/month
- Upgrade to k3s or EKS later
**For 1 user who wants k8s experience:** Option E (k3s on EC2)
- Same manifests work on EKS later
- $7-10/month
- Real Kubernetes learning
**For future growth path:**
```
EC2+Docker → k3s → EKS (when needed)
$5 $7 $100+
```
## Implementation: Option A (Fastest)
### Terraform for Single EC2
```hcl
# Minimal VPC
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
map_public_ip_on_launch = true
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
}
# Single EC2 instance
resource "aws_instance" "forgejo" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = "t4g.small"
subnet_id = aws_subnet.public.id
user_data = <<-EOF
#!/bin/bash
dnf install -y docker
systemctl enable --now docker
docker run -d --name forgejo \
-p 80:3000 -p 22:22 \
-v /data/forgejo:/data \
--restart always \
codeberg.org/forgejo/forgejo:9
EOF
root_block_device {
volume_size = 20
volume_type = "gp3"
}
}
# Elastic IP for stable DNS
resource "aws_eip" "forgejo" {
instance = aws_instance.forgejo.id
}
```
### DNS Setup
Point `git.beyondtheuniverse.superviber.com` to the Elastic IP.
### TLS Options
1. **Caddy reverse proxy** (auto Let's Encrypt)
2. **Traefik** (auto Let's Encrypt)
3. **certbot** on the instance
## Next Steps
1. Choose option
2. Implement minimal terraform
3. Deploy Forgejo
4. Create hearth repo in Forgejo
5. Push hearth to Forgejo
6. Iterate
## Questions
1. Do you need Kubernetes experience/compatibility?
2. Is $5-7/mo acceptable?
3. Do you want TLS managed or manual?