✨feature: Add Gitea docs
This commit is contained in:
254
content/soloforge-docs.md
Normal file
254
content/soloforge-docs.md
Normal file
@@ -0,0 +1,254 @@
|
||||
---
|
||||
title: SoloForge Documentation
|
||||
section: docs
|
||||
summary: SoloForge Infrastructure Documentation for Self-Hosted Gitea with Actions Runner on Hetzner
|
||||
tags: [servers, infrasctructure, gitea, ci/cd, hetzner, docker]
|
||||
nav: 1
|
||||
---
|
||||
|
||||
## Self-Hosted Gitea + Actions Runner (Hetzner Deployment)
|
||||
|
||||
This document describes the current SoloForge setup — Gitea, Traefik routing, the Gitea Actions runner, backup routines, directory layout, and operational notes.
|
||||
|
||||
This repo exists so future-me (and actual-me) don’t need to reverse-engineer anything when something eventually explodes.
|
||||
|
||||
## 1. Overview
|
||||
|
||||
SoloForge is a self-hosted Gitea instance running on a Hetzner VM.
|
||||
|
||||
It provides:
|
||||
|
||||
- Private (but login-protected) Git hosting
|
||||
- Public-visible repositories (instance auth is required anyway)
|
||||
- Gitea Actions, backed by a Docker-based self-hosted runner
|
||||
- Automatic CI for TODO-to-issue sync and other workflows
|
||||
- Reverse-proxy via Traefik
|
||||
- Automated Gitea backups
|
||||
|
||||
The system replaces the original Proxmox-hosted Gitea instance lost due to disk failure.
|
||||
|
||||
---
|
||||
|
||||
## 2. System Layout
|
||||
|
||||
### Hetzner VM
|
||||
|
||||
- Debian 13
|
||||
- Docker + Docker Compose installed
|
||||
- Traefik reverse proxy (existing before SoloForge migration)
|
||||
- HTTPS termination handled by Traefik via Let’s Encrypt
|
||||
|
||||
### Directory structure
|
||||
|
||||
```bash
|
||||
/gitea/
|
||||
├── gitea/ # Gitea app + persistent data
|
||||
├── postgres/ # PostgreSQL data directory (if using Postgres)
|
||||
└── docker-compose.yml # Main Gitea stack
|
||||
```
|
||||
|
||||
### Runner lives separately
|
||||
|
||||
```bash
|
||||
/gitea/gitea-runner/
|
||||
├── docker-compose.yml # Actions runner stack
|
||||
└── data/ # Contains .runner registration + job cache
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Gitea Deployment
|
||||
|
||||
### 3.1 Gitea Compose Service
|
||||
|
||||
Gitea is launched via Docker Compose and reverse-proxied through Traefik.
|
||||
Data lives under `/gitea/gitea` to ensure persistence.
|
||||
|
||||
### 3.2 Traefik Routing
|
||||
|
||||
Traefik handles:
|
||||
|
||||
- HTTPS certificate generation
|
||||
- Routing git.keithsolomon.net → Gitea web UI
|
||||
- Exposing SSH port (222) for git-over-SSH
|
||||
|
||||
No YAML generator required anymore — everything is stable and hand-maintained.
|
||||
|
||||
---
|
||||
|
||||
## 4. Gitea Actions Runner
|
||||
|
||||
SoloForge uses a self-hosted Gitea Actions runner, running via Docker and capable of executing JavaScript (Node-based) GitHub-style actions.
|
||||
|
||||
### 4.1 Runner compose file
|
||||
|
||||
Located at:
|
||||
|
||||
`/gitea/gitea-runner/docker-compose.yml`
|
||||
|
||||
Core configuration:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
GITEA_INSTANCE_URL: "https://git.keithsolomon.net"
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: "<token>"
|
||||
GITEA_RUNNER_NAME: "hetzner-runner-1"
|
||||
GITEA_RUNNER_LABELS: "ubuntu-latest:docker://node:20-bullseye,self-hosted,linux,x86_64,docker"
|
||||
```
|
||||
|
||||
By default, GitHub runners provide Node.js preinstalled.
|
||||
Self-hosted runners do NOT.
|
||||
|
||||
Mapping:
|
||||
|
||||
`ubuntu-latest:docker://node:20-bullseye`
|
||||
|
||||
ensures any workflow using:
|
||||
|
||||
```yaml
|
||||
runs-on: ubuntu-latest
|
||||
```
|
||||
|
||||
runs inside a Node-enabled container, fixing "node: command not found" errors.
|
||||
|
||||
### 4.3 Re-registering the runner (important!)
|
||||
|
||||
If labels change or the runner breaks:
|
||||
|
||||
```bash
|
||||
cd /gitea/gitea-runner
|
||||
docker compose down
|
||||
rm -f data/.runner # Forces new registration
|
||||
docker compose up -d # Registers with current labels
|
||||
```
|
||||
|
||||
Check runner status in Gitea:
|
||||
|
||||
**Site Admin → Actions → Runners**
|
||||
|
||||
---
|
||||
|
||||
## 5. Workflows
|
||||
|
||||
### 5.1 TODO-to-Issue Sync
|
||||
|
||||
Certain repos use a custom JavaScript action to:
|
||||
|
||||
- Parse TODO comments
|
||||
- Generate/close GitHub-style issues inside Gitea
|
||||
|
||||
These workflows run cleanly now because:
|
||||
|
||||
- The runner supports Node (ubuntu-latest → node:20 container)
|
||||
- Repository permissions allow issue writing
|
||||
|
||||
### 5.2 Secret tokens
|
||||
|
||||
Unlike GitHub, Gitea does not auto-inject GITHUB_TOKEN.
|
||||
Workflows requiring an auth token need one defined manually in:
|
||||
|
||||
**Repo → Settings → Secrets**
|
||||
|
||||
Example:
|
||||
|
||||
`GITHUB_TOKEN = <personal access token>`
|
||||
|
||||
(Or rename to something more Gitea-themed.)
|
||||
|
||||
---
|
||||
|
||||
## 6. Repository Management
|
||||
|
||||
### 6.1 Bulk import
|
||||
|
||||
All repos were migrated using a [custom bulk-mirror script](/assets/files/gitea/git-bulk) that:
|
||||
|
||||
- Created missing repos via the Gitea API
|
||||
- Pushed full history via git push --all and --tags
|
||||
|
||||
### 6.2 Public visibility
|
||||
|
||||
All repos are public (since Gitea login protects everything).
|
||||
A [bulk-update script](/assets/files/gitea/git-flip) is available to flip visibility via API if needed.
|
||||
|
||||
---
|
||||
|
||||
## 7. Backups
|
||||
|
||||
Gitea supports built-in dumps via:
|
||||
|
||||
`gitea dump`
|
||||
|
||||
A cronjob is installed to dump nightly at 3am:
|
||||
|
||||
```bash
|
||||
/gitea-backups/
|
||||
└── gitea-dump-YYYYMMDD.zip
|
||||
```
|
||||
|
||||
Recommended: sync this folder offsite or back to home lab.
|
||||
|
||||
---
|
||||
|
||||
## 8. Restore Notes
|
||||
|
||||
If Gitea must be restored from dump:
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
rm -rf gitea/* postgres/*
|
||||
unzip gitea-dump.zip into /gitea/gitea
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
If the runner needs re-registration, follow section 4.3.
|
||||
|
||||
---
|
||||
|
||||
## 9. Future Improvements (Optional)
|
||||
|
||||
- Mirror “source of truth” repos between GitHub ↔ Gitea
|
||||
- Add automated org-level secrets
|
||||
- Configure multiple runners (home lab, Hetzner, etc.)
|
||||
- Add Prometheus metrics + Grafana board for CI activity
|
||||
- Set up Gitea’s dependency listing or vulnerability scanning
|
||||
|
||||
---
|
||||
|
||||
## 10. `forge` CLI Tool
|
||||
|
||||
A custom CLI tool [`forge`](/assets/files/gitea/forge) exists to help manage common tasks:
|
||||
|
||||
| Command | Description |
|
||||
| --------------------------- | ---------------------------------------------------------- |
|
||||
| `forge status` | Show status of Gitea and runner containers |
|
||||
| `forge ps` | Alias for status |
|
||||
| `forge gitea-logs` | Tail logs from Gitea container |
|
||||
| `forge runner-logs` | Tail logs from Actions runner container |
|
||||
| `forge backup` | Run a Gitea dump and move it into BACKUP_DIR |
|
||||
| `forge restart-gitea` | Restart Gitea stack |
|
||||
| `forge restart-runner` | Restart Actions runner stack |
|
||||
| `forge runner-reset` | Re-register runner with current labels (destroys .runner) |
|
||||
| `forge diag` | Quick diagnostic summary |
|
||||
|
||||
## TL;DR Cheat Sheet
|
||||
|
||||
### Runner broke?
|
||||
|
||||
`→ delete data/.runner, docker compose up -d`
|
||||
|
||||
### `node` not found?
|
||||
|
||||
`→ ensure ubuntu-latest label is mapped to node:20-bullseye`
|
||||
|
||||
### Release workflows failing?
|
||||
|
||||
`→ they're GitHub-only; they run on GitHub mirrors`
|
||||
|
||||
### Backup?
|
||||
|
||||
`→ see /gitea-backups, nightly gitea dump`
|
||||
|
||||
### Repo not found?
|
||||
|
||||
`→ bulk import script: auto-create + push mirror`
|
||||
Reference in New Issue
Block a user