Demo content from demo/admin-guide (0c17989)
This commit is contained in:
parent
8385e2024a
commit
3c566c0cc9
11 changed files with 645 additions and 2 deletions
8
.order
Normal file
8
.order
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
sign-in-options
|
||||
entra-id
|
||||
forgejo-identity-provider
|
||||
github-sign-in
|
||||
spaces-and-git-providers
|
||||
configuration-reference
|
||||
backup-and-restore
|
||||
operations
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
# admin-guide
|
||||
|
||||
69
backup-and-restore/index.md
Normal file
69
backup-and-restore/index.md
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
---
|
||||
id: backup-and-restore
|
||||
title: Backup and restore
|
||||
description: What actually needs a backup — Git holds the content, the database only holds a derived index.
|
||||
tags: [admin, backup, restore]
|
||||
lang: en
|
||||
---
|
||||
|
||||
# Backup and restore
|
||||
|
||||
f451's split between "Git is the source of truth" and "Postgres is only an
|
||||
index" (see *Principles* in the Developer Guide) turns backup planning
|
||||
into a short list, not a long one.
|
||||
|
||||
## The one thing that matters
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **The Forgejo data volume is the only backup-critical piece of a whole
|
||||
> f451 deployment.** It holds every space's repository content plus
|
||||
> Forgejo's own configuration and account database. Losing it without a
|
||||
> backup means the wiki content is gone — there is nothing else it can be
|
||||
> rebuilt from.
|
||||
|
||||
If a space lives on GitHub instead of the bundled Forgejo, that content is
|
||||
already backed up by GitHub itself; only Forgejo-hosted spaces are this
|
||||
deployment's own responsibility.
|
||||
|
||||
## The database is a rebuildable cache
|
||||
|
||||
The Postgres volume holds the search index, rendered page content, the
|
||||
knowledge-graph edges, sessions, and encrypted provider tokens. All of the
|
||||
content-derived pieces are rebuilt automatically:
|
||||
|
||||
- `POST /admin/reindex` (bearer-token-protected, see
|
||||
[[operations]]) rebuilds the full index for one or all spaces from Git,
|
||||
on demand.
|
||||
- The drift job (see [[spaces-and-git-providers]]) rebuilds it
|
||||
automatically within about five minutes of a missed webhook, without any
|
||||
manual step.
|
||||
|
||||
Losing the database without a backup costs two things, neither of them
|
||||
content:
|
||||
|
||||
- **Sessions** — everyone has to sign in again.
|
||||
- **Encrypted provider tokens** — everyone has to reconnect their Forgejo
|
||||
or GitHub account once (see [[sign-in-options]]).
|
||||
|
||||
A database backup is still worth having in practice, purely to skip the
|
||||
reindex time and avoid the mass reconnect — but it is never the *only*
|
||||
copy of anything.
|
||||
|
||||
## Restore, in outline
|
||||
|
||||
1. Stop both stacks (the Git stack and the application stack).
|
||||
2. Restore the Forgejo data volume from backup.
|
||||
3. Start the Git stack and wait for it to report healthy.
|
||||
4. Start the application stack. The database starts empty — apply pending
|
||||
migrations before traffic reaches the new containers (the production
|
||||
image ships a compiled migration runner for exactly this).
|
||||
5. Trigger a full reindex of all spaces (`POST /admin/reindex`) rather than
|
||||
waiting for the drift job — after a restore there is no reason to wait
|
||||
up to five minutes for content to reappear.
|
||||
6. Verify: the space list responds, a known page is readable, and
|
||||
`GET /admin/status` reports no indexing errors for the reindex that just
|
||||
ran.
|
||||
|
||||
Sessions and account connections are deliberately not part of this
|
||||
procedure — people sign in again and, if needed, reconnect their Git
|
||||
account once, exactly as described above.
|
||||
123
configuration-reference/index.md
Normal file
123
configuration-reference/index.md
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
---
|
||||
id: configuration-reference
|
||||
title: Configuration reference
|
||||
description: Every environment variable the api service reads, grouped by concern.
|
||||
tags: [admin, reference, configuration]
|
||||
lang: en
|
||||
---
|
||||
|
||||
# Configuration reference
|
||||
|
||||
All variables below are read by the `api` service. None are required to
|
||||
start f451 at all — an instance with nothing set runs in a minimal,
|
||||
read-only, unauthenticated mode (`/healthz`/`/readyz` only). Each group
|
||||
becomes meaningful once you set its first variable.
|
||||
|
||||
## Spaces and providers
|
||||
|
||||
See [[spaces-and-git-providers]] for the full explanation.
|
||||
|
||||
| Variable | Required when | Default |
|
||||
|---|---|---|
|
||||
| `F451_SPACES` | Any space should be visible | — (minimal mode) |
|
||||
| `F451_FORGEJO_URL` | A space uses `provider: "forgejo"`, or Forgejo account linking is enabled | — |
|
||||
| `F451_FORGEJO_TOKEN` | A space uses `provider: "forgejo"` | — |
|
||||
| `F451_GITHUB_TOKEN` | A space uses `provider: "github"` | — |
|
||||
| `F451_WEBHOOK_SECRET_FORGEJO` | Forgejo webhooks should be accepted | — |
|
||||
| `F451_WEBHOOK_SECRET_GITHUB` | GitHub webhooks should be accepted | — |
|
||||
| `F451_GLOBAL_TEMPLATES` | A provider-wide template repository is shared across spaces | — |
|
||||
|
||||
## Sign-in (OIDC)
|
||||
|
||||
See [[sign-in-options]], [[entra-id]], [[forgejo-identity-provider]].
|
||||
|
||||
| Variable | Required when | Default |
|
||||
|---|---|---|
|
||||
| `F451_OIDC_ISSUER` | Auth should be enabled at all — unset means the entire API is unauthenticated | — (auth off) |
|
||||
| `F451_OIDC_CLIENT_ID` | `F451_OIDC_ISSUER` is set | — |
|
||||
| `F451_OIDC_CLIENT_SECRET` | `F451_OIDC_ISSUER` is set | — |
|
||||
| `F451_OIDC_REDIRECT_URL` | `F451_OIDC_ISSUER` is set — must equal `https://<host>/auth/callback` | — |
|
||||
| `F451_OIDC_PROVIDER_NAME` | Never required | unset → plain "Sign in" button |
|
||||
| `F451_TOKEN_KEY` | `F451_OIDC_ISSUER` is set — otherwise the api fails to start | — |
|
||||
|
||||
## Sign-in (GitHub)
|
||||
|
||||
See [[github-sign-in]].
|
||||
|
||||
| Variable | Required when | Default |
|
||||
|---|---|---|
|
||||
| `F451_GITHUB_LOGIN` | GitHub should appear as a sign-in method | `0` (off) |
|
||||
| `F451_GITHUB_OAUTH_CLIENT_ID` | `F451_GITHUB_LOGIN=1` | — |
|
||||
| `F451_GITHUB_OAUTH_CLIENT_SECRET` | `F451_GITHUB_LOGIN=1` | — |
|
||||
|
||||
## Account linking (reading and writing)
|
||||
|
||||
Independent of which method someone signed in with — see
|
||||
[[sign-in-options]].
|
||||
|
||||
| Variable | Required when | Default |
|
||||
|---|---|---|
|
||||
| `F451_FORGEJO_OAUTH_CLIENT_ID` / `_SECRET` | "Connect Forgejo" should be offered (needs `F451_FORGEJO_URL` too) | — (linking off) |
|
||||
| `F451_GITHUB_OAUTH_CLIENT_ID` / `_SECRET` | "Connect GitHub" should be offered | — (linking off) |
|
||||
|
||||
## Cookies and running more than one instance on a host
|
||||
|
||||
| Variable | Required when | Default |
|
||||
|---|---|---|
|
||||
| `F451_COOKIE_PREFIX` | A second instance shares a host with this one — browsers do not separate cookies by port | `f451` |
|
||||
| `F451_WEB_PORT` | A second instance needs a different host port for the web UI | `8080` |
|
||||
| `F451_DRAWIO_PORT` | A second instance needs a different host port for the diagram editor | `8081` |
|
||||
| `F451_FORGEJO_HTTP_PORT` / `F451_FORGEJO_SSH_PORT` | A second Forgejo instance shares a host | Forgejo defaults |
|
||||
| `F451_FORGEJO_ROOT_URL` | A second Forgejo instance shares a host | Forgejo default |
|
||||
|
||||
## Local development only
|
||||
|
||||
> [!WARNING]
|
||||
> Never set either of these in production.
|
||||
|
||||
| Variable | Effect |
|
||||
|---|---|
|
||||
| `F451_INSECURE_COOKIES=1` | Drops `secure` on session cookies (plain HTTP). |
|
||||
| `F451_OIDC_ALLOW_INSECURE=1` | Allows an `http://` OIDC issuer. |
|
||||
|
||||
## Admin and operations
|
||||
|
||||
See [[operations]] and [[backup-and-restore]].
|
||||
|
||||
| Variable | Required when | Default |
|
||||
|---|---|---|
|
||||
| `F451_ADMIN_TOKEN` | `POST /admin/reindex` and `GET /admin/status` should work at all — unset means both are fail-closed | — (disabled) |
|
||||
| `F451_MAX_UPLOAD_MB` | A non-default media upload limit is needed | `10` |
|
||||
|
||||
## Rate limits and reverse proxy
|
||||
|
||||
| Variable | Required when | Default |
|
||||
|---|---|---|
|
||||
| `F451_RATE_LIMIT_AUTH_MAX` | A non-default auth rate limit is needed (per route, per client IP) | `10`/min |
|
||||
| `F451_RATE_LIMIT_SEARCH_MAX` | A non-default search rate limit is needed | `60`/min |
|
||||
| `F451_RATE_LIMIT_API_TOKEN_MAX` | A non-default limit for API-token traffic (MCP agents) is needed, per user across their tokens | `300`/min |
|
||||
| `F451_TRUST_PROXY` | This deployment always runs behind a reverse proxy — without it, every user shares one rate-limit bucket | — (no proxy trusted) |
|
||||
|
||||
> [!IMPORTANT]
|
||||
> `F451_TRUST_PROXY` needs the number of trusted hops between the reverse
|
||||
> proxy and the `api` service, not just "on" or "off". Setting it to `true`
|
||||
> trusts the left-most `X-Forwarded-For` entry, which a client can set
|
||||
> itself — that makes the rate limits trivially bypassable. Verify the
|
||||
> correct hop count against your actual proxy chain before relying on the
|
||||
> limits in production; see [[operations]].
|
||||
|
||||
## Public URL
|
||||
|
||||
| Variable | Required when | Default |
|
||||
|---|---|---|
|
||||
| `F451_PUBLIC_BASE_URL` | Production, effectively always | — (falls back to the request's `Host` header) |
|
||||
|
||||
`F451_PUBLIC_BASE_URL` is the exact scheme and host (no path) that users
|
||||
type into their browser. It is the basis for the OAuth `redirect_uri` used
|
||||
when connecting a Forgejo or GitHub account, and it is the "our own
|
||||
origin" side of the CSRF origin check on every write request.
|
||||
|
||||
> [!WARNING]
|
||||
> A wrong value here does not fail loudly at startup — it fails at the
|
||||
> first save, with every mutating browser request rejected with `403`. See
|
||||
> [[operations]] for this symptom in the troubleshooting table.
|
||||
77
entra-id/index.md
Normal file
77
entra-id/index.md
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
---
|
||||
id: entra-id
|
||||
title: Microsoft Entra ID
|
||||
description: Registering an app in Entra and pointing f451's OIDC configuration at it, step by step.
|
||||
tags: [admin, auth, entra]
|
||||
lang: en
|
||||
---
|
||||
|
||||
# Microsoft Entra ID
|
||||
|
||||
Entra ID is a standard OpenID Connect provider from f451's point of view —
|
||||
nothing here is Entra-specific in the code, only in the app registration
|
||||
steps below.
|
||||
|
||||
## 1. Register an application
|
||||
|
||||
In the Entra admin center, create a new **app registration**:
|
||||
|
||||
- **Single tenant** (unless you specifically need multi-tenant sign-in).
|
||||
- **Redirect URI**, platform *Web*: `https://<host>/auth/callback` — this
|
||||
must match `F451_OIDC_REDIRECT_URL` exactly, including scheme and any
|
||||
trailing slash.
|
||||
- Under **Certificates & secrets**, create a **client secret**.
|
||||
|
||||
> [!WARNING]
|
||||
> Client secrets expire. Note the expiry date somewhere your team actually
|
||||
> looks (a calendar reminder, not just the Entra portal) — an expired
|
||||
> secret takes sign-in down for everyone until it is rotated. Rotating it
|
||||
> means generating a new secret in Entra and updating
|
||||
> `F451_OIDC_CLIENT_SECRET`, then restarting the `api` service.
|
||||
|
||||
## 2. Configure the ID token claims
|
||||
|
||||
Recommended: add the optional claim **`email`** to the ID token (**Token
|
||||
configuration** → **Add optional claim** → ID). f451 reads the user's
|
||||
email from the `email` claim, falling back to `preferred_username` or
|
||||
`upn` if either of those looks like an email address (contains `@`).
|
||||
Without a usable email claim, sign-in still works, but the identity f451
|
||||
records for that person is less predictable.
|
||||
|
||||
## 3. Restrict who may sign in
|
||||
|
||||
By default, anyone in the tenant with access to the app can sign in. To
|
||||
restrict that, open the **enterprise application** for this app
|
||||
registration and turn on **Assignment required** under **Properties**,
|
||||
then assign the users or groups who should have access under **Users and
|
||||
groups**. This is the only access control at the sign-in layer — it does
|
||||
not grant access to any space; that still comes from the person's Forgejo
|
||||
or GitHub permissions (see [[sign-in-options]]).
|
||||
|
||||
## 4. Configure f451
|
||||
|
||||
Set on the `api` service:
|
||||
|
||||
| Variable | Value |
|
||||
|---|---|
|
||||
| `F451_OIDC_ISSUER` | `https://login.microsoftonline.com/<tenant-id>/v2.0` |
|
||||
| `F451_OIDC_CLIENT_ID` | the app registration's Application (client) ID |
|
||||
| `F451_OIDC_CLIENT_SECRET` | the client secret from step 1 |
|
||||
| `F451_OIDC_REDIRECT_URL` | `https://<host>/auth/callback` |
|
||||
| `F451_TOKEN_KEY` | 32 random bytes, base64-encoded (`openssl rand -base64 32`) — encrypts stored provider tokens, independent of Entra |
|
||||
| `F451_OIDC_PROVIDER_NAME` | optional, e.g. `Microsoft Entra` — labels the sign-in button "Sign in with Microsoft Entra"; unset shows a plain "Sign in" |
|
||||
|
||||
f451 requests the scopes `openid email profile` — no Entra-side API
|
||||
permissions need to be granted beyond what a standard app registration
|
||||
gets by default.
|
||||
|
||||
## Forgejo can use Entra too
|
||||
|
||||
If your Forgejo instance should show the same people as f451 without a
|
||||
separate identity system, configure Entra as an **authentication source**
|
||||
in Forgejo itself (Forgejo admin panel → Authentication Sources → add an
|
||||
OAuth2/OIDC source pointed at the same Entra app, or a dedicated one).
|
||||
Users then still take the one extra step of linking their Forgejo account
|
||||
under **Settings → Connections** in f451 — Entra authenticating both
|
||||
systems does not by itself connect them. See
|
||||
[[forgejo-identity-provider]] for the setup that removes even that step.
|
||||
67
forgejo-identity-provider/index.md
Normal file
67
forgejo-identity-provider/index.md
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
---
|
||||
id: forgejo-identity-provider
|
||||
title: Forgejo as the identity provider
|
||||
description: Using the bundled Forgejo's built-in OIDC provider for sign-in, and linking accounts in one step.
|
||||
tags: [admin, auth, forgejo]
|
||||
lang: en
|
||||
---
|
||||
|
||||
# Forgejo as the identity provider
|
||||
|
||||
Forgejo ships a built-in OpenID Connect provider
|
||||
(`/.well-known/openid-configuration`). f451 can point its one configured
|
||||
OIDC issuer at it instead of an external identity provider — useful for
|
||||
local development, and viable for production if Forgejo is already your
|
||||
single source of identity (see [[entra-id]] for federating Forgejo's own
|
||||
accounts to Entra, so user management still lives in one place).
|
||||
|
||||
## Create the OAuth2 application in Forgejo
|
||||
|
||||
In Forgejo, as an administrator (or as the account that should own the
|
||||
app): **Settings → Applications → OAuth2 Applications**, create a new
|
||||
application with redirect URI `https://<host>/auth/callback`. Forgejo
|
||||
gives you a **Client ID** and **Client Secret** — set these as
|
||||
`F451_OIDC_CLIENT_ID` / `F451_OIDC_CLIENT_SECRET`, and set
|
||||
`F451_OIDC_ISSUER` to the Forgejo instance's base URL.
|
||||
|
||||
## The one-app trick: sign-in and account linking together
|
||||
|
||||
Normally, signing in and connecting a Forgejo account (for reading and
|
||||
writing spaces, see [[sign-in-options]]) are two separate steps: sign in
|
||||
via whatever OIDC provider is configured, then separately connect Forgejo
|
||||
under **Settings → Connections**.
|
||||
|
||||
> [!TIP]
|
||||
> If f451's OIDC client (`F451_OIDC_CLIENT_ID`/`_SECRET`) and the Forgejo
|
||||
> account-linking connection (`F451_FORGEJO_OAUTH_CLIENT_ID`/`_SECRET`)
|
||||
> point at the **same** Forgejo OAuth2 application, the first sign-in
|
||||
> already links the Forgejo account — there is no second step. This is
|
||||
> exactly the setup `scripts/dev-local-setup.sh` creates for local
|
||||
> development.
|
||||
|
||||
Using two different Forgejo OAuth2 applications for the two purposes also
|
||||
works — it just means a person signs in, then still has to connect Forgejo
|
||||
separately before they see any space.
|
||||
|
||||
## User management lives in Forgejo
|
||||
|
||||
Once Forgejo is the identity source, account lifecycle — creating
|
||||
accounts, password resets, two-factor authentication, or federating a
|
||||
further upstream source like LDAP — happens entirely in Forgejo's own
|
||||
admin panel. f451 does not duplicate any of it; it only consumes the
|
||||
resulting OIDC identity.
|
||||
|
||||
## Local-only settings
|
||||
|
||||
Running Forgejo as the identity provider over plain HTTP (typical for
|
||||
local development) needs two additional variables on the `api` service:
|
||||
|
||||
| Variable | Effect |
|
||||
|---|---|
|
||||
| `F451_INSECURE_COOKIES=1` | Drops the `secure` flag on session cookies so they survive over HTTP. |
|
||||
| `F451_OIDC_ALLOW_INSECURE=1` | Allows an `http://` issuer during OIDC discovery. |
|
||||
|
||||
> [!WARNING]
|
||||
> Both are for local HTTP development only. Never set either in
|
||||
> production — a production Entra issuer only ever speaks HTTPS anyway, so
|
||||
> there is nothing to gain and a cookie without `secure` to lose.
|
||||
48
github-sign-in/index.md
Normal file
48
github-sign-in/index.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
id: github-sign-in
|
||||
title: GitHub sign-in
|
||||
description: Enabling GitHub as a sign-in method, independent of or alongside OIDC.
|
||||
tags: [admin, auth, github]
|
||||
lang: en
|
||||
---
|
||||
|
||||
# GitHub sign-in
|
||||
|
||||
GitHub can be enabled as its own sign-in method, separate from the single
|
||||
configured OIDC provider (see [[sign-in-options]]). It works whether or
|
||||
not an OIDC provider is configured at all.
|
||||
|
||||
## Enable it
|
||||
|
||||
| Variable | Effect |
|
||||
|---|---|
|
||||
| `F451_GITHUB_LOGIN` | Set to `1` to turn on "Sign in with GitHub". |
|
||||
| `F451_GITHUB_OAUTH_CLIENT_ID` | Client ID of a GitHub OAuth app. |
|
||||
| `F451_GITHUB_OAUTH_CLIENT_SECRET` | Client secret of the same app. |
|
||||
|
||||
## Register the OAuth app on GitHub
|
||||
|
||||
Under `https://github.com/settings/developers`, create an **OAuth App**
|
||||
with **Authorization callback URL** set to `https://<host>/auth/`. Use
|
||||
exactly that path, not a more specific one — it must cover both
|
||||
`/auth/github/callback` (sign-in) and `/auth/connect/github/callback`
|
||||
(account linking, used when GitHub is only being connected rather than
|
||||
signed in with).
|
||||
|
||||
## Sign-in also links the account
|
||||
|
||||
Signing in with GitHub links the GitHub account in the same step — there
|
||||
is no separate "connect GitHub" action needed afterwards, unlike signing
|
||||
in through OIDC and connecting a Git account separately (see
|
||||
[[sign-in-options]]).
|
||||
|
||||
## One person, two users
|
||||
|
||||
> [!WARNING]
|
||||
> f451 has no concept of "the same person across sign-in methods." Someone
|
||||
> who signs in once via your OIDC provider and once via GitHub becomes
|
||||
> **two** separate f451 users — with separate sessions and separate sets of
|
||||
> connected accounts. This is rarely a problem in practice (most people use
|
||||
> one method consistently), but worth knowing before you enable a second
|
||||
> method for a team that already uses the first: tell people to pick one
|
||||
> method and stick with it, rather than discovering the split themselves.
|
||||
46
index.md
Normal file
46
index.md
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
id: admin-home
|
||||
title: Admin Guide
|
||||
description: Deploying and running f451 — sign-in setup, spaces, configuration, backup, and day-to-day operations.
|
||||
tags: [admin, guide]
|
||||
lang: en
|
||||
---
|
||||
|
||||
# Admin Guide
|
||||
|
||||
f451 is git-native: every space is a repository on Forgejo or GitHub, every
|
||||
page a Markdown file in it. Postgres holds only a derived index (rendered
|
||||
content, search vectors, graph edges) plus sessions and encrypted provider
|
||||
tokens — nothing that lives exclusively in the database is irreplaceable.
|
||||
That single fact shapes most of the operational decisions in this guide,
|
||||
especially backup and restore.
|
||||
|
||||
This guide is for the people who deploy and run an instance, not for people
|
||||
writing pages in it — for that, see the User Guide space.
|
||||
|
||||
## How this guide is organised
|
||||
|
||||
- [[sign-in-options]] — the identity providers f451 supports, and why there
|
||||
are no local accounts
|
||||
- [[entra-id]] — step-by-step setup with Microsoft Entra ID
|
||||
- [[forgejo-identity-provider]] — using the bundled Forgejo as the identity
|
||||
source, and linking accounts in one step
|
||||
- [[github-sign-in]] — enabling GitHub as a sign-in method
|
||||
- [[spaces-and-git-providers]] — configuring spaces, service tokens,
|
||||
webhooks, and the drift job
|
||||
- [[configuration-reference]] — every environment variable, grouped by
|
||||
concern
|
||||
- [[backup-and-restore]] — what actually needs a backup, and what a reindex
|
||||
rebuilds for you
|
||||
- [[operations]] — health checks, troubleshooting, and running two
|
||||
instances on one host
|
||||
|
||||
> [!NOTE]
|
||||
> **f451 has no role system of its own.** Who may sign in is decided by
|
||||
> your identity provider; what a signed-in person can see and write is
|
||||
> decided entirely by their linked Git account's permissions on the
|
||||
> repository behind each space. See [[sign-in-options]].
|
||||
|
||||
If you are setting up sign-in for the first time, start with
|
||||
[[sign-in-options]] to decide which provider fits your setup, then follow
|
||||
the matching page.
|
||||
72
operations/index.md
Normal file
72
operations/index.md
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
---
|
||||
id: operations
|
||||
title: Operations
|
||||
description: Health checks, the admin reindex endpoint, a troubleshooting playbook, and running two instances on one host.
|
||||
tags: [admin, operations, monitoring]
|
||||
lang: en
|
||||
---
|
||||
|
||||
# Operations
|
||||
|
||||
## Health and readiness
|
||||
|
||||
| Endpoint | Meaning |
|
||||
|---|---|
|
||||
| `GET /healthz` | Always `200` if the process is running — no database access. |
|
||||
| `GET /readyz` | `200` if a query against Postgres succeeds, `503` otherwise. Use this for orchestration readiness probes. |
|
||||
| `GET /admin/status` | Bearer-token-protected (`F451_ADMIN_TOKEN`, see [[configuration-reference]]). Returns in-memory counters (`webhookErrors`, `indexerErrors`, `driftErrors`) and a `since` timestamp. The counters reset on every process restart — treat this as "is something wrong right now", not as a historical audit log. |
|
||||
|
||||
## Triggering a reindex
|
||||
|
||||
```bash
|
||||
curl -X POST https://<host>/admin/reindex \
|
||||
-H "Authorization: Bearer $F451_ADMIN_TOKEN" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{}'
|
||||
```
|
||||
|
||||
An empty body reindexes every configured space; `{"space":"<space-id>"}`
|
||||
reindexes just one. The response reports success or failure per space —
|
||||
`200` if at least one space succeeded, `502` only if all of them failed
|
||||
(check `GET /admin/status` and the `api` logs next).
|
||||
|
||||
> [!NOTE]
|
||||
> If OIDC sign-in is active, `/admin/*` routes need a valid session **in
|
||||
> addition to** the bearer token — a plain `curl` call without a browser
|
||||
> session behind it gets a reproducible `401`. Run admin calls from a
|
||||
> browser context where you are already signed in (developer tools'
|
||||
> network/fetch panel with the session cookie present), not from a bare
|
||||
> terminal.
|
||||
|
||||
## Troubleshooting playbook
|
||||
|
||||
| Symptom | Likely cause |
|
||||
|---|---|
|
||||
| Every API route is reachable without signing in | `F451_OIDC_ISSUER` is unset — auth is intentionally off in that state. |
|
||||
| Sign-in redirects to an error page after the identity provider | `F451_OIDC_REDIRECT_URL` (or the app registration's redirect URI) doesn't match the actual callback URL exactly. |
|
||||
| Every save/publish/release fails with `403` | `F451_PUBLIC_BASE_URL` doesn't match the URL users actually browse to — the CSRF origin check rejects the mismatch. See [[configuration-reference]]. |
|
||||
| A webhook call fails with `401` | `F451_WEBHOOK_SECRET_FORGEJO`/`_GITHUB` doesn't match the secret configured on the repository's webhook. |
|
||||
| A page edited directly in Git takes a few minutes to show up | Expected — the drift job catches up within about 5 minutes if the webhook was missed. See [[spaces-and-git-providers]]. |
|
||||
| `POST /admin/reindex` / `GET /admin/status` returns `503` | `F451_ADMIN_TOKEN` is unset — both endpoints are fail-closed without it. |
|
||||
| `POST /admin/reindex` returns `401` from a plain terminal call | Missing session — see the note above. |
|
||||
| The rate limits seem to apply to "everyone at once" instead of per person | `F451_TRUST_PROXY` is unset or wrong for the real proxy chain — see [[configuration-reference]]. |
|
||||
| The same person appears as two different users | They signed in through two different methods (e.g. OIDC once, GitHub once) — see [[github-sign-in]]. Not a bug, a consequence of having no shared identity across methods. |
|
||||
| A user reports "I don't see any spaces" | Their account is signed in but has no linked Forgejo/GitHub account yet, or that account lacks repository access — see [[sign-in-options]]. |
|
||||
|
||||
## Running a second instance on the same host
|
||||
|
||||
Both the Forgejo stack and the application stack expose their ports and
|
||||
cookie naming as variables, so a second instance (for example a demo or a
|
||||
staging copy) can run alongside the first without conflicting:
|
||||
|
||||
| Variable | What it separates |
|
||||
|---|---|
|
||||
| `F451_COOKIE_PREFIX` | Session cookie names — without a distinct value, two instances sharing a host would overwrite each other's cookies in the browser. |
|
||||
| `F451_WEB_PORT` | Host port for the web UI. |
|
||||
| `F451_DRAWIO_PORT` | Host port for the diagram editor. |
|
||||
| `F451_FORGEJO_HTTP_PORT` / `F451_FORGEJO_SSH_PORT` | Host ports for the second Forgejo instance. |
|
||||
| `F451_FORGEJO_ROOT_URL` | The second Forgejo instance's own public URL. |
|
||||
|
||||
Give the second instance's Git stack its own Compose project name
|
||||
(`docker compose -p <name> ...`) so its containers and volumes don't
|
||||
collide with the first instance's.
|
||||
60
sign-in-options/index.md
Normal file
60
sign-in-options/index.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
id: sign-in-options
|
||||
title: Sign-in options
|
||||
description: The identity providers f451 supports, how they compare, and why there are no local accounts.
|
||||
tags: [admin, auth]
|
||||
lang: en
|
||||
---
|
||||
|
||||
# Sign-in options
|
||||
|
||||
f451 never stores a password. Every sign-in goes through an external
|
||||
identity provider, and every permission check after that goes through the
|
||||
Git provider behind the space a person is looking at — see *Principles* in the Developer Guide
|
||||
in the developer guide for why that split exists. This page is about the
|
||||
first half: who is allowed to sign in at all.
|
||||
|
||||
## Why no local accounts
|
||||
|
||||
A local account system would need its own password reset, its own
|
||||
lockout policy, its own audit trail — none of which f451 could do better
|
||||
than the identity provider your organisation already runs and already
|
||||
trusts for offboarding. Instead, f451 delegates entirely: one configured
|
||||
OIDC issuer, optionally GitHub as a second method, and permissions that
|
||||
come from the linked Forgejo or GitHub account rather than from anything
|
||||
f451 tracks itself.
|
||||
|
||||
## Comparison
|
||||
|
||||
| Provider | Use case | What f451 needs | Notes |
|
||||
|---|---|---|---|
|
||||
| **Microsoft Entra ID** | Production, organisation-managed identities | `F451_OIDC_ISSUER`/`_CLIENT_ID`/`_CLIENT_SECRET`/`_REDIRECT_URL`, `F451_TOKEN_KEY` | See [[entra-id]]. Sign-in only — reading/writing still needs a separately connected Forgejo or GitHub account, unless Forgejo itself also authenticates against Entra (see next row). |
|
||||
| **Forgejo (bundled)** | Local development, or production where Forgejo is the single identity source | Same OIDC variables, pointed at Forgejo's built-in OIDC provider | See [[forgejo-identity-provider]]. Can also make the *first* sign-in link the Forgejo account automatically. |
|
||||
| **Other OIDC provider** (Keycloak, Authentik, Zitadel, Okta, Google, …) | Any organisation already standardised on a different IdP | Same OIDC variables, pointed at that provider's issuer | Configuration only — f451 speaks standard OpenID Connect, nothing provider-specific. |
|
||||
| **GitHub** | Teams whose spaces already live on GitHub | `F451_GITHUB_LOGIN=1`, `F451_GITHUB_OAUTH_CLIENT_ID`/`_SECRET` | See [[github-sign-in]]. Works with or without an OIDC provider configured; signing in with GitHub also links the GitHub account in the same step. |
|
||||
|
||||
Only one OIDC issuer can be configured at a time — f451 does not offer a
|
||||
picker between several OIDC providers. GitHub sign-in is independent of
|
||||
that and can be enabled alongside it, or on its own.
|
||||
|
||||
## What sign-in does and does not unlock
|
||||
|
||||
Signing in only authenticates *who someone is*. It does not, by itself,
|
||||
grant access to any space's content:
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Reading and writing follow the linked Git account, not the sign-in
|
||||
> method.** A person who signs in but never connects a Forgejo or GitHub
|
||||
> account sees no spaces at all — not because f451 hides them, but because
|
||||
> there is no permission to check against.
|
||||
|
||||
See [[spaces-and-git-providers]] for how a space is tied to a repository,
|
||||
and the User Guide's *Getting started* page for what connecting an account
|
||||
looks like for the person doing it.
|
||||
|
||||
## One person, several identities
|
||||
|
||||
Because each sign-in method produces its own identity, a person who signs
|
||||
in once through Entra and once through GitHub becomes **two** separate
|
||||
f451 users, each with its own set of connected Git accounts — see
|
||||
[[github-sign-in]] for the practical consequence of that.
|
||||
75
spaces-and-git-providers/index.md
Normal file
75
spaces-and-git-providers/index.md
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
id: spaces-and-git-providers
|
||||
title: Spaces and Git providers
|
||||
description: Configuring which repositories are wiki spaces, service tokens, webhooks, and how the index stays current.
|
||||
tags: [admin, spaces, git]
|
||||
lang: en
|
||||
---
|
||||
|
||||
# Spaces and Git providers
|
||||
|
||||
A space is one repository on Forgejo or GitHub, declared to f451 as one
|
||||
entry in `F451_SPACES` — a JSON array on the `api` service:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "handbook",
|
||||
"name": "Handbook",
|
||||
"provider": "forgejo",
|
||||
"owner": "docs",
|
||||
"repo": "handbook",
|
||||
"defaultLang": "en"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Without `F451_SPACES` set, the API starts in a minimal mode: only
|
||||
`/healthz` and `/readyz` respond, and no space is visible at all.
|
||||
|
||||
## Service tokens are for indexing, not for user access
|
||||
|
||||
Each provider used by at least one space needs a service-account token:
|
||||
|
||||
| Variable | Used for |
|
||||
|---|---|
|
||||
| `F451_FORGEJO_URL` | Base URL of the Forgejo instance (no `/api/v1`). Also the one source for the service-account registry, the write-permission check, and — if Forgejo doubles as identity provider — the OIDC issuer. |
|
||||
| `F451_FORGEJO_TOKEN` | Service-account token Forgejo spaces are indexed with. |
|
||||
| `F451_GITHUB_TOKEN` | Service-account token GitHub spaces are indexed with. |
|
||||
|
||||
> [!NOTE]
|
||||
> These tokens exist purely so the indexer can *read* repository content to
|
||||
> build the search index and page tree. They are never used to write on a
|
||||
> user's behalf — every write is committed with the writer's own linked
|
||||
> provider token (see [[sign-in-options]]). A misconfigured or missing
|
||||
> service token breaks indexing for that provider's spaces, not writing.
|
||||
|
||||
## Webhooks keep the index current
|
||||
|
||||
Configure a webhook in each space's repository pointing at f451, and set a
|
||||
matching secret on the `api` service so f451 can verify it:
|
||||
|
||||
| Variable | Effect |
|
||||
|---|---|
|
||||
| `F451_WEBHOOK_SECRET_FORGEJO` | HMAC secret for Forgejo webhooks. Must match the secret entered when creating the webhook in the Forgejo repository. |
|
||||
| `F451_WEBHOOK_SECRET_GITHUB` | Same, for GitHub webhooks. |
|
||||
|
||||
Without the matching secret set, every webhook signature check fails
|
||||
(`401`) and pushes never trigger an incremental reindex — see
|
||||
[[operations]] for how that shows up and how it self-heals.
|
||||
|
||||
## The drift job is the safety net
|
||||
|
||||
A background job compares each space's current `main` HEAD against the
|
||||
last fully indexed commit every 5 minutes, and triggers a full reindex on
|
||||
a mismatch. This means a webhook that never arrives — a firewall rule, a
|
||||
wrong secret, a Git provider outage — is not a lasting problem: the index
|
||||
catches up on its own within 5 minutes, no manual action required. See
|
||||
[[operations]] for how to observe this happening.
|
||||
|
||||
## Templates across spaces
|
||||
|
||||
`F451_GLOBAL_TEMPLATES` optionally names one more repository
|
||||
(`{"provider","owner","repo"}`, same shape as an `F451_SPACES` entry) that
|
||||
supplies templates available to every space, in addition to a space's own
|
||||
`_templates/*.md`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue