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>
136 lines
5.2 KiB
Markdown
136 lines
5.2 KiB
Markdown
---
|
||
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
|