正在确认登录状态。
Open-source, self-hosted IT documentation for MSPs — servers, network, credentials & licenses in one searchable place.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Deutsch · English
Central, multi-tenant documentation of a customer's entire IT — from sites through servers, network and Active Directory to licences and credentials. With a guided initial survey, PDF export, global search across every customer, and devices that document themselves through an agent.
Sign in as admin, techniker, kunde-rw or kunde-r — the password is password for all four
Each role sees something different. Change anything you like; the demo resets every hour.
MSPs lose time to scattered spreadsheets, stale wikis and “where did we write that down?”. DokuVault keeps it all in one place — structured, searchable, encrypted and current.
| 🏢 Multi-tenant | Every customer with their own sites, devices and credentials, cleanly separated |
| 🧭 Initial survey wizard | 16 steps through a new customer — ask, save the answer, next |
| 🔌 Patch panels | Outlet number, room and target switch per port — “where does outlet A.12 go?” |
| 🔎 Global search | Find a server, IP, serial number or MAC across all customers in seconds |
| 🤖 Auto-documentation | Installed agents for Windows, Proxmox and Linux report on their own — roles, interval and “report now” are set in DokuVault. Plus scripts for Hyper-V, VMware, UniFi and Microsoft 365 |
| 💾 Backup monitoring | Veeam, Windows Server Backup and Proxmox jobs report every run — the last runs at a glance, failures on the dashboard |
| 📊 Statistics | API load, data growth, agent health, usage and system resources — to see when the server needs more power |
| 🌐 IPAM | Used, free and reserved IP addresses per VLAN at a glance, DHCP and gateway detection |
| 🔐 Encrypted | Every password stored encrypted, role-based access, audit log |
| 📄 PDF export | Complete customer documentation as a PDF at the push of a button |
| 🌙 Light & dark | Modern, responsive UI — on the phone too |
| 🌍 German & English | Switchable per user, or following the browser |
| ⏰ Expiry warnings | Licences, certificates and domains never expire unnoticed |
| ♻️ Recycle bin | Deleted by accident? Restore instead of re-entering |
Taking on a new customer used to mean: find the area in the sidebar, click “New”, fill in the form, save, go back, next area — sixteen times over. You had to know what to document and in which order.
The wizard turns that around. It asks one question at a time (“Which VLANs are there?”) and creates each answer straight away:
| Phase | Steps |
|---|---|
| Basics | Sites → contacts |
| Network | Internet connections → routers → VLANs → Wi-Fi networks → switches → access points |
| Servers & storage | Servers → VMs → NAS |
| Clients | Computers → printers |
| Services | AD domains → phone systems → backups |
Start under Other → Initial survey wizard, or from the card on the customer dashboard.
No more typing things over. Create an agent token bound to a customer and site in the interface, install an agent or run a script — the inventory lands in the documentation by itself. Every agent has its own token and can be locked on its own; repeated runs update instead of duplicating.
The recommended way: an agent that stays on the machine and reports by itself.
| Agent | Install | Reports |
|---|---|---|
| Windows | download the .exe (address and token are already inside) and double-click — a Windows service | server, Active Directory (users, groups, memberships), Hyper-V, workstation, Veeam and Windows Server Backup jobs |
| Proxmox | bash dokuvault-agent-proxmox.sh as root — a systemd timer | host, VMs, containers, vzdump backup jobs; Proxmox tags become services if the catalogue knows them |
| Linux | bash dokuvault-agent-linux.sh as root on Debian/Ubuntu — a systemd timer | hardware, operating system, IP address and running services |
.exe can be code-signed (scripts/build-windows-agent.sh with a certificate in
scripts/signing.env); the token appended on download keeps the signature valid.These agents need nothing but their token — they read the machine they run on.
# On the Proxmox host, as root:
bash proxmox-doku.sh
The Proxmox agent records host hardware, serial number, IP, CPU, memory and storage pools as well as all VMs and LXC containers (IP via the QEMU guest agent or the container config) and creates them as a server with its guests.
# On the Hyper-V host, or on a Windows server (as Administrator):
.\hyperv-doku.ps1
.\windows-server-doku.ps1
Hyper-V reports the host and every virtual machine. The Windows Server agent files the
machine as a server rather than a client — anyone who used to run the client agent on a server
found it under “Clients” afterwards, where nobody looks for it. It also reads the installed roles
(AD, DNS, DHCP, file server …) into the services field, as long as that field is still empty:
someone who has curated those services by hand knows more than Get-WindowsFeature.
# On a domain controller, or a machine with the RSAT AD module:
.\windows-ad-doku.ps1
# On a workstation:
.\windows-client-doku.ps1
The Windows AD agent reads all users plus only self-created groups — default and built-in groups and system accounts (Guest, krbtgt, DefaultAccount …) are filtered out on the domain controller itself, while the built-in Administrator is kept. Passwords are never read; in AD they are hashed and cannot be read at all.
The Windows client agent reports the hostname, manufacturer, model, serial number, operating system and IP of a workstation. It is recognised by an identifier of its own rather than by name — a renamed machine stays the same entry instead of becoming a second one.
These three do not run on the device but query a system through its API.
.\unifi-doku.ps1 -Controller "https://unifi.local" -User "doku" -Password "…" -Site "Kunde A"
.\vmware-doku.ps1 -Server "vcenter.local" -User "[email protected]" -Password "…"
.\microsoft365-doku.ps1 -TenantId "…" -ClientId "…" -ClientSecret "…"
UniFi picks up switches, access points and Wi-Fi networks — recognised by MAC address or controller id, so a renamed device stays the same entry. The script talks to both UniFi OS (UDM, Cloud Key Gen2+) and the classic controller without you having to know which one it is. VMware does what Hyper-V does, but per ESXi host under a vCenter, through the vSphere REST API and without PowerCLI. Microsoft 365 reads mailboxes, verified domains and booked licences through Microsoft Graph.
Because those three only talk to an API, UniFi and Microsoft 365 also ship as a shell script —
run them from a Mac or a Linux box, no PowerShell needed (curl and jq are enough). The token
page offers both versions side by side:
bash unifi-doku.sh --controller https://unifi.local --user doku --site "Kunde A"
bash microsoft365-doku.sh --tenant-id "…" --client-id "…"
The shell versions ask for the password rather than taking it as an argument, so it stays out
of the process list and the shell history — or read it from UNIFI_PASSWORD /
M365_CLIENT_SECRET.
A UniFi controller often holds several sites, while an agent token belongs to exactly one
customer — so the site is never guessed. With a single site it is used; with several the script
lists them and stops until one is chosen. --site takes the internal name or the display name;
--sites just lists them.
/etc/os-release (“debian 12”) and fills in only what the catalogue already holds — if nothing
matches, the field stays empty. “Debian 12” and “Debian 13” have different end-of-support dates;
a catch-all “Linux” would have none at all, which is worse than a gap. Same for Windows Server:
only a role the service catalogue already lists is taken over.The one exception among the passwords is the Wi-Fi passphrase: it sits in plain text in the
controller's configuration, DokuVault has an encrypted column for it, and in a documentation tool
it is exactly what people look up. --ohne-kennwoerter turns that off.
Crypt)APP_KEY, without which no stored password could be read after a restoreEvery object type follows the same pattern — know one, know them all. Four lists in
config/custom.php hold it together:
| Key | What for |
|---|---|
permissions | creates the gates _viewAny, _create, _update, _delete per object (in AuthServiceProvider) |
trashables | which objects appear in the recycle bin and can be restored |
list_titles | heading of the respective list page |
wizard_steps | order, questions and fields of the initial survey wizard |
A new object type therefore needs a model, migration, FormRequest, controller and views — plus one entry in each list that concerns it. Permission gates, recycle-bin support and page titles follow from that on their own.
Every resource lives under /{customer}/…; the customer binding is enforced through route model
binding and getFilteredQuery() in the base controller, which also applies the site filter from the
sidebar. Password fields are encrypted by the model itself through an Attribute cast, so plain
text reaches neither the database nor the audit log.
| Area | Used |
|---|---|
| Backend | PHP 8.2 · Laravel 12 · Livewire 4 · Laravel Sanctum 4 (agent/API tokens) |
| Packages | spatie/laravel-activitylog 4.12 (audit log) · barryvdh/laravel-dompdf 3.0 (PDF export) · spatie/laravel-backup 9.3 · league/flysystem-sftp-v3, -ftp (backup targets) |
| Frontend | Tailwind CSS 4 · Alpine.js 3 · Flowbite 4 · Vite 6 |
| Database | MySQL / MariaDB |
| Quality | Pest 3 (1394 tests) · Laravel Pint · GitHub Actions CI |
Requirements: either Docker — or PHP 8.2+, Composer, Node.js and MySQL/MariaDB.
git clone https://github.com/PhilippKuhlmann/dokuvault.git && cd dokuvault && docker compose up
Then open http://localhost:8000 and sign in with admin / password.
The first start creates the database, demo data and accounts by itself; a second start does not
seed again, so anything you entered stays.
The container is meant for trying things out and for small installations: one process with Laravel's built-in server, no nginx. For many users, the route in DEPLOYMENT.md is the right one.
Installs the demo customer “Mustermann” with realistic sample data. The demo data needs
fakerphp/faker, so install with dev dependencies here.
git clone https://github.com/PhilippKuhlmann/dokuvault.git
cd dokuvault
composer install # incl. dev packages (Faker for the demo data)
npm install && npm run build
cp .env.example .env # adjust APP_ENV=local, database credentials etc.
php artisan key:generate
php artisan migrate:fresh --seed # creates the demo customer + demo accounts
Then sign in with one of the demo accounts.
For a real server — no Faker, no demo data, only the seed data (roles/permissions, operating-system and mail-provider lists) — and no default administrator:
composer install --no-dev --optimize-autoloader
npm install && npm run build
cp .env.example .env
# IMPORTANT in .env: APP_ENV=production (drives the HTTPS requirement and the seeder)
php artisan key:generate
php artisan migrate --force
php artisan db:seed --force # runs the ProductionDatabaseSeeder
The seeder prints a one-time setup code. Open the instance in the browser: every page leads to
/setup, where you create the first administrator with that code and your own password. The page
is gone for good once an administrator exists. Lost the code? php artisan setup:code makes a new
one. To fix it in advance (e.g. for automated installs), set SETUP_TOKEN in the .env.
The seeder branches on
APP_ENV: demo data forlocal, only the seed data forproduction. WithAPP_ENV=localbut installed without dev packages, seeding fails (fake()not found) — then either setAPP_ENV=productionor install with dev packages.
Under Admin → Settings → Backup: daily time, an external SFTP or FTP/FTPS target (tested
before saving), retention and an archive password. Only with the archive password does the
backup contain the .env with the APP_KEY — without it every stored password is unreadable after
a restore. The page lists existing backups for download and explains the restore step by step.
Bringing an existing installation up to date — backup, git pull, dependencies, migrations — is
described step by step in DEPLOYMENT.md → Updating. To pin a
version instead of following main, use a tag in the format vYY.MM.DD.
A push to main can update the server by itself: the tests run first, and only if they pass does a
GitHub Action fetch the new state over SSH, migrate and rebuild the caches. Setup, secrets and the
hourly reset of a public demo are described in DEPLOYMENT.md.
| Role | Permissions |
|---|---|
| Admin | Everything, always — a built-in override that can't be locked out by an unchecked box |
| Technician | Access to all customers; the admin area is available role by role — see below |
| Customer | Sees only their own data |
The seeder creates four accounts — the same ones apply in the live demo. You see the most by trying them one after another: the sidebar, the “New” buttons and the admin area change with the role.
| Username | Password | Role | What it shows |
|---|---|---|---|
admin | password | Admin | Everything: all customers, the full admin area, activity log |
techniker | password | Technician | All customers, plus the full admin area in the demo — see below |
kunde-rw | password | Customer | Only the customer “Mustermann”, read and write |
kunde-r | password | Customer | Only the customer “Mustermann”, read-only — no “New” or “Edit” buttons |
The admin area is permission-based, not role-hardcoded: each of its sections — customers,
users & roles, dropdowns, settings, recycle bin, activity log, API tokens — has its own permission,
freely combinable per role in the role editor. A second technician group that may see the recycle
bin and the activity log but not manage users is a checkbox away, not a code change. Only the
built-in Admin role is special: it passes every permission check unconditionally, so removing
“manage roles” from it by accident can never lock out the last administrator. In the demo, both
admin and techniker have every permission checked, which is why they look identical there.
⚠️ These accounts do not belong on a real server. They come from the demo seeder and all share the same password. For production, create your own users and delete the demo accounts.
1394 feature tests (Pest 3) run against an in-memory SQLite — no setup needed, no traces in your development database. GitHub Actions runs the same suite on every push, against PHP 8.2 and 8.3 with SQLite and MariaDB, plus PHP 8.4 alongside but not blocking.
php artisan test
Individual areas:
php artisan test --filter=DocumentationWizard
Covered are, among others, tenant separation (no access to other customers or sites), the permission gates per role, the initial survey wizard including the field lists of its steps, the site filter across all lists, and the recycle bin with restoring. Plus two-factor sign-in, the brake against guessing, and encryption at rest: one test compares every column whose name suggests a secret against those actually encrypted — add a new one and you must either encrypt it or record why not.
Check the code style before committing:
./vendor/bin/pint
Contributions are welcome — see CONTRIBUTING.md and CODE_OF_CONDUCT.md. Please report security issues as described in SECURITY.md, not as a public issue.
Released under the MIT licence.
.envAPP_KEY