chore(deploy): stage .vault git-stack compose + adopt xx.xx.xx versioning

Repo-only prep to align MokoGIT with the .vault single-source-of-truth structure and the
MokoOrgStandards xx.xx.xx version scheme. No server/.vault changes; relocation coordinated later.

Versioning (replaces leaked Gitea 1.24.0+dev-N-ghash):
- VERSION = 01.00.00 (Makefile STORED_VERSION uses it verbatim on branch builds -> strips the
  git-describe Gitea base; tag builds use the xx.xx.xx tag name).
- VERSIONING.md documents the scheme + how the binary/image version resolves.
- Default the upstream update-checker OFF (modules/setting/setting.go) so the fork never compares
  AppVer against Gitea's release feed.

Staged git-stack compose (target .vault/stacks/git/{prod,rc,dev}):
- deploy/git/{prod,rc,dev}/ each: docker-compose.yml (image mokoconsulting/mokogit per tier tag env
  MOKOGIT[_RC|_DEV]_TAG, containers mokogit/-rc/-dev, /opt/mokogit/{prod,rc,dev} data, host-MySQL
  db mokogit[_rc|_dev], /api/healthz healthcheck), VERSION (01.00.00), .env.example.
- deploy/git/VERSION (per-stack) + README.md (ownership split, reconcile-before-drop, restructure paused).
- Every host/secret value is ${VAR}; modeled on documented live config, marked RECONCILE (diff vs
  the live /opt/mokogitea/docker-compose.yml before dropping into .vault).

Secrets externalized:
- .gitignore now ignores real .env / *.env but keeps *.env.example. No real tokens committed.

Verified: go build ./modules/setting/ ok; .env.example tracked, real .env ignored.
This commit is contained in:
2026-07-16 10:42:38 -05:00
parent 6f482e7fdb
commit 0cb94ef37d
15 changed files with 340 additions and 1 deletions
+7
View File
@@ -115,6 +115,13 @@ prime/
/.github/copilot-instructions.md
/llms.txt
# Real deploy env files -- NEVER commit secrets. Keep the *.env.example templates.
.env
*.env
!*.env.example
!.env.example
deploy/**/.env
# Ignore worktrees when working on multiple branches
.worktrees/
+1
View File
@@ -0,0 +1 @@
01.00.00
+42
View File
@@ -0,0 +1,42 @@
<!-- SPDX-License-Identifier: GPL-3.0-or-later -->
# MokoGIT Versioning
MokoGIT follows the **MokoOrgStandards `xx.xx.xx`** scheme: `MAJOR.MINOR.PATCH`, **two digits
per segment** (e.g. `01.00.00`, `01.04.12`). This is MokoGIT's own version line — it deliberately
**replaces the inherited upstream Gitea version** (which previously leaked through as
`1.24.0+dev-<N>-g<hash>`).
## Where the version comes from
The binary version is injected at build time into `main.Version``setting.AppVer` (drives the
footer, `/api/v1/version`, and the PWA manifest). The Makefile resolves it in this order:
| Build type | Source | Result |
| --- | --- | --- |
| **Release (git tag)** | the tag name (`$GITHUB_REF_NAME`, `v` stripped) | e.g. tag `01.00.00``01.00.00` |
| **Branch / dev** | the repo-root **`VERSION`** file (`STORED_VERSION`) | `01.00.00` |
| _(fallback only if `VERSION` is absent)_ | `git describe --tags` | would leak the Gitea base — avoided by shipping `VERSION` |
The committed `VERSION` file (currently `01.00.00`) is what strips the Gitea base on ordinary
branch builds. **Do not delete it.**
## Release tagging — MUST use `xx.xx.xx`
Release/tag automation MUST create tags in the `xx.xx.xx` form (e.g. `01.00.00`). Because the
deploy workflows derive the container image tag from `git describe --tags`, tagging with
`01.00.00` makes the deployed image report MokoGIT's version rather than Gitea's. Tiers append a
suffix: dev → `-dev`, rc → `-rc`.
## Update checker
The upstream update-checker defaults to **disabled** (`modules/setting/setting.go`) — a fork must
not compare its `AppVer` against Gitea's release feed. Re-enable only against a MokoGIT endpoint.
## Scope of a bump
- **PATCH** — fixes, no behavior change.
- **MINOR** — backward-compatible features (default bump for feature/dev → stable releases).
- **MAJOR** — breaking changes.
Per-stack and per-tier `VERSION` files also live under `deploy/git/` for the `.vault` git stack.
+49
View File
@@ -0,0 +1,49 @@
<!-- SPDX-License-Identifier: GPL-3.0-or-later -->
# MokoGIT git stack (staged for `.vault`)
This directory is the **staged server compose** for the MokoGIT git service, laid out to match the
target `.vault/stacks/git/{prod,rc,dev}/` structure so it can be dropped into `.vault` when the
restructure resumes.
## Ownership split
- **This repo** (the Gitea fork) builds + pushes the **image** (`mokoconsulting/mokogit`, tiers
`mokogit` / `-rc` / `-dev`) via its own CI.
- **`.vault`** (`MokoConsulting/.vault`, `/opt/.vault` on the Beelink) owns the **server compose +
config** that RUNS those containers. `.vault` is the single source of truth for the box.
## Layout
```
deploy/git/
VERSION # per-stack version (xx.xx.xx)
prod/ { docker-compose.yml, VERSION, .env.example } -> container mokogit, /opt/mokogit/prod, db mokogit
rc/ { docker-compose.yml, VERSION, .env.example } -> container mokogit-rc, /opt/mokogit/rc, db mokogit_rc
dev/ { docker-compose.yml, VERSION, .env.example } -> container mokogit-dev, /opt/mokogit/dev, db mokogit_dev
```
Versioning follows MokoOrgStandards `xx.xx.xx` (see repo-root `VERSIONING.md`). Each tier and the
stack carry a `VERSION` file.
## ⚠️ Not yet live — reconcile first
These composes are **modeled on the documented live config**, not copied from the running box, so
they are **NOT guaranteed byte-accurate**. Before dropping into `.vault`:
1. **DIFF against the live** `/opt/mokogitea/docker-compose.yml` (run with `docker compose -p
gitea-dev`). Reconcile every line tagged `RECONCILE` in the compose: exact volume/conf layout
(live app.ini is at `${GIT_DATA_DIR}/conf/app.ini`), host ports, the DB host reachability (DB is
**host MySQL**; app DB user is `mokogitea`), the docker network name, and any `act_runner` /
`depends_on` wiring (note: `depends_on` uses the prod service key — mismatches caused a past
outage).
2. **Secrets stay external** — every host/secret value is `${VAR}`; real values go in a **gitignored
`.env`** or Gitea Actions secrets, never committed. `.env.example` files carry only placeholders.
## Do NOT relocate yet
The `.vault` restructure is **PAUSED** on server drift (partly from the mokogitea→mokogit rebrand
leaving the box tree dirty) and an **open critical secrets-in-git issue** in `.vault` history. Moving
the git compose onto the box now risks breaking the `--ff-only` pull. Relocation happens when the
restructure resumes — coordinate first. Until then git keeps running from `/opt/mokogitea` +
`/opt/gitea-dev` (the old locations).
+1
View File
@@ -0,0 +1 @@
01.00.00
+27
View File
@@ -0,0 +1,27 @@
# MokoGIT git stack -- DEV tier env (EXAMPLE -- copy to .env and fill; .env is gitignored)
# SPDX-License-Identifier: GPL-3.0-or-later
# No real secrets here. RECONCILE all values against the live box before use.
GIT_REGISTRY=git.mokoconsulting.tech
GIT_IMAGE=mokoconsulting/mokogit
MOKOGIT_DEV_TAG=01.00.00-dev # dev image tag. Deploy CI pins this per build.
GIT_UID=1000
GIT_GID=1000
GIT_DOMAIN=dev.git.mokoconsulting.tech
GIT_ROOT_URL=https://dev.git.mokoconsulting.tech/
GIT_SSH_DOMAIN=dev.git.mokoconsulting.tech
GIT_SSH_PUBLIC_PORT=2918
GIT_HTTP_PORT=3002
GIT_SSH_PORT=2224
GIT_DATA_DIR=/opt/mokogit/dev
GIT_DB_HOST=host.docker.internal:3306
GIT_DB_NAME=mokogit_dev
GIT_DB_USER=mokogitea
GIT_DB_PASSWD=__SET_IN_REAL_ENV__
GIT_NETWORK=gitea-dev_default
+1
View File
@@ -0,0 +1 @@
01.00.00
+47
View File
@@ -0,0 +1,47 @@
# MokoGIT git stack -- DEV tier
# SPDX-License-Identifier: GPL-3.0-or-later
#
# STAGED for .vault/stacks/git/dev/ -- see ../README.md. Modeled on the documented live config;
# DIFF against the live /opt/mokogitea/docker-compose.yml before dropping into .vault.
# Every host/secret value is ${VAR} (define real values in a gitignored .env; see .env.example).
services:
git:
image: "${GIT_REGISTRY}/${GIT_IMAGE}:${MOKOGIT_DEV_TAG}"
container_name: mokogit-dev
restart: unless-stopped
environment:
- USER_UID=${GIT_UID}
- USER_GID=${GIT_GID}
- GITEA__server__DOMAIN=${GIT_DOMAIN}
- GITEA__server__ROOT_URL=${GIT_ROOT_URL}
- GITEA__server__SSH_DOMAIN=${GIT_SSH_DOMAIN}
- GITEA__server__SSH_PORT=${GIT_SSH_PUBLIC_PORT}
- GITEA__database__DB_TYPE=mysql
- GITEA__database__HOST=${GIT_DB_HOST}
- GITEA__database__NAME=${GIT_DB_NAME}
- GITEA__database__USER=${GIT_DB_USER}
- GITEA__database__PASSWD=${GIT_DB_PASSWD}
volumes:
# RECONCILE: live app.ini at ${GIT_DATA_DIR}/conf/app.ini (/opt/mokogit/dev/conf).
- "${GIT_DATA_DIR}:/data"
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "${GIT_HTTP_PORT}:3000"
- "${GIT_SSH_PORT}:22"
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:3000/api/healthz"]
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- git
networks:
git:
name: ${GIT_NETWORK}
external: true
+34
View File
@@ -0,0 +1,34 @@
# MokoGIT git stack -- PROD tier env (EXAMPLE -- copy to .env and fill real values; .env is gitignored)
# SPDX-License-Identifier: GPL-3.0-or-later
# No real secrets in this file. RECONCILE all values against the live box before use.
# --- image ---
GIT_REGISTRY=git.mokoconsulting.tech
GIT_IMAGE=mokoconsulting/mokogit
MOKOGIT_TAG=01.00.00 # prod image tag (release xx.xx.xx). Deploy CI pins this per build.
# --- runtime user ---
GIT_UID=1000
GIT_GID=1000
# --- server / URLs ---
GIT_DOMAIN=git.mokoconsulting.tech
GIT_ROOT_URL=https://git.mokoconsulting.tech/
GIT_SSH_DOMAIN=git.mokoconsulting.tech
GIT_SSH_PUBLIC_PORT=2918 # public SSH port advertised to clients
# --- host ports (container 3000/22 mapped to host) ---
GIT_HTTP_PORT=3000
GIT_SSH_PORT=2222
# --- data ---
GIT_DATA_DIR=/opt/mokogit/prod
# --- database (HOST MySQL; app DB user is 'mokogitea') ---
GIT_DB_HOST=host.docker.internal:3306
GIT_DB_NAME=mokogit
GIT_DB_USER=mokogitea
GIT_DB_PASSWD=__SET_IN_REAL_ENV__ # real value ONLY in gitignored .env / Actions secret
# --- docker network (external; RECONCILE actual name) ---
GIT_NETWORK=gitea-dev_default
+1
View File
@@ -0,0 +1 @@
01.00.00
+52
View File
@@ -0,0 +1,52 @@
# MokoGIT git stack -- PROD tier
# SPDX-License-Identifier: GPL-3.0-or-later
#
# STAGED for .vault/stacks/git/prod/ -- see ../README.md. Modeled on the documented live
# config; DIFF against the live /opt/mokogitea/docker-compose.yml before dropping into .vault.
# Ownership: THIS repo builds+pushes the image; .vault runs it. Every host/secret value is ${VAR}
# (define real values in a gitignored .env; see .env.example). Do NOT commit a real .env.
#
# RECONCILE before use: exact volume/conf layout, ports, DB host reachability (host MySQL),
# network name, and any act_runner/depends_on wiring are modeled -- verify against the box.
services:
git:
image: "${GIT_REGISTRY}/${GIT_IMAGE}:${MOKOGIT_TAG}"
container_name: mokogit
restart: unless-stopped
environment:
- USER_UID=${GIT_UID}
- USER_GID=${GIT_GID}
- GITEA__server__DOMAIN=${GIT_DOMAIN}
- GITEA__server__ROOT_URL=${GIT_ROOT_URL}
- GITEA__server__SSH_DOMAIN=${GIT_SSH_DOMAIN}
- GITEA__server__SSH_PORT=${GIT_SSH_PUBLIC_PORT}
# DB is HOST MySQL (RECONCILE host reachability: host-gateway / socket / LAN IP).
- GITEA__database__DB_TYPE=mysql
- GITEA__database__HOST=${GIT_DB_HOST}
- GITEA__database__NAME=${GIT_DB_NAME}
- GITEA__database__USER=${GIT_DB_USER}
- GITEA__database__PASSWD=${GIT_DB_PASSWD}
volumes:
# RECONCILE: live app.ini is at ${GIT_DATA_DIR}/conf/app.ini (/opt/mokogit/prod/conf).
- "${GIT_DATA_DIR}:/data"
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "${GIT_HTTP_PORT}:3000"
- "${GIT_SSH_PORT}:22"
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:3000/api/healthz"]
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- git
networks:
git:
name: ${GIT_NETWORK}
external: true
+27
View File
@@ -0,0 +1,27 @@
# MokoGIT git stack -- RC tier env (EXAMPLE -- copy to .env and fill; .env is gitignored)
# SPDX-License-Identifier: GPL-3.0-or-later
# No real secrets here. RECONCILE all values against the live box before use.
GIT_REGISTRY=git.mokoconsulting.tech
GIT_IMAGE=mokoconsulting/mokogit
MOKOGIT_RC_TAG=01.00.00-rc # rc image tag. Deploy CI pins this per build.
GIT_UID=1000
GIT_GID=1000
GIT_DOMAIN=rc.git.mokoconsulting.tech
GIT_ROOT_URL=https://rc.git.mokoconsulting.tech/
GIT_SSH_DOMAIN=rc.git.mokoconsulting.tech
GIT_SSH_PUBLIC_PORT=2918
GIT_HTTP_PORT=3001
GIT_SSH_PORT=2223
GIT_DATA_DIR=/opt/mokogit/rc
GIT_DB_HOST=host.docker.internal:3306
GIT_DB_NAME=mokogit_rc
GIT_DB_USER=mokogitea
GIT_DB_PASSWD=__SET_IN_REAL_ENV__
GIT_NETWORK=gitea-dev_default
+1
View File
@@ -0,0 +1 @@
01.00.00
+47
View File
@@ -0,0 +1,47 @@
# MokoGIT git stack -- RC tier
# SPDX-License-Identifier: GPL-3.0-or-later
#
# STAGED for .vault/stacks/git/rc/ -- see ../README.md. Modeled on the documented live config;
# DIFF against the live /opt/mokogitea/docker-compose.yml before dropping into .vault.
# Every host/secret value is ${VAR} (define real values in a gitignored .env; see .env.example).
services:
git:
image: "${GIT_REGISTRY}/${GIT_IMAGE}:${MOKOGIT_RC_TAG}"
container_name: mokogit-rc
restart: unless-stopped
environment:
- USER_UID=${GIT_UID}
- USER_GID=${GIT_GID}
- GITEA__server__DOMAIN=${GIT_DOMAIN}
- GITEA__server__ROOT_URL=${GIT_ROOT_URL}
- GITEA__server__SSH_DOMAIN=${GIT_SSH_DOMAIN}
- GITEA__server__SSH_PORT=${GIT_SSH_PUBLIC_PORT}
- GITEA__database__DB_TYPE=mysql
- GITEA__database__HOST=${GIT_DB_HOST}
- GITEA__database__NAME=${GIT_DB_NAME}
- GITEA__database__USER=${GIT_DB_USER}
- GITEA__database__PASSWD=${GIT_DB_PASSWD}
volumes:
# RECONCILE: live app.ini at ${GIT_DATA_DIR}/conf/app.ini (/opt/mokogit/rc/conf).
- "${GIT_DATA_DIR}:/data"
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "${GIT_HTTP_PORT}:3000"
- "${GIT_SSH_PORT}:22"
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:3000/api/healthz"]
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- git
networks:
git:
name: ${GIT_NETWORK}
external: true
+3 -1
View File
@@ -187,7 +187,9 @@ func loadCommonSettingsFrom(cfg ConfigProvider) error {
func loadUpdateCheckerFrom(cfg ConfigProvider) {
sec := cfg.Section("update_checker")
UpdateChecker.Enabled = sec.Key("ENABLED").MustBool(true)
// MokoGIT is a fork with its own xx.xx.xx version scheme (see repo VERSION / VERSIONING.md);
// default the upstream update-checker OFF so we never compare AppVer against Gitea's release feed.
UpdateChecker.Enabled = sec.Key("ENABLED").MustBool(false)
UpdateChecker.Endpoint = sec.Key("ENDPOINT").MustString(UpdateChecker.Endpoint)
UpdateChecker.Channel = sec.Key("CHANNEL").MustString(UpdateChecker.Channel)
}