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>
277 lines
5.7 KiB
Markdown
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?
|