feat(forgejo): remove gitea-mirror, all repos now first-class

GitHub mirroring is no longer needed now that Forgejo is the primary
remote. Drops the gitea-mirror service, its volume, env vars, Caddy
site, and firewall rule; docs updated to match.
This commit is contained in:
Brian Pooe 2026-07-19 13:21:05 +02:00
parent 1549283f19
commit 73ff919b9f
7 changed files with 9 additions and 161 deletions

View file

@ -32,7 +32,7 @@ help:
@echo " deploy-paperless - Deploy Paperless-ngx" @echo " deploy-paperless - Deploy Paperless-ngx"
@echo " deploy-vaultwarden - Deploy Vaultwarden" @echo " deploy-vaultwarden - Deploy Vaultwarden"
@echo " deploy-koffan - Deploy Koffan (grocery list)" @echo " deploy-koffan - Deploy Koffan (grocery list)"
@echo " deploy-forgejo - Deploy Forgejo (self-hosted Git + GitHub mirroring)" @echo " deploy-forgejo - Deploy Forgejo (self-hosted Git)"
@echo "" @echo ""
@echo "Utility Targets:" @echo "Utility Targets:"
@echo " status - Show status of all deployed stacks" @echo " status - Show status of all deployed stacks"

View file

@ -28,7 +28,7 @@ Each stack guide in `docker-compose-files/<stack>/README.md` explains appdata pl
| [Beszel Hub](docker-compose-files/beszel-hub/README.md) | Beszel monitoring dashboard | | [Beszel Hub](docker-compose-files/beszel-hub/README.md) | Beszel monitoring dashboard |
| [Beszel Socket Proxy](docker-compose-files/socket-proxy/README.md) | Restricted Docker API access for Beszel | | [Beszel Socket Proxy](docker-compose-files/socket-proxy/README.md) | Restricted Docker API access for Beszel |
| [Caddy](docker-compose-files/caddy/README.md) | Reverse proxy with Cloudflare DNS-01 | | [Caddy](docker-compose-files/caddy/README.md) | Reverse proxy with Cloudflare DNS-01 |
| [Forgejo](docker-compose-files/forgejo/README.md) | Self-hosted Git service with automatic GitHub mirroring | | [Forgejo](docker-compose-files/forgejo/README.md) | Self-hosted Git service |
| [Gramps Web](docker-compose-files/gramps-web/README.md) | Genealogy web application | | [Gramps Web](docker-compose-files/gramps-web/README.md) | Genealogy web application |
| [Home Assistant](docker-compose-files/homeassistant/README.md) | Home Assistant, Mosquitto, and Zigbee2MQTT | | [Home Assistant](docker-compose-files/homeassistant/README.md) | Home Assistant, Mosquitto, and Zigbee2MQTT |
| [Immich](docker-compose-files/immich/README.md) | Photo and video management with GPU acceleration | | [Immich](docker-compose-files/immich/README.md) | Photo and video management with GPU acceleration |

View file

@ -180,11 +180,6 @@ git.{{CADDY_BASE_DOMAIN:-home.example.com}} {
reverse_proxy {{CADDY_OFFICE_PREFIX:-10.0.10}}.18:3000 reverse_proxy {{CADDY_OFFICE_PREFIX:-10.0.10}}.18:3000
} }
git-mirror.{{CADDY_BASE_DOMAIN:-home.example.com}} {
import common
reverse_proxy {{CADDY_OFFICE_PREFIX:-10.0.10}}.18:4321
}
# Hermes Agent web dashboard (LXC 113, not docker — systemd service) # Hermes Agent web dashboard (LXC 113, not docker — systemd service)
hermes.{{CADDY_BASE_DOMAIN:-home.example.com}} { hermes.{{CADDY_BASE_DOMAIN:-home.example.com}} {
import common import common

View file

@ -20,34 +20,3 @@ FORGEJO_DATA_ROOT=/mnt/unas/forgejo_data
# `docker exec forgejo forgejo admin user create ...` instead. # `docker exec forgejo forgejo admin user create ...` instead.
FORGEJO_DISABLE_REGISTRATION=true FORGEJO_DISABLE_REGISTRATION=true
FORGEJO_REQUIRE_SIGNIN_VIEW=false FORGEJO_REQUIRE_SIGNIN_VIEW=false
# --- gitea-mirror: auto-syncs GitHub repos into Forgejo ---
GITEA_MIRROR_VERSION=latest
GITEA_MIRROR_PORT=4321
GITEA_MIRROR_BIND_IP=0.0.0.0
GITEA_MIRROR_MEM_LIMIT=256m
# Full URL where gitea-mirror's own UI is reachable
GITEA_MIRROR_PUBLIC_URL=https://git-mirror.home.example.com
# Generate with: openssl rand -base64 32
GITEA_MIRROR_AUTH_SECRET=<random-secret>
# GitHub source — a classic PAT with repo (+ read:org if mirroring orgs) scope
GITHUB_USERNAME=<your-github-username>
GITHUB_TOKEN=<github-personal-access-token>
GITEA_MIRROR_SKIP_FORKS=false
GITEA_MIRROR_PRIVATE_REPOS=true
GITEA_MIRROR_STARRED=false
GITEA_MIRROR_ORGANIZATIONS=false
GITEA_MIRROR_ISSUES=false
GITEA_MIRROR_WIKI=false
# Forgejo destination — GITEA_MIRROR_FORGEJO_TOKEN can only be created after
# Forgejo is up and you've logged in once (Settings -> Applications ->
# Generate New Token, scopes: repo, admin:org). See README "GitHub mirroring".
GITEA_MIRROR_FORGEJO_USERNAME=<your-forgejo-username>
GITEA_MIRROR_FORGEJO_TOKEN=<forgejo-api-token>
GITEA_MIRROR_ORG=github-mirrors
GITEA_MIRROR_ORG_VISIBILITY=private
GITEA_MIRROR_INTERVAL=8h

View file

@ -1,8 +1,6 @@
# Forgejo # Forgejo
Self-hosted Git service (soft fork of Gitea) with Postgres, plus Self-hosted Git service (soft fork of Gitea) with Postgres.
[gitea-mirror](https://github.com/RayLabsHQ/gitea-mirror) to automatically
pull all your GitHub repositories in as mirrors.
## Persistent Data ## Persistent Data
@ -29,9 +27,6 @@ The share binds use `create_host_path: false`, so the stack refuses to start
if the share is not mounted, rather than silently writing into an empty if the share is not mounted, rather than silently writing into an empty
directory that later needs merging back in. directory that later needs merging back in.
`gitea_mirror_data` (local named volume) holds gitea-mirror's own small
SQLite state DB — negligible size, not worth splitting out.
## Installation ## Installation
1. Create `.env` if it does not exist: 1. Create `.env` if it does not exist:
@ -42,8 +37,7 @@ SQLite state DB — negligible size, not worth splitting out.
2. Set the required values in `docker-compose-files/forgejo/.env` — at 2. Set the required values in `docker-compose-files/forgejo/.env` — at
minimum `FORGEJO_ROOT_URL`, `FORGEJO_DOMAIN`, `FORGEJO_DB_PASSWORD`, and minimum `FORGEJO_ROOT_URL`, `FORGEJO_DOMAIN`, `FORGEJO_DB_PASSWORD`, and
`FORGEJO_DATA_ROOT`. Leave the `GITEA_MIRROR_*` GitHub/Forgejo-token vars `FORGEJO_DATA_ROOT`.
for step 6 — Forgejo needs to exist before those tokens can be generated.
3. Add the UNAS share and bind-mount it into the LXC, following 3. Add the UNAS share and bind-mount it into the LXC, following
[nfs-mounts.md](../../docs/unas/nfs-mounts.md) (add `forgejo_data` to the [nfs-mounts.md](../../docs/unas/nfs-mounts.md) (add `forgejo_data` to the
@ -67,49 +61,15 @@ SQLite state DB — negligible size, not worth splitting out.
```bash ```bash
./substitute_env.sh docker-compose-files/forgejo/template.yaml docker-compose.forgejo.yml .env docker-compose-files/forgejo/.env ./substitute_env.sh docker-compose-files/forgejo/template.yaml docker-compose.forgejo.yml .env docker-compose-files/forgejo/.env
docker compose -f docker-compose.forgejo.yml config --quiet docker compose -f docker-compose.forgejo.yml config --quiet
docker compose -f docker-compose.forgejo.yml up -d forgejo-db forgejo docker compose -f docker-compose.forgejo.yml up -d
``` ```
`gitea-mirror` is intentionally left out of the first `up` — see step 6.
5. Open `http://<host-ip>:3000`, create the first (admin) account, and 5. Open `http://<host-ip>:3000`, create the first (admin) account, and
confirm repo creation/push/clone works before wiring up mirroring. confirm repo creation/push/clone works.
## GitHub Mirroring
`gitea-mirror` is a separate small app, not a Forgejo built-in — Forgejo
itself has no config option to bulk-pull an entire GitHub account. Once you
have a Forgejo login:
1. In Forgejo: **Settings → Applications → Generate New Token**, scopes
`repo` + `admin:org` (needed to auto-create the `github-mirrors`
destination org). Put the token in `GITEA_MIRROR_FORGEJO_TOKEN`.
2. Create a GitHub classic PAT with `repo` scope (add `read:org` if you set
`GITEA_MIRROR_ORGANIZATIONS=true`). Put it in `GITHUB_TOKEN`.
3. Start the mirror service:
```bash
docker compose -f docker-compose.forgejo.yml up -d gitea-mirror
```
With `AUTO_IMPORT_REPOS=true`, `AUTO_MIRROR_REPOS=true`, and
`SCHEDULE_ENABLED=true` (all defaulted on in the template), it imports every
repo from `GITHUB_USERNAME` on first startup and re-syncs every
`GITEA_MIRROR_INTERVAL` (default `8h`) after that — no manual per-repo setup.
Fine-tune what gets pulled via `GITEA_MIRROR_PRIVATE_REPOS`,
`GITEA_MIRROR_STARRED`, `GITEA_MIRROR_ORGANIZATIONS`, `GITEA_MIRROR_SKIP_FORKS`.
`CLEANUP_DELETE_IF_NOT_IN_GITHUB` stays `false` by default — a repo you
delete on GitHub won't get deleted in Forgejo automatically. Flip that on
deliberately if you want mirrors pruned to match GitHub exactly.
Its own UI is at `http://<host-ip>:4321` for monitoring sync status and
tweaking mirror settings beyond what's templated here.
## Reverse Proxy ## Reverse Proxy
Add blocks for `git.<domain>` (port `FORGEJO_HTTP_PORT`) and optionally Add a block for `git.<domain>` (port `FORGEJO_HTTP_PORT`) to
`git-mirror.<domain>` (port `GITEA_MIRROR_PORT`) to
`docker-compose-files/caddy/Caddyfile_template`, then `make reload-caddy`. `docker-compose-files/caddy/Caddyfile_template`, then `make reload-caddy`.
Git-over-SSH (`FORGEJO_SSH_PORT`) is not proxyable through Caddy — expose that Git-over-SSH (`FORGEJO_SSH_PORT`) is not proxyable through Caddy — expose that
port directly if you want SSH clone/push from outside the LAN. port directly if you want SSH clone/push from outside the LAN.
@ -128,7 +88,6 @@ port directly if you want SSH clone/push from outside the LAN.
```bash ```bash
# Tail logs # Tail logs
docker compose -f docker-compose.forgejo.yml logs -f forgejo docker compose -f docker-compose.forgejo.yml logs -f forgejo
docker compose -f docker-compose.forgejo.yml logs -f gitea-mirror
# Create an additional user without open registration # Create an additional user without open registration
docker exec -it forgejo forgejo admin user create --username <name> --email <email> --random-password docker exec -it forgejo forgejo admin user create --username <name> --email <email> --random-password

View file

@ -1,5 +1,4 @@
# Forgejo self-hosted Git service, backed by Postgres, with automatic # Forgejo self-hosted Git service, backed by Postgres.
# mirroring of GitHub repositories via gitea-mirror.
# #
# Storage split (see docs/unas/nfs-mounts.md): # Storage split (see docs/unas/nfs-mounts.md):
# - forgejo_data (local named volume): app config, SSH host keys, session # - forgejo_data (local named volume): app config, SSH host keys, session
@ -150,79 +149,6 @@ services:
max-file: "{{DOCKERLOGGING_MAXFILE}}" max-file: "{{DOCKERLOGGING_MAXFILE}}"
max-size: "{{DOCKERLOGGING_MAXSIZE}}" max-size: "{{DOCKERLOGGING_MAXSIZE}}"
# Auto-syncs GitHub repos into Forgejo as mirrors. Forgejo itself has no
# "pull all my repos" config option — this is a separate open-source tool
# (https://github.com/RayLabsHQ/gitea-mirror) that provides exactly that,
# driven entirely by env vars below plus a one-time Forgejo API token (see
# README "GitHub mirroring" section — the token can't exist until Forgejo
# has an admin account, so it can't be templated here).
gitea-mirror:
image: ghcr.io/raylabshq/gitea-mirror:{{GITEA_MIRROR_VERSION:-latest}}
container_name: gitea-mirror
restart: unless-stopped
depends_on:
forgejo:
condition: service_healthy
environment:
NODE_ENV: production
DATABASE_URL: file:data/gitea-mirror.db
HOST: 0.0.0.0
PORT: "4321"
BASE_URL: "/"
BETTER_AUTH_SECRET: "{{GITEA_MIRROR_AUTH_SECRET}}"
BETTER_AUTH_URL: "{{GITEA_MIRROR_PUBLIC_URL}}"
PUBLIC_BETTER_AUTH_URL: "{{GITEA_MIRROR_PUBLIC_URL}}"
# GitHub source
GITHUB_USERNAME: "{{GITHUB_USERNAME}}"
GITHUB_TOKEN: "{{GITHUB_TOKEN}}"
SKIP_FORKS: "{{GITEA_MIRROR_SKIP_FORKS:-false}}"
PRIVATE_REPOSITORIES: "{{GITEA_MIRROR_PRIVATE_REPOS:-true}}"
MIRROR_STARRED: "{{GITEA_MIRROR_STARRED:-false}}"
MIRROR_ORGANIZATIONS: "{{GITEA_MIRROR_ORGANIZATIONS:-false}}"
MIRROR_ISSUES: "{{GITEA_MIRROR_ISSUES:-false}}"
MIRROR_WIKI: "{{GITEA_MIRROR_WIKI:-false}}"
# Forgejo destination — internal service name, no need to hairpin
# through the reverse proxy.
GITEA_URL: "http://forgejo:3000"
GITEA_TOKEN: "{{GITEA_MIRROR_FORGEJO_TOKEN}}"
GITEA_USERNAME: "{{GITEA_MIRROR_FORGEJO_USERNAME}}"
GITEA_ORGANIZATION: "{{GITEA_MIRROR_ORG:-github-mirrors}}"
GITEA_ORG_VISIBILITY: "{{GITEA_MIRROR_ORG_VISIBILITY:-private}}"
# Auto-import every repo on startup and keep mirroring on a schedule —
# this is the "pull all my GitHub repos via config" behavior.
AUTO_IMPORT_REPOS: "true"
AUTO_MIRROR_REPOS: "true"
SCHEDULE_ENABLED: "true"
GITEA_MIRROR_INTERVAL: "{{GITEA_MIRROR_INTERVAL:-8h}}"
CLEANUP_DELETE_IF_NOT_IN_GITHUB: "false"
CLEANUP_DRY_RUN: "true"
networks:
- forgejo_network
ports:
- "{{GITEA_MIRROR_BIND_IP:-0.0.0.0}}:{{GITEA_MIRROR_PORT:-4321}}:4321"
volumes:
- /etc/localtime:/etc/localtime:ro
- gitea_mirror_data:/app/data
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:4321/api/health"]
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
deploy:
resources:
limits:
memory: "{{GITEA_MIRROR_MEM_LIMIT:-256m}}"
reservations:
memory: 64M
security_opt:
- no-new-privileges:true
logging:
driver: json-file
options:
max-file: "{{DOCKERLOGGING_MAXFILE}}"
max-size: "{{DOCKERLOGGING_MAXSIZE}}"
networks: networks:
forgejo_network: forgejo_network:
driver: bridge driver: bridge
@ -231,4 +157,3 @@ networks:
volumes: volumes:
forgejo_db_data: forgejo_db_data:
forgejo_data: forgejo_data:
gitea_mirror_data:

View file

@ -99,7 +99,7 @@ Every policy in this table uses:
| `ALLOW CADDY to Bento PDF` | `10.0.10.6` | `8080` | Bento PDF | | `ALLOW CADDY to Bento PDF` | `10.0.10.6` | `8080` | Bento PDF |
| `ALLOW CADDY to Koffan` | `10.0.10.12` | `8080` | Koffan (LXC 111) | | `ALLOW CADDY to Koffan` | `10.0.10.12` | `8080` | Koffan (LXC 111) |
| `ALLOW CADDY to Hermes` | `10.0.10.19` | `9119` | Hermes Agent dashboard (LXC 113) | | `ALLOW CADDY to Hermes` | `10.0.10.19` | `9119` | Hermes Agent dashboard (LXC 113) |
| `ALLOW CADDY to Forgejo` | `10.0.10.18` | `3000,4321` | Forgejo (LXC 114) and gitea-mirror | | `ALLOW CADDY to Forgejo` | `10.0.10.18` | `3000` | Forgejo (LXC 114) |
--- ---