blumeops/docs/zk/1768246525-RVRY.md
Erich Blume 7112297150 Move zk cards to docs/zk/ for documentation restructuring
Phase 1 of docs restructuring: move all zettelkasten cards to a
temporary docs/zk/ subdirectory while preparing to build a new
Diataxis-based documentation structure.

- Move all existing markdown files from docs/ to docs/zk/
- Update zk-docs mise task to look in the new location
- Add docs/README.md explaining the restructuring plan

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 07:57:47 -08:00

136 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: 1768246525-RVRY
aliases:
- forgejo
- forge
tags:
- blumeops
- forgejo
- git
- scm
- forge
---
# Mon Jan 12 11:35
```fish
brew install forgejo
brew --prefix forgejo
/opt/homebrew/opt/forgejo
brew services start forgejo
==> Successfully started `forgejo` (label: homebrew.mxcl.forgejo)
```
From the service definition I can see that this runs as:
```bash
/opt/homebrew/opt/forgejo/bin/forgejo web --work-path /opt/homebrew/var/forgejo > /opt/homebrew/var/log/forgejo.log 2> /opt/homebrew/var/log/forgejo.log
```
It sounds from the docs like this means the config file should live at:
```
/opt/homebrew/var/forgejo/custom/conf/app.ini
```
Ah, based on the logs, it looks like forgejo has picked port 3000 which is used by grafana:
```
lsof -nP -iTCP:3000 -sTCP:LISTEN
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
grafana 1530 erichblume 15u IPv6 0x4acfad8b21dcb063 0t0 TCP *:3000 (LISTEN)
```
Ok I've set a basic config for port 3001, and then gone through the basic app setup. Looks like it's working! Not sure how SSH works yet though. Let's get this service registered.
Ok so the next issue is that I want to use ssh as my primary git interface, and
I want that to look to users like I'm using port 22 but I want to host it on
indri which has its own separate ssh setup. Hmm. Let's tell forgejo to use port
2200. Ah perfect, we can set SSH_PORT to 22 and SSH_LISTEN_PORT to 2200.
Hmm, let's stop running this as me and run as a new user, 'forgejo'.
```fish
sudo sysadminctl -addUser forgejo -system -shell /usr/bin/false
sudo chown -R forgejo:staff /opt/homebrew/var/forgejo
```
Ok, I think I need to switch all my services on this host over to a services file.
Wow, missing from the above is like 4 hours of deep diving in to the particulars of tailscale service definition hosting. In the end, I never got a services file to work - and yes, I did remember to advertise! Adding to the complexity is that I didn't discover until the end that you can't do "hairpinning", ie you CANNOT use the tailnet service name from the host doing that hosting. I probably had it fixed at some point hours ago and ruled it out because I didn't know about the hairpinning issue. So anyway... what ended up working was to just use the cli:
```fish
tailscale serve --service="svc:forge" --tcp=22 tcp://localhost:2200
tailscale serve --service="svc:forge" --https=443 http://localhost:3001
```
That's it. Nothing else needed, worked right away. Sheesh. (Ok there was also a
solid hour spent on permission issues... I honestly don't know how it's working
now, as there is now a `forgejo` user and the config says to use it but the
files are all owned by `erichblume:staff` but with group permissions set... in
any case, it friggin' works. So I'm happy.
# Configuration (Ansible-Managed)
As of 2026-01-23, the `app.ini` is managed by ansible:
- Template: `ansible/roles/forgejo/templates/app.ini.j2`
- Secrets fetched from 1Password in playbook pre_tasks
- Secrets item: "Forgejo Secrets" in blumeops vault (fields: `lfs-jwt-secret`, `internal-token`, `oauth2-jwt-secret`, `runner_reg`)
Deploy config changes:
```bash
mise run provision-indri -- --tags forgejo
```
# Forgejo Actions (CI/CD)
## Runner (k8s)
The Forgejo runner runs in Kubernetes with Docker-in-Docker (DinD) for container builds.
**Architecture:**
- Runner daemon + DinD sidecar in a single pod
- Jobs execute in containers using the `k8s` label
- DinD exposes Docker API on `tcp://127.0.0.1:2375`
- Pods reach `*.ops.eblu.me` services via Caddy reverse proxy
**Components:**
- ArgoCD app: `argocd/apps/forgejo-runner.yaml`
- Manifests: `argocd/manifests/forgejo-runner/`
- Job image: `registry.ops.eblu.me/blumeops/forgejo-runner` (Node.js + Docker CLI)
- Job image source: `containers/forgejo-runner/`
**Deployment:**
```bash
# Apply secret (contains runner token from 1Password)
op inject -i argocd/manifests/forgejo-runner/secret.yaml.tpl | kubectl --context=minikube-indri apply -f -
# Sync via ArgoCD
argocd app sync forgejo-runner
```
**View logs:**
```bash
kubectl --context=minikube-indri logs -n forgejo-runner -l app=forgejo-runner -c runner
```
## Container Build Workflow
Container images are built via `.forgejo/workflows/build-container.yaml`, triggered by tags matching `<container>-v<version>`.
**Release a container:**
```bash
mise run container-list # See available containers
mise run container-tag-and-release nettest v1.0.0 # Tag and trigger build
```
**Test container** (`containers/nettest/`): Network connectivity test for debugging CI/CD.
## Workflows
Workflows live in `.forgejo/workflows/` (not `.github/workflows/`).
**Important**: Use `github.*` context variables, not `gitea.*`. Forgejo supports both at runtime, but:
1. The Forgejo web UI schema validator only recognizes `github.*`
2. `actionlint` pre-commit hook validates workflows locally (catches errors before push)
3. Pass untrusted inputs (like `github.head_ref`) through env vars for security
## Runner Token
Stored in 1Password "Forgejo Secrets" item, field `runner_reg`.
To create a new token:
1. Go to https://forge.ops.eblu.me/admin/actions/runners
2. Click "Create new Runner"
3. Copy the token and update 1Password