Update README and INSTALL with LDAP, collab, and all features
This commit is contained in:
@@ -50,6 +50,14 @@ Open `http://your-host:8080` and log in with the admin credentials above.
|
|||||||
| `MH_LDAP_USER_FILTER` | No | `(&(objectClass=inetOrgPerson)(uid=%s))` | LDAP search filter (`%s` = username) |
|
| `MH_LDAP_USER_FILTER` | No | `(&(objectClass=inetOrgPerson)(uid=%s))` | LDAP search filter (`%s` = username) |
|
||||||
| `MH_LDAP_SKIP_TLS` | No | `false` | Skip TLS verification (for self-signed certs) |
|
| `MH_LDAP_SKIP_TLS` | No | `false` | Skip TLS verification (for self-signed certs) |
|
||||||
|
|
||||||
|
### LDAP Notes
|
||||||
|
|
||||||
|
- Use `ldaps://host:636` for SLDAP (LDAP over TLS)
|
||||||
|
- LDAP settings can also be configured from the **Admin panel** (⚙️ → 👤) without restarting
|
||||||
|
- If a required group is set, only users who are members of that group can log in
|
||||||
|
- On first LDAP login, a local user is auto-created (for preferences, file storage, etc.)
|
||||||
|
- Local accounts still work alongside LDAP — local auth is tried first
|
||||||
|
|
||||||
## Data Volume
|
## Data Volume
|
||||||
|
|
||||||
Mount a persistent volume to `/app/data`. This contains:
|
Mount a persistent volume to `/app/data`. This contains:
|
||||||
|
|||||||
@@ -4,50 +4,41 @@ Self-hosted collaborative markdown workspace with real-time editing, Git integra
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Three editor modes**: WYSIWYG (Milkdown), raw markdown (CodeMirror-style), and split-pane with live preview
|
- **Three editor modes**: WYSIWYG (Milkdown), raw markdown, and split-pane with live preview
|
||||||
- **File management**: Tree-based file browser, folders, search, create/delete
|
- **File management**: Tree-based file browser, folders, search, drag-and-drop, rename, trash
|
||||||
- **Git versioning**: Auto-commit on save, full history, diff viewer, restore previous versions
|
- **Git versioning**: Auto-commit on save, full history, diff viewer, restore previous versions
|
||||||
- **External Git sync**: Per-user remotes (Gitea, GitHub, etc.), push/pull on demand
|
- **External Git sync**: Per-user remotes (Gitea, GitHub, etc.), push/pull on demand
|
||||||
|
- **Real-time collaboration**: Yjs CRDT via WebSocket — multiple users editing simultaneously
|
||||||
- **Sharing**: Share files/folders with other users (read-only or read-write)
|
- **Sharing**: Share files/folders with other users (read-only or read-write)
|
||||||
- **AI integration**: Verify specs, generate prompts, summarize — via LiteLLM/vLLM
|
- **AI integration**: Verify specs, generate prompts, summarize — via LiteLLM/vLLM
|
||||||
- **AI Build Pipeline**: Write a spec → verify → build entire project → push to Gitea
|
- **AI Build Pipeline**: Write a spec → verify → build entire project → push to Gitea
|
||||||
- **2FA**: TOTP-based two-factor authentication
|
- **Authentication**: Local accounts, LDAP/SLDAP, TOTP 2FA, group-based access control
|
||||||
- **Light/Dark theme**: Toggle in UI, persisted in preferences
|
- **Light/Dark theme**: Toggle in UI, persisted in preferences
|
||||||
- **Export**: PDF, HTML, raw markdown download
|
- **Export**: PDF, HTML, raw markdown download
|
||||||
- **Offline-ready**: PWA architecture (planned)
|
- **Image upload**: Drag-drop images into the editor
|
||||||
- **Multi-device**: Responsive, works on desktop and iPad
|
- **PWA / Offline**: Service worker, IndexedDB caching, sync on reconnect
|
||||||
|
- **Multi-device**: Responsive with mobile hamburger menu
|
||||||
- **Docker deployment**: Single container, easy backup
|
- **Docker deployment**: Single container, easy backup
|
||||||
|
- **Admin panel**: User management, LDAP configuration (no restart needed)
|
||||||
|
- **Security**: Rate limiting, encrypted tokens, audit log, password complexity
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
### Docker (recommended)
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
git clone https://git.aholck.net/anders-pub/markdown-hub.git
|
||||||
|
cd markdown-hub
|
||||||
docker build -t markdownhub .
|
docker build -t markdownhub .
|
||||||
docker run -d --name markdownhub \
|
docker run -d --name markdownhub \
|
||||||
|
--restart unless-stopped \
|
||||||
-p 8080:8080 \
|
-p 8080:8080 \
|
||||||
-v ./data:/app/data \
|
-v ./data:/app/data \
|
||||||
-e MH_SECRET=your-random-secret \
|
-e MH_SECRET="$(openssl rand -hex 32)" \
|
||||||
markdownhub
|
markdownhub
|
||||||
```
|
```
|
||||||
|
|
||||||
Default admin: `admin@localhost` / `admin`
|
Default admin: `admin@localhost` / `admin` — **change password immediately**.
|
||||||
|
|
||||||
### Development
|
See [INSTALL.md](INSTALL.md) for full deployment guide.
|
||||||
|
|
||||||
**Backend:**
|
|
||||||
```bash
|
|
||||||
go run ./cmd/server
|
|
||||||
```
|
|
||||||
|
|
||||||
**Frontend:**
|
|
||||||
```bash
|
|
||||||
cd frontend
|
|
||||||
npm install
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
Frontend dev server proxies API calls to `localhost:8080`.
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
@@ -63,6 +54,15 @@ Environment variables:
|
|||||||
| `MH_AI_ENDPOINT` | — | LiteLLM-compatible API URL |
|
| `MH_AI_ENDPOINT` | — | LiteLLM-compatible API URL |
|
||||||
| `MH_AI_API_KEY` | — | API key for AI endpoint |
|
| `MH_AI_API_KEY` | — | API key for AI endpoint |
|
||||||
| `MH_AI_MODEL` | `gpt-4` | Default model for AI features |
|
| `MH_AI_MODEL` | `gpt-4` | Default model for AI features |
|
||||||
|
| `MH_LDAP_URL` | — | LDAP server (`ldap://` or `ldaps://`) |
|
||||||
|
| `MH_LDAP_BIND_DN` | — | Service account DN |
|
||||||
|
| `MH_LDAP_BIND_PASS` | — | Service account password |
|
||||||
|
| `MH_LDAP_BASE_DN` | — | Base DN for user search |
|
||||||
|
| `MH_LDAP_USER_FILTER` | `(&(objectClass=inetOrgPerson)(uid=%s))` | User search filter |
|
||||||
|
| `MH_LDAP_GROUP_FILTER` | — | Required group DN for login |
|
||||||
|
| `MH_LDAP_SKIP_TLS` | `false` | Skip TLS verification |
|
||||||
|
|
||||||
|
LDAP settings can also be configured from the **Admin panel** (no restart needed).
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
@@ -72,6 +72,7 @@ Environment variables:
|
|||||||
│ (Vue 3) │◀────│ (net/http) │ └────────┘
|
│ (Vue 3) │◀────│ (net/http) │ └────────┘
|
||||||
└─────────────┘ │ │────▶ Filesystem (.md files)
|
└─────────────┘ │ │────▶ Filesystem (.md files)
|
||||||
│ │────▶ Git (per-user repos)
|
│ │────▶ Git (per-user repos)
|
||||||
|
│ │◀───▶ LDAP (optional)
|
||||||
└──────────────┘
|
└──────────────┘
|
||||||
│
|
│
|
||||||
┌──────▼───────┐ ┌────────┐
|
┌──────▼───────┐ ┌────────┐
|
||||||
@@ -80,50 +81,55 @@ Environment variables:
|
|||||||
└──────────────┘
|
└──────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Backend**: Go, stdlib `net/http`, SQLite (pure Go via modernc.org/sqlite)
|
- **Backend**: Go 1.23, stdlib `net/http`, SQLite (modernc.org/sqlite), gorilla/websocket
|
||||||
- **Frontend**: Vue 3, Vite, Milkdown, CodeMirror 6, marked
|
- **Frontend**: Vue 3, Vite, Milkdown, marked, Yjs
|
||||||
- **Auth**: JWT + bcrypt + TOTP
|
- **Auth**: JWT + bcrypt + TOTP + LDAP/SLDAP
|
||||||
- **Git**: Shell-based git operations (auto-commit, remotes, push/pull)
|
- **Git**: Shell-based git operations (auto-commit, remotes, push/pull)
|
||||||
- **AI**: LiteLLM-compatible OpenAI API calls
|
- **AI**: LiteLLM-compatible OpenAI API calls
|
||||||
- **Build Daemon**: Python (stdlib only), polls for build jobs, runs Pi coding agent
|
- **Build Daemon**: Python (stdlib only), polls for build jobs
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
cmd/server/ — Web server entry point
|
cmd/server/ — Web server entry point
|
||||||
cmd/mdsync/ — CLI sync tool (planned)
|
cmd/mdsync/ — CLI sync tool
|
||||||
internal/api/ — HTTP handlers & routing
|
internal/api/ — HTTP handlers & routing
|
||||||
internal/auth/ — JWT, bcrypt, TOTP
|
internal/auth/ — JWT, bcrypt, TOTP, LDAP
|
||||||
internal/db/ — SQLite schema & connection
|
internal/collab/ — Real-time collaboration (Yjs WebSocket hub)
|
||||||
|
internal/db/ — SQLite schema & migrations
|
||||||
internal/files/ — File CRUD & search
|
internal/files/ — File CRUD & search
|
||||||
internal/git/ — Git operations
|
internal/git/ — Git operations
|
||||||
internal/crypto/ — AES-256-GCM encryption (for private vault)
|
internal/crypto/ — AES-256-GCM encryption
|
||||||
daemon/ — Build daemon (Python)
|
daemon/ — Build daemon (Python)
|
||||||
frontend/ — Vue 3 SPA
|
frontend/ — Vue 3 SPA
|
||||||
```
|
```
|
||||||
|
|
||||||
## Build Daemon
|
## CLI Tool
|
||||||
|
|
||||||
The build daemon runs on a separate Linux machine and processes AI build jobs:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export MH_URL=http://your-markdownhub:8080
|
go build -o mdsync ./cmd/mdsync
|
||||||
export MH_DAEMON_TOKEN=your-token
|
mdsync login https://md.example.com you@example.com password
|
||||||
export MH_WORKSPACE=~/builds
|
mdsync pull .
|
||||||
python3 daemon/build_daemon.py
|
mdsync push .
|
||||||
|
mdsync status
|
||||||
```
|
```
|
||||||
|
|
||||||
It polls MarkdownHub for pending jobs, creates Gitea repos, runs the Pi coding agent, and pushes results.
|
|
||||||
|
|
||||||
## Backup & Restore
|
## Backup & Restore
|
||||||
|
|
||||||
All data lives in the `data/` volume:
|
All data lives in the `data/` volume:
|
||||||
- `data/db/markdownhub.db` — SQLite database
|
- `data/db/markdownhub.db` — SQLite database
|
||||||
- `data/files/{user_id}/` — User markdown files (also git repos)
|
- `data/files/{user_id}/` — User markdown files (also git repos)
|
||||||
|
|
||||||
**Backup**: Copy the `data/` directory.
|
```bash
|
||||||
**Restore**: Stop container, replace `data/`, start container.
|
# Backup
|
||||||
|
cp -r ./data ./backup-$(date +%Y%m%d)
|
||||||
|
|
||||||
|
# Restore
|
||||||
|
docker stop markdownhub
|
||||||
|
rm -rf ./data && cp -r ./backup-YYYYMMDD ./data
|
||||||
|
docker start markdownhub
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT
|
MIT — Anders Holck 2026
|
||||||
|
|||||||
Reference in New Issue
Block a user