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

5.7 KiB

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:

# 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

# 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?