blumeops/docs/reference/services/forgejo.md
Erich Blume 695089499e Nix container build for nettest (#214)
## Summary
- Add `containers/nettest/default.nix` using `dockerTools.buildLayeredImage` with curl, jq, dnsutils, cacert, and bash — equivalent to the existing Dockerfile
- Update `container-tag-and-release` to require `--nix` or `--dockerfile` flag when both build types exist for a container
- Update `container-list` to show `[dockerfile+nix]` label when both exist

## Deployment and Testing
- [ ] SSH to ringtail, run `nix build -f containers/nettest/default.nix -o result` to verify the nix expression builds
- [ ] Tag `nettest-nix-v1.0.0`, confirm `build-container-nix` workflow runs on `nix-container-builder` runner and pushes to registry
- [ ] Smoke test on ringtail k3s: `kubectl run nettest --image=registry.ops.eblu.me/blumeops/nettest:v1.0.0 --restart=Never && kubectl logs nettest`
- [ ] Verify `mise run container-list` shows `[dockerfile+nix]` for nettest
- [ ] Verify `mise run container-tag-and-release nettest v1.1.0` prompts for build type

Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/214
2026-02-19 08:42:58 -08:00

3.7 KiB

title modified tags
Forgejo 2026-02-19
service
git
ci-cd

Forgejo

Git forge and CI/CD platform. Primary source of truth for blumeops (mirrored to GitHub).

Quick Reference

Property Value
URL https://forge.ops.eblu.me
SSH ssh://forgejo@forge.ops.eblu.me:2222
Local Ports 3001 (HTTP), 2200 (SSH)
Config ansible/roles/forgejo/templates/app.ini.j2

Repositories

Repo Description
eblume/blumeops Infrastructure as code (primary)
eblume/alloy Grafana Alloy fork (CGO build)
eblume/tesla_auth Tesla OAuth helper
Helm chart mirrors cloudnative-pg-charts, grafana-helm-charts

CI/CD (Forgejo Actions)

Runners:

Runner Host Labels Purpose
k8s DinD pod indri (minikube) k8s Dockerfile builds via Dagger
ringtail-nix-builder ringtail (native) nix-container-builder Nix builds via nix-build + skopeo

Workflows: .forgejo/workflows/

  • build-container.yaml - Dockerfile builds on tag (runs on k8s)
  • build-container-nix.yaml - Nix builds on tag (runs on nix-container-builder)
  • build-blumeops.yaml - Documentation builds and releases

Both container workflows trigger on the same tag pattern (*-v[0-9]*). Each checks for its build file (Dockerfile or default.nix) and skips if not present. See build-container-image.

Secrets (Forgejo Config)

Server configuration secrets managed via 1Password → Ansible:

  • lfs-jwt-secret, internal-token, oauth2-jwt-secret - Forgejo server tokens
  • runner_reg - Runner registration token (also in k8s via external-secrets)

Forgejo Actions Secrets

Repository-level secrets for CI/CD workflows, synced from 1Password via Ansible.

Secret 1Password Field Used By Purpose
ARGOCD_AUTH_TOKEN argocd_token build-blumeops.yaml Sync docs app after release

These secrets are injected as ${{ secrets.SECRET_NAME }} in workflow files.

IaC: The forgejo_actions_secrets Ansible role syncs these secrets from 1Password to Forgejo via the Forgejo API. Run with:

mise run provision-indri -- --tags forgejo_actions_secrets

API Token Setup (Manual, One-Time)

The Ansible role authenticates to the Forgejo API using a Personal Access Token (PAT). This PAT must be created manually:

  1. Go to https://forge.ops.eblu.me/user/settings/applications
  2. Create a new token with write:repository scope
  3. Store it in 1Password → "Forgejo Secrets" item → api-token field

This is a bootstrapping requirement - the PAT enables IaC for all other secrets.

Future: Public Access

Forgejo can be exposed publicly at forge.eblu.me via flyio-proxy. Since Forgejo runs natively on indri (not in k8s), the pattern is:

  1. Create a k8s ExternalName Service pointing to indri's Tailscale IP
  2. Create a Tailscale Ingress with tailscale.com/tags: "tag:k8s,tag:flyio-target"
  3. Add the nginx server block and DNS CNAME

Exposing a dynamic, authenticated service like Forgejo requires a full security review before going live:

  • Disable open user registration (require invites or admin approval)
  • Configure fail2ban on indri with a filter for Forgejo's log format
  • Ensure Forgejo logs the forwarded client IP (X-Real-IP) rather than the proxy's Tailscale IP
  • Audit repository visibility defaults and permissions
  • Rehearse the break-glass shutoff (mise run fly-shutoff)

See expose-service-publicly for the full howto and dynamic service checklist.

  • argocd - Uses Forgejo as git source
  • zot - Container registry for built images