> **TODO:** This tutorial is light on specifics and should be expanded. In its current form it serves as a general sketch of how BlumeOps got started — every component mentioned here (Forgejo, Zot, CI runners, etc.) receives much deeper treatment elsewhere in the blumeops codebase and documentation.
This tutorial walks through setting up the foundational services that your GitOps infrastructure depends on: a git forge and optionally a container registry.
## Why Core Services First?
Before Kubernetes and ArgoCD, you need somewhere to store your infrastructure definitions. [[forgejo]] provides:
- Git hosting for your GitOps repository
- CI/CD workflows for building and deploying
- A web interface for code review and PRs
The [[zot]] container registry is optional but useful for hosting your own container images.
## Step 1: Install Forgejo
Forgejo runs directly on your server (not in Kubernetes) because Kubernetes depends on it.
Forgejo runs its own SSH server on a non-standard port (e.g., 2222) to avoid conflicting with the host's SSH daemon on port 22. Later, [[caddy]] with the L4 plugin can map port 22 to 2222 using a DNS name (e.g., `forge.ops.eblu.me`), so git clients don't need to specify a port.
Forgejo Actions runs workflows defined in `.forgejo/workflows/`. The simplest setup is a native runner that executes jobs directly on the host (no Docker required):
1. Download the `forgejo-runner` binary from [code.forgejo.org](https://code.forgejo.org/forgejo/runner/releases):
> **Note:** Host mode has no isolation — jobs run as whatever user runs `forgejo-runner`. This is fine for a personal setup with trusted repos. Use a `launchd` plist or `brew services` wrapper to keep it running.