Skip to content
SumGuy's Ramblings
Go back

Wiki.js with GitSync: Documentation That Lives in Version Control Like It Should

Documentation Stored Only in a Database Is a Single Point of Failure

If your wiki lives entirely in a database with no export, no backup strategy, and no version history beyond “last edited by someone three months ago,” that’s not documentation — it’s a liability. A drive failure, a botched upgrade, or an accidental delete wipes it. No history, no rollback, no “who changed this and when.”

Wiki.js’s GitSync feature fixes this by syncing your wiki content to a Git repository. Your documentation becomes flat Markdown files in a repo. You get:

It’s docs-as-code, and it changes how you think about documentation.

Architecture: Push vs Pull Sync

Wiki.js GitSync works in two directions:

Pull (Git → Wiki): The wiki periodically fetches from the repo. Changes committed to the repo show up in the wiki after the sync interval. Useful if your source of truth is the repo and the wiki is just a reader.

Push (Wiki → Git): Changes made in the wiki editor get committed to the repo. The wiki is the editing interface, git is the backup.

Two-way sync: Both. Changes in the wiki push to git; changes in git pull to the wiki. This is the most flexible but requires careful merge conflict handling.

For most self-hosters: start with two-way sync and switch to push-only if you start doing a lot of direct repo edits.

Setting Up Wiki.js with Docker Compose

# docker-compose.yml
version: '3'
services:
  wiki:
    image: ghcr.io/requarks/wiki:2
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      DB_TYPE: postgres
      DB_HOST: db
      DB_PORT: 5432
      DB_NAME: wiki
      DB_USER: wikijs
      DB_PASS: supersecret
    depends_on:
      - db
    volumes:
      - wiki-data:/wiki/data

  db:
    image: postgres:15-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: wiki
      POSTGRES_USER: wikijs
      POSTGRES_PASSWORD: supersecret
    volumes:
      - postgres-data:/var/lib/postgresql/data

volumes:
  wiki-data:
  postgres-data:
docker compose up -d
# Access at http://localhost:3000
# Complete the setup wizard — set admin email/password

Configuring GitSync in the Wiki.js Admin Panel

Navigate to Administration → Storage → Git.

For GitHub:

# Create a Personal Access Token in GitHub
# Settings → Developer settings → Personal access tokens → Fine-grained tokens
# Permissions: Contents (Read and Write), Metadata (Read)

# In Wiki.js Git storage:
Authentication Type: SSH (recommended) or Basic Auth (Personal Access Token)
Repository URL: https://github.com/yourusername/wiki-docs.git
  # Or SSH: git@github.com:yourusername/wiki-docs.git
Branch: main
SSH Private Key: (paste your private key)
Username: yourusername (for HTTPS)
Password/Token: your_PAT_token (for HTTPS)

For Gitea (self-hosted):

Repository URL: https://gitea.internal/youruser/wiki-docs.git
  # Or SSH: git@gitea.internal:youruser/wiki-docs.git
Branch: main
Username: youruser
Password/Token: your_gitea_token

Generate a dedicated deploy key for SSH auth:

ssh-keygen -t ed25519 -C "wikijs-sync" -f ~/.ssh/wikijs_deploy -N ""
# Add the public key to your repo's deploy keys (with write access)
# Paste the private key into Wiki.js

Sync Settings

# Sync interval: how often Wiki.js polls for changes
Sync interval: 5 minutes (300 seconds)

# Sync direction:
- "Push to remote source" — wiki → git
- "Pull from remote source" — git → wiki  
- "Sync bidirectionally" — both

# For the sync to work on first setup:
# Initialize the repo with at least one commit first

After saving, click “Sync Now” to test the connection.

Branch Strategy for Docs Workflows

Simple: Single Branch

Everyone edits in the wiki, changes push to main. Simple, works fine for small teams.

Wiki (editing) → Git main ← direct commits

PR Workflow: Main + Draft

Use Wiki.js to edit on a draft branch. When ready, create a PR from draftmain for review.

# In your git repo
git checkout -b draft
git push origin draft

# Configure Wiki.js GitSync to use the "draft" branch
# Set up a CI job to merge draft → main on approval

This is particularly useful for public-facing documentation where you want someone to review before publishing.

Per-Section Branches

For large teams: different sections of the wiki live on different branches. The main branch holds stable docs; contributors branch per-topic.

This gets complex fast. Only do it if you have a team that already understands the overhead.

Handling Merge Conflicts

Two-way sync can produce conflicts if the same page is edited in the wiki and in the repo simultaneously.

Wiki.js handles this with a last-write-wins strategy by default — which is fine for single-editor setups, problematic for teams.

To avoid conflicts:

  1. Enforce a single source of truth: Either edit in the wiki or in the repo, not both simultaneously
  2. Use short sync intervals (every 1-2 minutes) to reduce the conflict window
  3. Use webhooks to trigger immediate syncs when the repo changes

Configure a GitHub/Gitea webhook to trigger an immediate Wiki.js sync:

# In Wiki.js, the sync endpoint is:
# POST http://your-wiki:3000/admin/storage/sync

# In GitHub/Gitea webhook settings:
Payload URL: http://your-wiki:3000/admin/storage/sync
Content type: application/json
Trigger: Push events

This way, a commit to the repo immediately syncs to the wiki rather than waiting for the polling interval.

CI/CD Integration: Automated Doc Updates

The real power of GitSync: your CI/CD pipeline can update documentation automatically.

# .github/workflows/update-docs.yml
name: Update API Docs

on:
  push:
    branches: [main]
    paths: ['openapi.yaml', 'src/**']

jobs:
  update-docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          repository: yourusername/wiki-docs
          token: ${{ secrets.WIKI_DEPLOY_TOKEN }}

      - name: Generate API docs
        run: |
          pip install openapi-to-markdown
          openapi-to-markdown openapi.yaml > api-reference.md

      - name: Commit updated docs
        run: |
          git config user.name "CI Bot"
          git config user.email "ci@example.com"
          git add api-reference.md
          git diff --staged --quiet || git commit -m "Update API docs from OpenAPI spec"
          git push

When this CI job runs, it updates the Markdown in the repo, which syncs to the wiki within your polling interval (or immediately via webhook). Your API docs stay in sync with your code automatically.

Markdown vs Visual Editor Mode

Wiki.js supports two editing modes:

Markdown editor: Edit raw Markdown directly. Better if you’re comfortable with Markdown, want consistent formatting, and plan to do a lot of repo-side editing.

Visual (WYSIWYG) editor: Richer formatting, more accessible for non-technical team members. The visual editor saves as Markdown under the hood, but the output can be slightly more verbose.

You can set the default editor per page type. For technical documentation, set Markdown as default. For HR policies or onboarding docs that non-engineers edit, the visual editor reduces friction.

Wiki.js vs MkDocs vs Jekyll

For “should I use Wiki.js with GitSync or just use a static site generator?”

FeatureWiki.js + GitSyncMkDocs/Jekyll
Web editing interfaceYesNo (need to commit)
Git-backedYes (via sync)Native
SearchBuilt-in (fast)Requires plugin
Access controlPer-page permissionsStatic = public or nothing
Setup complexityMediumLow
DeploymentDocker + databaseAny static host
Comments/discussionBuilt-inExternal service

Choose Wiki.js + GitSync when: you want an editing interface for non-engineers, need per-page access control, or want comments and collaboration features.

Choose MkDocs/Jekyll when: all editors are comfortable with git, you want zero infrastructure (GitHub Pages hosting), or your docs are public and you want full CI/CD control.

Access Control in Wiki.js

Wiki.js has granular permission controls. Combined with GitSync, you can have:

Public readers: can view /docs/public/*
Editors: can edit /docs/internal/*
Admins: can edit everything, manage users

Configure in Administration → Groups:

  1. Create groups: Viewers, Editors, Admins
  2. Assign page rules: path prefix, allowed actions (read/write/manage)
  3. Assign users to groups
  4. Configure guest access (anonymous read) separately

For a documentation site where you want public content and private internal docs on the same wiki, set up two sections with different group permissions. Works well, and it’s all backed by the same git repo.

The Practical Setup Checklist

  1. Stand up Wiki.js + Postgres via Docker Compose
  2. Create a dedicated Git repo for wiki content (empty is fine)
  3. Generate an SSH deploy key, add public key to repo
  4. Configure GitSync: two-way sync, 5-minute interval, your repo URL
  5. Click “Sync Now” — verify it commits a test page
  6. Set up a webhook for immediate sync on push
  7. Configure CI/CD job to auto-update generated docs
  8. Set up access groups before inviting team members

The first sync takes a minute. After that, every page change in the wiki shows up in the repo within minutes, and every commit to the repo shows up in the wiki. Your documentation is now version-controlled, backed up, and accessible from both a nice web interface and your terminal.

That’s what documentation infrastructure should look like.


Share this post on:

Previous Post
Proxmox vs XCP-ng: Hypervisors for People Who Like Their Data Center at Home
Next Post
Docker Compose vs Docker Swarm: When "Good Enough" Beats "Enterprise"