422 lines
11 KiB
Markdown
422 lines
11 KiB
Markdown
<div align="center">
|
|
|
|
# custom-gitea-runner
|
|
|
|
A versioned, Docker-first, self-owned Gitea Actions runner platform for Unraid and Linux hosts.
|
|
|
|
[Overview](#overview) • [Goals](#goals) • [Architecture](#architecture) • [Repository-layout](#repository-layout) • [Quick-start](#quick-start) • [Environment](#environment) • [Roadmap](#roadmap) • [Operations](#operations)
|
|
|
|
</div>
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
`custom-gitea-runner` is a controlled replacement for opaque runner setups that are difficult to debug, mutate at startup, or break unexpectedly when upstream images or runtime assumptions change.
|
|
|
|
The project packages a Gitea-compatible runner into a predictable Docker image with pinned dependencies, explicit startup logic, clean documentation, and testable operational workflows. The goal is to make the runner understandable, inspectable, and easy to version over time.
|
|
|
|
This repository is designed for self-hosted environments where the operator wants direct control over:
|
|
|
|
- base image selection,
|
|
- bundled tooling,
|
|
- startup and registration flow,
|
|
- Docker socket/build behavior,
|
|
- release/version policy,
|
|
- troubleshooting and rollback.
|
|
|
|
---
|
|
|
|
## Why this exists
|
|
|
|
This project exists to eliminate common self-hosted runner pain points such as:
|
|
|
|
- missing runtime dependencies like Node.js, Git, or Docker CLI,
|
|
- fragile startup behavior that depends on mutable package installs,
|
|
- difficult-to-diagnose nested container failures,
|
|
- unclear registration/config persistence,
|
|
- and weak operational visibility when jobs fail early.
|
|
|
|
Instead of treating the runner like a disposable black box, this repository treats it like an internal platform component.
|
|
|
|
---
|
|
|
|
## Goals
|
|
|
|
### Primary goals
|
|
|
|
- Build a custom Docker image for a Gitea-compatible runner.
|
|
- Bundle required CI dependencies at image build time.
|
|
- Support checkout, Node-based actions, Docker login, Docker build, and Docker push workflows.
|
|
- Provide deterministic bootstrap and registration behavior.
|
|
- Provide clean deployment guidance for Unraid and standard Linux Docker hosts.
|
|
- Keep all operational knowledge versioned in-repo.
|
|
|
|
### Secondary goals
|
|
|
|
- Support custom CA trust.
|
|
- Support opinionated label templates.
|
|
- Support smoke testing and regression fixtures.
|
|
- Support future hardening tracks like rootless or DinD variants.
|
|
|
|
### Non-goals
|
|
|
|
- Replacing Gitea itself.
|
|
- Building a full control plane or autoscaling runner manager in v1.
|
|
- Solving every orchestration model on day one.
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
### Design principles
|
|
|
|
- Deterministic image builds.
|
|
- No hidden runtime package installs in normal operation.
|
|
- Explicit entrypoint and healthcheck behavior.
|
|
- Pinned versions where practical.
|
|
- Clear separation of image build, registration, runtime config, and operations.
|
|
- Logs that are useful during failure, not just success.
|
|
|
|
### Planned v1 stack
|
|
|
|
- Debian slim or Ubuntu slim base image.
|
|
- Pinned `act_runner` binary or pinned upstream release artifact.
|
|
- Bundled tooling:
|
|
- `bash`
|
|
- `curl`
|
|
- `git`
|
|
- `jq`
|
|
- `node`
|
|
- `npm`
|
|
- `docker`
|
|
- `ca-certificates`
|
|
- `tini`
|
|
- Entrypoint script for validation, registration, and daemon startup.
|
|
- Healthcheck script for runtime verification.
|
|
- Example config and compose files.
|
|
|
|
### Runtime model
|
|
|
|
The runner container is intended to be long-lived and operator-managed.
|
|
|
|
Preferred v1 modes:
|
|
|
|
1. Pre-generated config mounted into the container.
|
|
2. Environment-driven one-time bootstrap registration when config is absent.
|
|
|
|
For Docker build/push workflows, v1 assumes a trusted host and supports a mounted Docker socket. Future variants can harden or isolate this behavior.
|
|
|
|
---
|
|
|
|
## Repository layout
|
|
|
|
```text
|
|
custom-gitea-runner/
|
|
├── AGENT.md
|
|
├── README.md
|
|
├── ROADMAP.md
|
|
├── CHANGELOG.md
|
|
├── LICENSE
|
|
├── .gitignore
|
|
├── .env.example
|
|
├── docker/
|
|
│ ├── runner/
|
|
│ │ ├── Dockerfile
|
|
│ │ ├── docker-entrypoint.sh
|
|
│ │ ├── healthcheck.sh
|
|
│ │ └── smoke-test.sh
|
|
│ └── compose/
|
|
│ ├── docker-compose.example.yml
|
|
│ └── unraid-template-notes.md
|
|
├── config/
|
|
│ ├── runner.example.yaml
|
|
│ ├── labels.example.env
|
|
│ └── trusted-ca/
|
|
├── scripts/
|
|
│ ├── register-runner.sh
|
|
│ ├── deregister-runner.sh
|
|
│ ├── verify-runtime.sh
|
|
│ ├── build-image.sh
|
|
│ ├── publish-image.sh
|
|
│ └── test-local-runner.sh
|
|
├── docs/
|
|
│ ├── architecture.md
|
|
│ ├── operations.md
|
|
│ ├── troubleshooting.md
|
|
│ ├── unraid.md
|
|
│ └── decisions/
|
|
│ └── 0001-base-image.md
|
|
├── test/
|
|
│ ├── fixtures/
|
|
│ ├── sample-workflows/
|
|
│ └── smoke/
|
|
└── src/
|
|
└── optional/
|
|
```
|
|
|
|
---
|
|
|
|
## Quick start
|
|
|
|
### 1. Create the repository
|
|
|
|
Create a new Gitea repository named `custom-gitea-runner` and commit the initial documentation set:
|
|
|
|
- `AGENT.md`
|
|
- `README.md`
|
|
- `ROADMAP.md`
|
|
- `CHANGELOG.md`
|
|
- `.gitignore`
|
|
- `.env.example`
|
|
|
|
### 2. Build the first image
|
|
|
|
Once the Dockerfile exists:
|
|
|
|
```bash
|
|
docker build -t custom-gitea-runner:v0.1.0 -f docker/runner/Dockerfile .
|
|
```
|
|
|
|
### 3. Provide runtime configuration
|
|
|
|
Create a `.env` file from `.env.example` and decide whether to:
|
|
|
|
- mount a pre-generated runner config, or
|
|
- let the container self-register on first boot.
|
|
|
|
### 4. Start the runner
|
|
|
|
Use Docker Compose or the equivalent Unraid template settings to start the container with:
|
|
|
|
- persistent config mount,
|
|
- persistent work directory,
|
|
- Docker socket mount if build/push is required,
|
|
- required env vars.
|
|
|
|
### 5. Run smoke workflows
|
|
|
|
Before production use, validate at minimum:
|
|
|
|
- checkout-only workflow,
|
|
- Node-based action workflow,
|
|
- Docker login workflow,
|
|
- Docker build/push workflow.
|
|
|
|
---
|
|
|
|
## Environment
|
|
|
|
Planned environment variables for bootstrap mode:
|
|
|
|
| Variable | Required | Purpose |
|
|
|---|---:|---|
|
|
| `GITEA_INSTANCE_URL` | Yes | Base URL of the Gitea instance. |
|
|
| `GITEA_RUNNER_TOKEN` | Yes | Registration token for the runner. |
|
|
| `GITEA_RUNNER_NAME` | Yes | Human-readable runner name. |
|
|
| `GITEA_RUNNER_LABELS` | No | Comma-separated label list. |
|
|
| `GITEA_RUNNER_WORKDIR` | No | Working directory inside the container. |
|
|
| `GITEA_RUNNER_CONFIG_PATH` | No | Path to the runner config file. |
|
|
| `TZ` | No | Time zone for logs and runtime behavior. |
|
|
|
|
Future environment variables may include:
|
|
|
|
- custom CA paths,
|
|
- logging mode,
|
|
- healthcheck tuning,
|
|
- Docker socket override,
|
|
- feature flags for experimental runner behavior.
|
|
|
|
---
|
|
|
|
## Example deployment model
|
|
|
|
### Docker Compose direction
|
|
|
|
The project will include a compose example that follows this pattern:
|
|
|
|
- pinned image tag,
|
|
- mounted runner config,
|
|
- mounted work directory,
|
|
- mounted Docker socket,
|
|
- explicit restart policy,
|
|
- explicit environment variables.
|
|
|
|
Example shape:
|
|
|
|
```yaml
|
|
services:
|
|
gitea-runner:
|
|
image: custom-gitea-runner:v0.1.0
|
|
container_name: custom-gitea-runner
|
|
restart: unless-stopped
|
|
environment:
|
|
GITEA_INSTANCE_URL: https://git.example.com
|
|
GITEA_RUNNER_NAME: unraid-runner-01
|
|
GITEA_RUNNER_TOKEN: ${GITEA_RUNNER_TOKEN}
|
|
GITEA_RUNNER_LABELS: ubuntu-latest,docker
|
|
TZ: America/Chicago
|
|
volumes:
|
|
- ./config:/config
|
|
- ./work:/work
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
```
|
|
|
|
### Unraid direction
|
|
|
|
The Unraid notes should document:
|
|
|
|
- repository/image field,
|
|
- appdata path recommendations,
|
|
- variable definitions,
|
|
- volume mounts,
|
|
- Docker socket usage,
|
|
- update workflow,
|
|
- rollback workflow.
|
|
|
|
---
|
|
|
|
## Operations
|
|
|
|
### Expected startup behavior
|
|
|
|
At startup, the container should log:
|
|
|
|
- image version,
|
|
- embedded git revision if available,
|
|
- `act_runner` version,
|
|
- `node` version,
|
|
- `docker` version,
|
|
- config path,
|
|
- work path,
|
|
- registration mode,
|
|
- target Gitea URL,
|
|
- active labels.
|
|
|
|
### Health behavior
|
|
|
|
The healthcheck should confirm:
|
|
|
|
- runner process is alive,
|
|
- config exists,
|
|
- required tools exist,
|
|
- Docker socket is available when configured.
|
|
|
|
### Upgrade workflow
|
|
|
|
Recommended upgrade process:
|
|
|
|
1. Pull or build a new pinned image tag.
|
|
2. Review `CHANGELOG.md`.
|
|
3. Stop the existing container.
|
|
4. Update image tag in compose or Unraid template.
|
|
5. Start the container.
|
|
6. Verify logs and healthcheck.
|
|
7. Run smoke workflow.
|
|
|
|
### Rollback workflow
|
|
|
|
1. Stop the container.
|
|
2. Revert to prior known-good image tag.
|
|
3. Start the container.
|
|
4. Verify registration/config still valid.
|
|
5. Confirm smoke workflow success.
|
|
|
|
---
|
|
|
|
## Documentation set
|
|
|
|
This repository should maintain the following docs as first-class assets:
|
|
|
|
- `AGENT.md` — build rules, architecture constraints, agent instructions.
|
|
- `README.md` — project overview, install/use guidance, operational entry point.
|
|
- `ROADMAP.md` — phased plan with active status tracking.
|
|
- `CHANGELOG.md` — release history.
|
|
- `docs/architecture.md` — deeper design details.
|
|
- `docs/operations.md` — runtime/admin guidance.
|
|
- `docs/troubleshooting.md` — symptom-driven fixes.
|
|
- `docs/unraid.md` — Unraid-specific deployment instructions.
|
|
- `docs/decisions/*.md` — ADR-style architecture decisions.
|
|
|
|
---
|
|
|
|
## Testing strategy
|
|
|
|
Required validation layers:
|
|
|
|
- image build verification,
|
|
- runtime tool verification,
|
|
- registration smoke tests,
|
|
- workflow smoke tests,
|
|
- regression tests for previously encountered failure classes.
|
|
|
|
The first workflows to validate should be:
|
|
|
|
1. `actions/checkout`
|
|
2. Node-based action execution
|
|
3. `docker/login-action`
|
|
4. `docker build`
|
|
5. `docker push`
|
|
|
|
---
|
|
|
|
## Roadmap
|
|
|
|
Project planning lives in [`ROADMAP.md`](./ROADMAP.md).
|
|
|
|
High-level phases:
|
|
|
|
- Phase 0: Research and design
|
|
- Phase 1: Base image and bootstrap
|
|
- Phase 2: Registration/config flows
|
|
- Phase 3: Docker workflow support
|
|
- Phase 4: Test harness and smoke validation
|
|
- Phase 5: Unraid packaging and docs
|
|
- Phase 6: Hardening and enhancements
|
|
|
|
---
|
|
|
|
## Release model
|
|
|
|
Recommended versioning:
|
|
|
|
- `v0.1.0`
|
|
- `v0.1.1`
|
|
- `v0.2.0`
|
|
|
|
`latest` may exist as a convenience tag, but documentation should always recommend pinned versions for real deployments.
|
|
|
|
Every release should map to:
|
|
|
|
- a Git tag,
|
|
- a CHANGELOG entry,
|
|
- image metadata labels,
|
|
- and documented upgrade notes where relevant.
|
|
|
|
---
|
|
|
|
## Contributing workflow
|
|
|
|
Recommended development loop:
|
|
|
|
1. Update docs first when requirements or behavior change.
|
|
2. Make small, reviewable changes.
|
|
3. Keep scripts simple and auditable.
|
|
4. Add regression coverage for painful bugs.
|
|
5. Prefer explicit configuration over implicit behavior.
|
|
|
|
---
|
|
|
|
## Current status
|
|
|
|
This repository is in planning/bootstrap stage.
|
|
|
|
The immediate next steps are:
|
|
|
|
- finalize the architecture direction,
|
|
- scaffold the repository,
|
|
- build the first pinned image,
|
|
- implement registration/bootstrap scripts,
|
|
- validate smoke workflows,
|
|
- document Unraid deployment.
|