Skip to content

Run the web editor

The web editor is an optional service on its own host. It signs authors in with GitHub or your company's identity provider, and commits for them through your GitHub App.

  • A running OpenD server, with the docs repository registered and the GitHub App installed on it (installationId set). Connect GitHub in the admin console does both (Connect GitHub from the admin console); the manual route is Connect GitHub: webhooks and the GitHub App.
  • A host name for the editor that is not the docs site's, such as edit.docs.example.com. Cookies ignore ports, so in production a different port on the same host is refused.
  1. Give the GitHub App the permissions the editor needs, and accept the change on the installation.
    Repository permissionAccessFor
    ContentsRead and writeReading files, saving commits, merging the main branch in
    Pull requestsRead and writeOpening, updating and merging pull requests
    AdministrationReadReading branch protection and rulesets
    Commit statusesRead (keep Read and write for build statuses)Showing required checks
    ChecksReadShowing required checks
    MetadataReadChecking a developer's permission on the repository

    Without Administration read the editor still works, but it cannot see the review rules, so it never merges by itself: a maintainer merges each pull request on GitHub.

  2. Set up at least one way to sign in.
    • GitHub, for developers: create an OAuth app (or use the GitHub App's own client id and secret) with the callback URL $EDITOR_PUBLIC_URL/auth/github/callback. Anyone with write, maintain or admin permission on the docs repository gets an account the first time they sign in.
    • Company OIDC, for other authors: register a client with your identity provider, with the redirect URI $EDITOR_PUBLIC_URL/auth/oidc/callback. It can be the same provider as reader sign-in, but use a separate client. These authors must be added before they can sign in.
  3. Set the editor's variables.

    The editor reads its own settings and checks them all at start-up. It shares DATABASE_URL with the other services, and with it everything the admin console stores: once GitHub is connected there, the editor uses the same GitHub App for commits and author sign-in without variables of its own. With only SESSION_SECRET it derives a cookie key of its own, so it never signs cookies with the docs site's key.

    The smallest set, with GitHub connected in the admin console: DATABASE_URL, SESSION_SECRET (the docs site's value), EDITOR_PUBLIC_URL and PUBLIC_URL.

    VariableDefaultMeaning and rules
    DATABASE_URLrequiredThe same Postgres database as the docs site.
    EDITOR_PUBLIC_URLrequiredWhere authors reach the editor. Must not share a host with PUBLIC_URL; in production the host names must differ.
    SESSION_SECRETsee the meaningThe docs site's value. The editor derives its own cookie key from it under a separate label (so the two never share a key), and opens the settings and secrets the admin console stored with it. Set this or EDITOR_SESSION_SECRET.
    EDITOR_SESSION_SECRETderived from SESSION_SECRETSigns the editor's session cookie instead of the derived key. At least 32 characters, and not the docs site's SESSION_SECRET.
    OPEND_SECRET_KEYnoneThe docs site's value, when it sets one: the key stored secrets are sealed with. Without it the key comes from SESSION_SECRET.
    GITHUB_APP_IDthe connected appThe GitHub App that commits and opens pull requests. Without it, the editor uses the app connected in the admin console (Integrations > GitHub) or the token broker. Set together with GITHUB_APP_PRIVATE_KEY.
    GITHUB_APP_PRIVATE_KEYthe connected appThe App's private key, as for the worker.
    OPEND_GITHUB_BROKER_URLnoneManaged hosting: the control plane's token broker. The editor asks it for write tokens. Set by the hosting provider, together with OPEND_GITHUB_BROKER_SECRET.
    OPEND_GITHUB_BROKER_SECRETnoneThis instance's bearer token for the broker.
    GITHUB_OAUTH_CLIENT_IDthe connected app'sTurns on GitHub sign-in. Without it, the client id of the app connected in the admin console is used. Set together with GITHUB_OAUTH_CLIENT_SECRET.
    GITHUB_OAUTH_CLIENT_SECRETnoneThe OAuth client secret.
    EDITOR_OIDC_ISSUERnoneTurns on company sign-in. Needs EDITOR_OIDC_CLIENT_ID and EDITOR_OIDC_CLIENT_SECRET. Managed hosting sets all three to its own sign-in service.
    EDITOR_OIDC_CLIENT_IDnoneThe editor's OIDC client id.
    EDITOR_OIDC_CLIENT_SECRETnoneThe editor's OIDC client secret.
    EDITOR_OIDC_SCOPESopenid email profileScopes to request.
    EDITOR_REPOOPEND_SITE_REPOThe registered repository to edit, such as acme/docs. Not needed when only one is registered.
    OPEND_SITE_REPOnoneUsed when EDITOR_REPO is unset.
    EDITOR_BASE_BRANCHmainThe branch authors' work is based on and published to.
    PUBLIC_URLnoneThe docs site, if set: the editor refuses to start on the same host.
    PORT3001Port to listen on. The image sets 3000.
    HOST0.0.0.0Interface to listen on.
    GITHUB_API_URLhttps://api.github.comFor GitHub Enterprise Server.
    GITHUB_WEB_URLhttps://github.comWhere GitHub sign-in sends authors, for GitHub Enterprise Server.
    NODE_ENVdevelopmentSet production for real use.
  4. Start the editor.
    • Docker Compose: docker compose -f deploy/docker-compose.yml --profile editor up -d starts the editor service on port 3001 (or OPEND_EDITOR_PORT). Put it behind your reverse proxy on its own host name.
    • Railway: add a third service, editor, from the same repository and deploy/Dockerfile, with the start command node dist/bin.js editor serve, the health check /healthz and its own public domain on port 3000. It needs no pre-deploy step: the web service runs the migrations. See Run OpenD on Railway.
    • Anywhere else: run opend-server editor serve from the image.
  5. Add the authors who sign in with their company account.
    opend-server editor add-user writer@example.com --name "Wendy Writer"
    opend-server editor add-user dev@example.com --github dev-login
    opend-server editor list-users
    opend-server editor disable-user writer@example.com

    These commands need only DATABASE_URL. With Compose, run them as docker compose -f deploy/docker-compose.yml run --rm migrate editor add-user ….

    • add-user registers an email address, with the name used on commits. --github also lets that GitHub account in, for developers without write access. Adding a disabled editor again turns them back on.
    • Company accounts are matched by verified email at first sign-in, then by the provider's subject.
    • disable-user stops someone signing in and ends their sessions at once.

Authors sign in at EDITOR_PUBLIC_URL. See Edit docs in the browser for what they can do.

  • Edit this page. Set EDITOR_PUBLIC_URL on the docs site too, and signed-in staff readers see Edit this page under each topic, opening /edit?path=topic file in the editor. The editor still asks them to sign in as an author. One GitHub App can serve both hosts; see One GitHub App for the site, the editor and builds.
  • Separate accounts. Editors are not readers. A reader session never opens the editor, and an editor session grants nothing on the docs site.
  • Commits. Each save is a commit to the author's branch editor/<user-id>/<name>. Authors who signed in with GitHub commit as themselves: the editor keeps their GitHub user access token, sealed with the same key as the admin console's secrets, and GitHub signs their commits (Verified). Other authors' commits are made by the App, with the author's name and email and a Co-authored-by line. The editor refuses to write to any other branch, including the main branch.
  • Requiring signed commits. If branch protection or a ruleset requires signed commits on the base branch or on editor/**, only authors who signed in with GitHub can save and publish; authors who use company sign-in are asked to sign in with GitHub. For that, GitHub sign-in must use a GitHub App's client id and secret (the app connected in the admin console, or a GITHUB_OAUTH_CLIENT_ID starting with Iv): an OAuth app's tokens are never kept. A secret key is needed too (SESSION_SECRET or OPEND_SECRET_KEY), and the App needs Administration read so the editor can see the rule. Managed hosting signs authors in with OIDC, which carries no GitHub token, so those authors cannot save to such repositories. Tokens are kept per session, refreshed before they expire, and deleted on sign-out and by disable-user.
  • Preview as an org. Any signed-in editor can preview their branch as an org that has entitlements. Each preview is tied to that editor, one commit and the org's entitlements at that moment, expires after 30 minutes, and is logged. There are no editor roles yet.
  • Audit. Every sign-in, save, merge from the main branch, conflict resolution, publish, merge, request for a developer and preview is recorded in the editor_audit table, with the session, user, commit and pull request. Each author sees their own on the Activity page.
  • Large repositories. The preview rebuilds the whole docs project in memory. That suits hundreds of topics; a repository too large for GitHub's recursive tree listing is refused.