blue/.blue/docs/rfcs/0015-cert-manager-letsencrypt.draft.md
Eric Garcia 0fea499957 feat: lifecycle suffixes for all document states + resolve all clippy warnings
Every document filename now mirrors its lifecycle state with a status
suffix (e.g., .draft.md, .wip.md, .accepted.md). No more bare .md for
tracked document types. Also renamed all from_str methods to parse to
avoid FromStr trait confusion, introduced StagingDeploymentParams struct,
and fixed all 19 clippy warnings across the codebase.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 12:19:46 -05:00

4.3 KiB

RFC 0015: Let's Encrypt TLS for Forgejo

Status Complete
Date 2026-01-25

Summary

Enable automatic TLS certificate management via Let's Encrypt for git.beyondtheuniverse.superviber.com on the hearth instance.

Problem

Current state:

  • git.beyondtheuniverse.superviber.com uses self-signed certificates
  • API calls require curl -k to skip verification
  • Blue's forge client fails without HTTPS_INSECURE workarounds
  • No automatic certificate renewal

Solution

Architecture (Final)

┌─────────────────────────────────────────────────────────┐
│                Hearth K3s (3.218.167.115)               │
│                                                         │
│  ┌─────────────────────────────────────────────────┐   │
│  │                    Traefik                       │   │
│  │  ┌───────────────────────────────────────────┐  │   │
│  │  │  Built-in ACME Resolver (letsencrypt)     │  │   │
│  │  │  - HTTP-01 Challenge                      │  │   │
│  │  │  - Auto-renewal                           │  │   │
│  │  │  - Storage: /data/acme.json               │  │   │
│  │  └───────────────────────────────────────────┘  │   │
│  └─────────────────────────────────────────────────┘   │
│                          │                              │
│                          ▼                              │
│  ┌─────────────────────────────────────────────────┐   │
│  │              Forgejo (port 3000)                │   │
│  └─────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────┘

Components

  1. Traefik built-in ACME - Handles Let's Encrypt automatically
  2. IngressRoute - Routes traffic to Forgejo with TLS
  3. PowerDNS - Self-managed DNS (also on hearth)

Implementation

Traefik on hearth was already configured with ACME support:

# Traefik args (already configured)
- --certificatesresolvers.letsencrypt.acme.email=admin@superviber.com
- --certificatesresolvers.letsencrypt.acme.storage=/data/acme.json
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web

The Forgejo IngressRoute references this resolver:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: forgejo
  namespace: forgejo
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`git.beyondtheuniverse.superviber.com`)
      kind: Rule
      services:
        - name: forgejo
          port: 3000
  tls:
    certResolver: letsencrypt

Verification

# HTTPS works without -k flag
curl https://git.beyondtheuniverse.superviber.com/api/v1/version
# Returns: {"version":"9.0.3+gitea-1.22.0"}

# Certificate details
echo | openssl s_client -connect 3.218.167.115:443 \
  -servername git.beyondtheuniverse.superviber.com 2>/dev/null | \
  openssl x509 -noout -issuer -dates
# issuer=C=US, O=Let's Encrypt, CN=R12
# notBefore=Jan 25 21:23:57 2026 GMT
# notAfter=Apr 25 21:23:56 2026 GMT

Test Plan

  • Traefik configured with ACME resolver
  • Certificate issued by Let's Encrypt (CN=R12)
  • HTTPS works without -k flag
  • Browser shows secure connection
  • Blue forge client works without SSL workarounds

DNS Configuration

DNS is managed via PowerDNS on hearth (3.218.167.115):

  • git.beyondtheuniverse.superviber.com → 3.218.167.115

"One instance. One certificate. Done."

— Blue