Skip to content

bootstrap

standing the stack up from nothing. onboarding is the other thing called onboarding: that one adds a repo to a board that already runs.

read architecture first, in particular the single-node and static-storage constraints. this deployment targets openshift; the pieces that are openshift-specific are called out as they come up.

1. dns and hostnames

two public names pointing at the cluster's ingress: one for the editor, one for the board. TLS comes from cert-manager, so a ClusterIssuer must already exist (this deployment uses letsencrypt-prod); the ingresses reference it by name and nothing in this repo creates it.

2. github apps

three separate github registrations, all optional in local development and all required in production:

  • editor login: an OAuth app. callback https://<editor-host>/auth/github/callback. gives CMD_GITHUB_CLIENTID and CMD_GITHUB_CLIENTSECRET. no repo scope is requested: the editor only needs identity.
  • board login: a second OAuth app for the board's /settings and /bots pages. callback https://<board-host>/auth/github/callback. gives BOARD_OAUTH_CLIENT_ID and BOARD_OAUTH_CLIENT_SECRET.
  • writing to target repos: either a github app installed on each namespace repo (GITHUB_APP_ID + GITHUB_APP_PRIVATE_KEY, preferred: per-repo installation tokens) or one service PAT (GITHUB_TOKEN) with contents and pull-request write on every namespace. an app plus the PAT as fallback is the normal setup.

3. storage

there is no dynamic provisioner: create the host directories and the PVs before anything can bind. on the node:

mkdir -p /var/data/hedgedoc/{postgresql,backups,uploads}
chown root:0 /var/data/hedgedoc/*
chmod 2770 /var/data/hedgedoc/*

group 0 with the setgid bit is what makes the volumes writable under openshift's random-UID SCC without granting anyuid.

4. secrets

created out of band and never committed. one secret per service, so no pod carries another's credentials: hedgedoc-editor, spec-board and hedgedoc-postgres. the table below groups the keys by which secret holds them.

key secret required
CMD_DB_PASSWORD all three (it is the same database) yes
CMD_SESSION_SECRET hedgedoc-editor: sessions yes
CMD_GITHUB_CLIENTSECRET hedgedoc-editor: login yes
GITHUB_TOKEN spec-board: roles, scans, PR fallback one of these
GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY spec-board: per-namespace tokens one of these
BOARD_OAUTH_CLIENT_SECRET, SESSION_SECRET spec-board: /settings, /bots, unsubscribe links for the settings page
SMTP_USER, SMTP_PASS spec-board: email digests optional
WEBHOOK_URL spec-board: notifications optional

rotating SESSION_SECRET logs everyone out of the board and invalidates every unsubscribe link already emailed. treat it as a one-way door.

5. images

both images are built from this repo:

hack/build-editor.sh                              # editor
podman build -t spec-board:local spec-board       # board

on a cluster, the infra repo builds both for you: oc start-build editor-src once, and after that a push to master is enough.

6. deploy

the manifests live in specdoc-infra, exported from a running cluster rather than written by hand:

oc apply -k namespaces/hedgedoc/build   # imagestreams, builds, the poller
oc apply -k namespaces/hedgedoc/app     # editor, board, postgres, backups

they carry this cluster's hostnames, storage class and hostPath layout, so a different cluster means editing them. oc diff -k before every apply: the manifests are meant to describe what is already running.

7. first login and check

  • open the editor host, sign in with github, create a note
  • curl https://<board-host>/statusz for poller state
  • curl https://<board-host>/api/namespaces should report pass for roles on every configured repo
  • then follow onboarding to add the first repo