Otomo: wiki service¶
Ticket: SCRUM-172 (wiki hosting on the VM with Docker Compose).
Builds on: 15-allocator-and-edge-plan.md §3 (the public edge this is served through).
Otomo hosts two kinds of wiki with one framework:
| Site | Content lives in | Served at | Who edits |
|---|---|---|---|
| Technical wiki: onboarding, technical design, setup docs for anyone adopting otomo | this repository, docs/ |
https://<public host>/docs/ |
the otomo team, by PR |
| Game site: the wiki for the game built on otomo | the game's own repository, never this one | https://<public host>/ |
the game team, by pushing to that repo |
Otomo doesn't depend on any particular game. It provides the framework (build, image, serving, deployment) and reads a content directory. It contains no game content and no game names.
1. The content contract¶
A content directory is:
_site.yml site settings (required)
index.md the home page
*.md, */*.md pages; any folder layout
assets/… images and other static files, linked relatively
README.md optional; excluded from the site (use it for editing instructions)
_site.yml is a small subset of MkDocs' configuration. The framework owns everything else
(theme, extensions, search, strictness):
site_name: Example Wiki # required
site_description: … # optional
nav: [...] # optional; defaults to the folder layout
copyright: … # optional
theme: # optional, only these keys
palette: {primary: indigo, accent: amber}
logo: assets/logo.png
favicon: assets/favicon.png
extra: {...} # optional, passed through
Unknown keys fail the build with a message naming them, so a typo can't silently do nothing.
2. The framework (services/wiki)¶
- Build stage: Python with pinned
mkdocsandmkdocs-material.build.pymerges the framework'sbase.ymlwith the content's_site.ymland runsmkdocs build --strict. A broken link, a missing nav page or a bad config fails the build, so the running site is never replaced by a broken one. - Runtime stage: unprivileged nginx on 8080 serving the static files under the site's
base path (
BASE_PATH, e.g./docs/). Redirects and relative links then stay correct behind the edge, which forwards the path unchanged. - Privacy and safety: no cookies, no external requests (no web fonts, no analytics), a
strict CSP,
X-Content-Type-Options, and noServerversion. Search runs in the browser. - The content is a named build context (
content), so the same image recipe builds any site: compose passes../docsfor the technical wiki andSITE_CONTENT_DIRfor the game site. services/wiki/example/is a minimal, game-neutral content directory used by tests and as a template for adopters.
3. Deployment¶
| Compose service | Profile | Content | Image tag |
|---|---|---|---|
wiki-docs |
edge |
../docs |
commit SHA of this repo |
wiki-site |
site |
SITE_CONTENT_DIR (a checkout of the game's repo) |
commit SHA of the content repo |
Both are on otomo-edge only. The edge routes /docs/ to wiki-docs and, when
EDGE_SITE_URL is set, everything that isn't the player API or /docs/ to wiki-site.
Automatic deploys of the game site¶
A push to the content repository's main branch redeploys the site:
content repo ──push──► GitHub webhook ──► :5009 webhook proxy ──► Jenkins job `otomo-site-deploy`
(Generic Webhook Trigger, own token, main only)
└── sudo -u <deploy user> deploy/site/deploy-site.sh (the only command Jenkins may run as that user)
1. git fetch + reset the content checkout to origin/main (read-only deploy key)
2. build wiki-site (mkdocs --strict); on failure stop, and the old site keeps serving
3. push to the local registry as otomo-wiki-site:<content sha>, record the tag in deploy/.env
4. recreate wiki-site and wait for it to answer
- The webhook carries no content. It only says "main moved", and the host fetches from
GitHub itself with a read-only deploy key. A forged webhook can at most redeploy what's
already on
main. - Rollback is a re-point, like every other service: set
OTOMO_WIKI_SITE_TAGto the previous SHA andup -d wiki-site.
Why the game repo doesn't include otomo (no submodule)¶
Otomo consumes the content directory; the content repo doesn't consume otomo.
- The game team edits Markdown and never manages a submodule pointer.
- The content repo needs no access to the private otomo repo.
- The framework can be upgraded for every site from one place.
The dependency is one-way: _site.yml is the whole interface. To preview locally, run
services/wiki/preview.sh <content dir> from an otomo checkout. It runs the same pinned
builder with live reload.
4. Tasks¶
| # | Task | Done when |
|---|---|---|
| W-1 | services/wiki: builder, runtime image, _site.yml validation, example content, preview script |
Example builds --strict; a broken link fails the build; the image serves under /docs/ and / |
| W-2 | Technical wiki content: docs/_site.yml, landing page, onboarding and adopter guides, nav over docs 00–16 |
wiki-docs builds strict; https://<host>/docs/ serves it |
| W-3 | Compose (wiki-docs, wiki-site), edge routing under the base path, check-compose |
check-compose passes; the edge serves both |
| W-4 | deploy/site/deploy-site.sh, the Jenkins job, deploy key and webhook |
A push to the content repo's main is live within a minute; a broken push leaves the old site up |