Admin Web UI
Vue 3 + Vite SPA served by the existing HTTP server at /admin/ (same origin as the JSON API).
Build
cd admin
rm -rf node_modules # optional; avoids stale installs after new deps (e.g. xterm)
npm ci # installs from package-lock.json (required on every build host)
npm run build
# → admin/dist/
npm run build refuses to start if package.json dependencies are missing from node_modules (see scripts/check-deps.mjs). Packaging/makepkg always runs a clean npm ci first.
Server config (default already points here):
"adminDistPath": "admin/dist"
Restart lindir-server. Open http://127.0.0.1:1289/admin/ and sign in with the bootstrap token or an API token (ldt_…).
Dev
# terminal 1 — API
dub run --compiler=ldc2 -- --config config.json
# terminal 2 — Vite (proxies /v1 and /health)
cd admin && npm run dev
# → http://127.0.0.1:5173/admin/
Navigation
Two-level IA: primary sidebar and secondary section tabs.
Primary: Dashboard, Directory, Hosts, Host access, Software, Compliance, Automation, Platform, Audit.
Workflow pages (Create user, Set password, Enroll host) are actions on the Users / Hosts lists, not secondary tabs (routes remain for deep links).
On desktop the sidebar can be resized (drag the edge) or hidden (‹ / Menu); preference is stored in localStorage. Main content uses the full remaining width (tables are not capped at ~64rem).
Legacy paths (/users, /groups, /fleet, /tokens, /oidc, /policy) redirect into this hierarchy. Most page URLs stay under /directory, /hosts, /policy, /fleet, /access — only the menu grouping changed.
Pages
| Section / route | Capabilities |
|---|---|
Login /login |
Bearer token → sessionStorage only |
Dashboard / |
Needs attention: stale sync, reboot recommended, failed package jobs, recent auth denials, upgradable counts, open vulns; queue reboot; upgradable links open Software → Upgrades (?hostId= for a host) |
Directory → Users /directory/users |
List + enable/disable; Create user / Set password actions |
Directory → Create user /directory/users/create |
Create account (from Users actions) |
Directory → Set password /directory/users/password |
Reset password (from Users actions) |
Directory → Groups /directory/groups |
Create groups; add/remove members; list members |
Directory → Passkeys /access/passkeys |
List/register/revoke WebAuthn passkeys per user |
Directory → Account policy /directory/account-policy |
Min length, complexity, max age, lockout, must-change-on-create |
Hosts → Hosts /hosts |
Hostnames, OS, last seen; Console link; Enroll host / enroll-tokens actions |
Hosts → Console /hosts/console |
Interactive agent PTY (xterm.js ↔ WebSocket); optional ?hostId=; root-equivalent |
Hosts → Inventory /fleet/inventory |
Collected inventory; hostname → host Systemd; per-row links to Systemd / Upgrades / Apt sources / Cron / Timers / Oneshots / Services (?hostId=); upgradable count links to host Upgrades; summary panels; queue reboot if recommended |
Hosts → Labels /fleet/labels |
Host sets; assign/unassign hosts; membership list; sync from HBAC |
Hosts → Enroll tokens /hosts/enroll-tokens |
One-shot len_… tokens + copy join command |
Hosts → Enroll host /hosts/enroll |
Admin-token enroll + copy secret; optional skip VPN (from Hosts actions) |
Host access → HBAC /policy/hbac |
Host-based access rules; dry-run check (groups × host → allowed/denied) |
Host access → Sudo /policy/sudo |
Sudo rules |
Host access → SSH keys /policy/ssh-keys |
Per-user public keys |
Software → Packages /fleet/packages |
Install/remove/upgrade/reboot/update-agent/add-ppa/enable-ppa/disable-ppa/remove-ppa by host or label; apt-source actions pick from reported sources; pending jobs list with cancel; job history (+ ?job= deep link to stdout/stderr) |
Software → Upgrades /fleet/upgrades |
Upgradable packages from apt/dnf/pacman/zypper indexes; optional ?hostId= filter; select packages or Queue upgrade all (full system upgrade) |
Software → Apt sources /fleet/apt-sources |
sources.list.d / Launchpad PPAs from inventory (incl. disabled); Enable / Disable / Remove; optional ?hostId= |
Software → Vulnerabilities /fleet/vulns |
Distro-aware CVE findings (Ubuntu + Arch + OSV for Debian/RHEL/SUSE); scan / refresh / force refresh; background job status |
Compliance → Devices /fleet/devices |
Host posture; lock / retire |
Compliance → Policies /fleet/compliance |
MDM policies (distro, encryption, password); assign/unassign; target list with unassign |
Compliance → Scripts /fleet/compliance-scripts |
Custom discovery scripts |
Compliance → Energy /fleet/energy |
Sleep/screen/lid policies; assign/unassign host/label; target list with unassign |
Automation → Cron /fleet/cron |
User crontabs + /etc/cron.d/lindir-*; add / enable / disable / remove; pending cancel; notes hosts missing user crontab (informational — Inventory omits that note) |
Automation → Timers /fleet/timers |
System + user lindir-*.timer / .service; add / enable / disable / remove; optional linger for user scope |
Automation → Oneshots /fleet/oneshots |
Login (default.target) / boot (multi-user.target) lindir-*.service oneshots; leave linger off for login-only |
Automation → Services /fleet/services |
Always-on Type=simple lindir-*.service (user or system); linger on by default for user scope; restart / enable / disable / remove |
Automation → Systemd /fleet/systemd |
Pick a host (dropdown or list), then browse that host’s unit catalog; queue start/stop/restart/reload/enable/disable/mask/unmask; denylist for critical units; ?hostId= from Inventory |
Automation → Queries /fleet/queries |
Define + queue queries |
Automation → Scripts /fleet/scripts |
Define + queue scripts |
Automation → Runs /fleet/runs |
Query/script run results |
Platform → API tokens /access/tokens |
Create/list/revoke |
Platform → OIDC /access/oidc |
Relying-party clients; optional require compliant device |
Platform → VPN /vpn |
Sync ACLs |
Audit /audit |
Filters; Logins; Host logins; Denials; Export CSV; clickable column sort (default When newest first); expand row for detail + package job stdout/stderr (hostname resolved) |
Uses Vue 3 (versioned via npm/package-lock.json) and vue-router 4.
Mobile
Wide tables scroll horizontally inside panels (cells stay in-column). Primary/secondary nav scroll sideways on narrow viewports.
Security notes
- Long-lived Bearer in
sessionStorageis XSS-sensitive — see OWASP Controls A01/A07. - Fleet package/script/energy/cron/timer/oneshot/systemd-operate actions are root-equivalent on targeted hosts.
- Hosts → Console is an interactive root shell via the agent — treat like fleet scripts (OWASP Controls).
- MDM retire clears enrollment; lock is
loginctl lock-sessions— see MDM & Compliance.
