https://github.com/perber/leafwiki
LeafWiki – A fast wiki for people who think in folders, not feeds. Single Go binary. Markdown on disk. No external database service.
https://github.com/perber/leafwiki
docker documentation file-based go knowledge-base markdown react runbooks self-hosted single-binary sqlite wiki
Last synced: 20 days ago
JSON representation
LeafWiki – A fast wiki for people who think in folders, not feeds. Single Go binary. Markdown on disk. No external database service.
- Host: GitHub
- URL: https://github.com/perber/leafwiki
- Owner: perber
- License: mit
- Created: 2025-03-25T21:24:11.000Z (12 months ago)
- Default Branch: main
- Last Pushed: 2026-01-25T01:11:15.000Z (about 2 months ago)
- Last Synced: 2026-01-25T10:57:01.538Z (about 2 months ago)
- Topics: docker, documentation, file-based, go, knowledge-base, markdown, react, runbooks, self-hosted, single-binary, sqlite, wiki
- Language: Go
- Homepage: https://demo.leafwiki.com
- Size: 5.03 MB
- Stars: 49
- Watchers: 1
- Forks: 10
- Open Issues: 39
-
Metadata Files:
- Readme: readme.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Codeowners: CODEOWNERS
Awesome Lists containing this project
README
# 🌿 LeafWiki
**LeafWiki – A fast wiki for people who think in folders, not feeds**
Single Go binary. Markdown on disk. No external database service.
LeafWiki is a lightweight, self-hosted wiki for runbooks, internal docs, and technical notes — built for fast writing and explicit structure.
It keeps your content as plain Markdown on disk and gives you fast navigation, search, and editing — without running additional services.
---
## Live Demo
A public demo of LeafWiki is available here:
🌐 **[demo.leafwiki.com](https://demo.leafwiki.com)**
Try: `Ctrl+E` to edit, `Ctrl+S` to save, `Ctrl+Shift+F` to open the search.
Login credentials are displayed on the demo site.
The demo instance resets automatically every hour, so all changes are temporary.
---
## Preview

---
**Mobile View:**
Mobile-friendly UI for reading (and editing) docs & runbooks on the go.
---
## What LeafWiki is good for today
LeafWiki focuses on personal and small-team documentation use cases today.
Team features will evolve over time, guided by real-world usage.
LeafWiki is currently well-suited for:
- Personal technical notes and documentation
- Project documentation maintained by one main contributor
- Runbooks, operational knowledge and engineering guides for small teams
- Structured content that benefits from explicit hierarchy and ordering
---
## Project Status
LeafWiki is stable for everyday use as a personal or primary-owner wiki.
The core features — writing, navigation, and search — are actively maintained and production-ready.
Collaboration is currently limited and follows a *last-write-wins* approach.
More advanced team-oriented capabilities are under development, with a focus on durability and predictable behavior.
**Current priorities:**
- Versioning
- Importing existing Markdown content
- Conflict handling for concurrent edits (optimistic locking)
Priorities are shaped by real-world usage, and development is iterative.
The platform will evolve cautiously toward team workflows while maintaining its principles of simplicity and low operational overhead.
> **LeafWiki** is actively developed and open to collaboration 🌿
See the [CHANGELOG](CHANGELOG.md) for release details.
---
## Why Another Wiki?
Most wiki tools become operational projects: databases, plugins, workflows, and setup decisions.
LeafWiki was designed around a few simple questions:
- Why require a complex database for Markdown content?
- Why should self-hosting a wiki require significant setup effort?
- Why can’t structure and navigation be handled explicitly while keeping files portable?
In practice, that means:
- Markdown on disk
- Explicit tree structure
- Single-binary or container deployment
- Minimal operational overhead
---
## Core principles
LeafWiki is built around a small set of clear principles:
- **Plain Markdown storage**
All content is stored as Markdown files on disk. This avoids vendor lock-in and keeps your data portable and transparent.
- **No external database required**
LeafWiki uses SQLite internally and does not require running or managing a separate database service.
- **Explicit structure management**
Structure is stored as metadata (JSON/SQLite) while page content stays plain Markdown.
- **Self-hosted by design**
Designed to run on a single server with minimal operational overhead.
---
### Data model
LeafWiki stores page content as Markdown files and uses a combination of JSON and SQLite for navigation, metadata, and search.
For details on the current model and its constraints, see [Known limitations](#known-limitations).
---
## What LeafWiki supports
- **Fast writing flow (editor + shortcuts)**
- **Explicit tree navigation**
- **Public read-only docs with authenticated editing**
- Built-in Markdown editor with live preview
- Brand customization (logo, favicon & site name)
- Full-text search across page titles and content
- Support for diagrams via Mermaid
- Image and asset support
- Dark mode and mobile-friendly UI
- Separation between admin, editor, and viewer users
- Keyboard shortcuts for common actions (like saving with Ctrl+S, ...)
## What LeafWiki is not
- Not a Confluence replacement
- Not real-time collaborative editing
- Not a workflow/approval/document-control platform
LeafWiki is designed to stay small, predictable, and easy to operate.
---
## Installation
LeafWiki is distributed as a single Go binary and can be run directly on the host or via Docker.
The sections below show a recommended quick start and a few common installation examples.
### Quick start
The easiest way to install LeafWiki is using the provided installation script:
```bash
sudo /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/perber/leafwiki/main/install.sh)"
```
This installs LeafWiki as a system service on the target machine.
The service is started automatically after installation.
> The installation script has been tested on Ubuntu.
> Feedback for other distributions is welcome via GitHub issues.
#### Deployment examples
- [Install LeafWiki with nginx on Ubuntu](docs/install/nginx.md)
- [Install LeafWiki on a Raspberry Pi](docs/install/raspberry.md)
#### Security notes
In interactive mode, environment variables appear in plain text in file `/etc/leafwiki/.env`.
Make sure that this file is accessible only to authorized users.
#### Installer script options
**Non-interactive mode**
The script supports non-interactive mode for automated deployments. Use the `--non-interactive` flag and provide configuration via an `.env` file.
An `.env.example` file is included showing all available environment variables. Copy and customize it as needed:
```bash
cp .env.example .env
# Edit .env with your configuration
sudo ./install.sh --non-interactive --env-file ./.env
```
### Docker
You can run LeafWiki as a container using Docker.
```bash
docker run -p 8080:8080 \
-v ~/leafwiki-data:/app/data \
ghcr.io/perber/leafwiki:latest \
--jwt-secret=yoursecret \
--admin-password=yourpassword
```
By default, the container binds to `0.0.0.0` so the wiki is reachable from your network.
The data directory inside the container is `/app/data`.
---
**Running as non-root user**
To avoid running the container as root, specify a user ID:
```bash
docker run -p 8080:8080 \
-u 1000:1000 \
-v ~/leafwiki-data:/app/data \
ghcr.io/perber/leafwiki:latest \
--jwt-secret=yoursecret \
--admin-password=yourpassword
```
Make sure that the mounted data directory is writable by the specified user.
The data directory inside the container will be `/app/data`..
---
### Docker Compose
You can also run LeafWiki using Docker Compose:
```yaml
services:
leafwiki:
image: ghcr.io/perber/leafwiki:latest
container_name: leafwiki
user: 1000:1000 # Run as non-root (specify your {UID}:{GID})
ports:
- "8080:8080"
environment:
- LEAFWIKI_JWT_SECRET=yourSecret
- LEAFWIKI_ADMIN_PASSWORD=yourPassword
volumes:
- ~/leafwiki-data:/app/data
restart: unless-stopped
```
Make sure the mounted data directory (`~/leafwiki-data`) is writable by the user specified in the `user` field.
### Manual installation
Download the latest release binary from GitHub, make it executable, and start the server:
```
chmod +x leafwiki
./leafwiki --jwt-secret=yoursecret --admin-password=yourpassword
```
**Note:** By default, the server listens on `127.0.0.1`, which means it will only be accessible from localhost. If you want to access the server from other machines on your network, add `--host=0.0.0.0` to the command:
```
./leafwiki --jwt-secret=yoursecret --admin-password=yourpassword --host=0.0.0.0
```
Default port is `8080`, and the default data directory is `./data`.
You can change the data directory with the `--data-dir` flag.
The JWT secret is required for authentication and should be kept secure.
## Authentication and admin user
### Reset Admin Password
If you need to reset the admin password, you can do so by running:
```bash
./leafwiki reset-admin-password
```
## Runtime Configuration
LeafWiki can be configured using command-line flags or environment variables.
These options control how the server runs after installation.
### CLI Flags
| Flag | Description | Default | Available since |
|---------------------------------|------------------------------------------------------------------------|---------------|-------------------|
| `--jwt-secret` | Secret used for signing JWTs (required) | – | – |
| `--host` | Host/IP address the server binds to | `127.0.0.1` | – |
| `--port` | Port the server listens on | `8080` | – |
| `--data-dir` | Directory where data is stored | `./data` | – |
| `--admin-password` | Initial admin password *(used only if no admin exists)* (required) | – | – |
| `--public-access` | Allow public read-only access | `false` | – |
| `--hide-link-metadata-section` | Hide link metadata section | `false` | – |
| `--inject-code-in-header` | Raw HTML/JS code injected into tag (e.g., analytics, custom CSS)| `""` | v0.6.0 |
| `--allow-insecure` | ⚠️ Disables Secure & HttpOnly cookies (required for HTTP) | `false` | v0.7.0 |
| `--access-token-timeout` | Access token timeout duration (e.g. 24h, 15m) | `15m` | v0.7.0 |
| `--refresh-token-timeout` | Refresh token timeout duration (e.g. 168h, 7d) | `7d` | v0.7.0 |
| `--disable-auth` | ⚠️ Disable authentication & authorization (internal networks only!) | `false` | v0.7.0 |
> When using the official Docker image, `LEAFWIKI_HOST` defaults to `0.0.0.0` if neither a `--host` flag nor `LEAFWIKI_HOST` is provided, as the container entrypoint sets this automatically.
### Environment Variables
The same configuration options can also be provided via environment variables.
This is especially useful in containerized or production environments.
| Variable | Description | Default | Available since |
|----------------------------------------|-------------------------------------------------------------------------|------------|-----------------|
| `LEAFWIKI_HOST` | Host/IP address the server binds to | `127.0.0.1`| - |
| `LEAFWIKI_PORT` | Port the server listens on | `8080` | - |
| `LEAFWIKI_DATA_DIR` | Path to the data storage directory | `./data` | - |
| `LEAFWIKI_ADMIN_PASSWORD` | Initial admin password *(used only if no admin exists yet)* (required) | – | - |
| `LEAFWIKI_JWT_SECRET` | Secret used to sign JWT tokens *(required)* | – | - |
| `LEAFWIKI_PUBLIC_ACCESS` | Allow public read-only access | `false` | - |
| `LEAFWIKI_HIDE_LINK_METADATA_SECTION` | Hide link metadata section | `false` | - |
| `LEAFWIKI_INJECT_CODE_IN_HEADER` | Raw HTML/JS code injected into tag (e.g., analytics, custom CSS) | `""` | v0.6.0 |
| `LEAFWIKI_ALLOW_INSECURE` | ⚠️ Disables Secure & HttpOnly cookies (required for HTTP) | `false` | v0.7.0 |
| `LEAFWIKI_ACCESS_TOKEN_TIMEOUT` | Access token timeout duration (e.g. 24h, 15m) | `15m` | v0.7.0 |
| `LEAFWIKI_REFRESH_TOKEN_TIMEOUT` | Refresh token timeout duration (e.g. 168h, 7d) | `7d` | v0.7.0 |
| `LEAFWIKI_DISABLE_AUTH` | ⚠️ Disable authentication & authorization (internal networks only!) | `false` | v0.7.0 |
These environment variables override the default values and are especially useful in containerized or production environments.
> When using the official Docker image, `LEAFWIKI_HOST` defaults to `0.0.0.0` if neither a `--host` flag nor `LEAFWIKI_HOST` is provided, as the container entrypoint sets this automatically.
### Security Overview - Since v0.7.0
LeafWiki includes several built-in security mechanisms enabled by default:
- **Secure, HttpOnly cookies** for session handling
- **Session-based authentication** backed by a local database
- **CSRF protection** for all state-changing requests
- **Rate limiting** on authentication-related endpoints
- **Role-based access** (admin, editor, viewer)
These features are **enabled by default** and provide safe defaults for most deployments.
⚠️ Disabling or weakening these protections (e.g. via `--disable-auth` or `--allow-insecure`)
should only be done in **trusted, internal environments**.
---
### ⚠️ Security Warning: `--disable-auth`
> **⚠️ WARNING – USE WITH EXTREME CAUTION**
The `--disable-auth` flag **completely disables authentication and authorization** in LeafWiki.
When enabled:
- **Anyone with network access can edit, delete and modify all content**
- **No login, no roles, no session checks are enforced**
- **All security mechanisms are bypassed**
**This flag MUST NOT be used on public or internet-facing deployments.**
**Intended use cases only:**
- Local development
- Internal networks
- Environments protected by VPN and/or firewall
- Fully isolated test systems
If you use this flag, **you are fully responsible for securing access at the network level**.
**Safe example (local development only):**
```bash
./leafwiki --disable-auth --host=127.0.0.1
```
**For most setups, prefer:**
- Authentication enabled (default)
- `--public-access` for read-only public access
- Viewer role for read-only access
---
## Reconstruct Tree from Filesystem
LeafWiki includes a built-in `reconstruct-tree` command that rebuilds the navigation tree (`tree.json`) by scanning the actual Markdown files and folders on disk.
**Usage:**
```bash
leafwiki [--data-dir ] reconstruct-tree
```
Or if you installed LeafWiki as a binary:
```bash
./leafwiki [--data-dir ] reconstruct-tree
```
**What it does:**
The command:
- Scans the `data/root` directory recursively
- Extracts page titles from Markdown files (from H1 headings or frontmatter)
- Preserves `leafwiki_id` values from frontmatter when present
- Generates new IDs for pages without frontmatter IDs
- Rebuilds the complete navigation tree structure
- Saves the new `tree.json` and updates `schema.json`
**Use cases:**
1. **Recovery from corrupted tree.json**
If your `tree.json` becomes corrupted or deleted, this command reconstructs it from your existing Markdown files.
2. **Manual filesystem changes**
If you've added, moved, or renamed Markdown files directly on disk (outside LeafWiki's UI), run this command to sync the navigation tree.
3. **Migration and import**
When importing existing Markdown content into LeafWiki, use this command to automatically generate the navigation structure.
4. **Tree structure reset**
If the tree structure becomes inconsistent with the filesystem, this provides a clean rebuild based on actual file layout.
**Important notes:**
- ⚠️ This command **replaces the entire tree structure**. Any custom ordering or metadata in `tree.json` will be lost.
- The command creates a **deterministic, alphabetically-sorted** tree based on file and folder names.
- Page content (Markdown files) is never modified—only the navigation structure is rebuilt.
- Frontmatter `leafwiki_id` values are preserved when present, maintaining page identity and internal links.
- For folders (sections), the command looks for `index.md` to extract the section title.
- Files and folders starting with `.` (hidden) are automatically skipped.
**Example:**
```bash
# Default data directory (./data)
leafwiki reconstruct-tree
# Custom data directory
leafwiki --data-dir /path/to/data reconstruct-tree
```
**Before running this command:**
- Ensure your data directory exists and contains a `root` folder with your Markdown content
- Consider backing up your current `tree.json` if you need to preserve custom ordering
- The server does not need to be running—this is a standalone command
---
## Import Feature
LeafWiki includes a built-in Markdown Importer that allows you to import existing Markdown files and folders into the wiki structure.
The importer is available as admin in the UI and can be used to quickly bring existing documentation into LeafWiki.
At the moment the importer does not support all features of the wiki (e.g. metadata, backlinks, assets, ...) but it provides a fast way to get started with existing Markdown content.
Please open an issue if you have specific feature requests or feedback for the importer.
---
## Quick Start (Dev)
```
# 1. Clone the repo
git clone https://github.com/perber/leafwiki.git
cd leafwiki
# 2. Install frontend dependencies
cd ui/leafwiki-ui
npm install
npm run dev # Starts Vite dev server on http://localhost:5173
# 3. In another terminal, start the backend
cd ../../cmd/leafwiki
go run main.go --jwt-secret=yoursecret --public-access=true --allow-insecure=true --admin-password=yourpassword
# Note: The backend binds to 127.0.0.1 by default for security.
# If you need to access it from a different machine or network interface
# (e.g., testing on mobile or from another device), use:
# go run main.go --host=0.0.0.0
```
---
### Keyboard Shortcuts
| Action | Shortcut |
|----------------------------|--------------------------------------------|
| Switch to Edit Mode | `Ctrl + E` (or `Cmd + E`) |
| Switch to Search Pane | `Ctrl + Shift + F` (or `Cmd + Shift + F`) |
| Switch to Navigation Pane | `Ctrl + Shift + E` (or `Cmd + Shift + E`) |
| Save Page | `Ctrl + S` (or `Cmd + S`) |
| Bold Text | `Ctrl + B` (or `Cmd + B`) |
| Italic Text | `Ctrl + I` (or `Cmd + I`) |
| Headline 1 | `Ctrl + Alt + 1` (or `Cmd + Alt + 1`) |
| Headline 2 | `Ctrl + Alt + 2` (or `Cmd + Alt + 2`) |
| Headline 3 | `Ctrl + Alt + 3` (or `Cmd + Alt + 3`) |
`Ctrl+V` / `Cmd+V` for pasting images or files is also supported in the editor.
`Esc` can be used to exit modals, dialogs or the edit mode.
More shortcuts may be added in future releases.
---
## Known limitations
LeafWiki focuses on simplicity with a well-defined scope.
As a result, the following limitations apply today:
- **No built-in page history or versioning**
Saving changes overwrites the previous state. Versioning is a planned feature.
- **Basic concurrency handling**
Edits follow a last-write-wins model. Best suited for single maintainers or low-concurrency use.
- **Metadata not fully embedded in Markdown**
Page content is plain Markdown, but structure, metadata, user accounts, and search indexes are stored in SQLite.
- **Minimal access control**
No role-based permissions or fine-grained restrictions at this time.
---
### Available Builds
LeafWiki is available as a native binary for the following platforms:
- **Linux (x86_64 and ARM64)**
- **macOS (x86_64 and ARM64)**
- **Windows (x86_64)**
- **Raspberry Pi (tested with 64-bit OS)**
---
## Contributing
Contributions, discussions, and feedback are very welcome.
If you have ideas, questions, or run into issues, feel free to open an issue or start a discussion.
## Stay in the loop
Follow the repository to get updates about new releases and ongoing development.