Architecture

Module layout of the Linux Directory server.

Architecture

┌─────────────────────────────────────────────────────────┐
│  lindir server (D)                                      │
│  ┌─────────┐ ┌──────────┐ ┌────────┐ ┌───────────────┐  │
│  │ identity│ │ policy   │ │ auth   │ │ vpn plugins   │  │
│  │ users   │ │ HBAC     │ │ tokens │ │ Tailscale…    │  │
│  │ groups  │ │ sudo     │ │ enroll │ │ (optional)    │  │
│  │ hosts   │ │ SSH keys │ │ PBKDF2 │ │               │  │
│  └────┬────┘ └────┬─────┘ └───┬────┘ └───────┬───────┘  │
│  ┌────┴───────────┴───────────┴──────────────┴───────┐  │
│  │ fleet: inventory · labels · packages · energy ·   │  │
│  │        queries/scripts · ops attention            │  │
│  │ oidc · webauthn · ldap gateway · audit            │  │
│  └───────────────────────┬───────────────────────────┘  │
│              repo layer (parameterized SQL)             │
│                         │                               │
│              Database interface (?, tx)                 │
│         memory://  |  postgres   |  mysql                 │
└─────────────────────────────────────────────────────────┘
          │
          ▼
┌─────────────────────────────────────────────────────────┐
│  lindir-client (D)                                      │
│  enroll · sync · pam-auth · authorized-keys             │
│  → extrausers · sudoers.d · package jobs · energy       │
│  → inventory · query/script runs                        │
└─────────────────────────────────────────────────────────┘

Modules

Path Role
source/lindir/api.d HTTP JSON API + static /admin SPA + OpenAPI serving
admin/ Vue 3 admin UI (Vite → admin/dist)
source/lindir/auth.d Bootstrap / API tokens, host enrollment auth, one-shot enroll tokens, account-policy login checks
source/lindir/crypto/password.d PBKDF2-HMAC-SHA256
source/lindir/identity.d / policy.d Domain services + audit
source/lindir/repo/* SQL repositories (users, hosts, fleet, account_policy, enroll_tokens, audit, …)
source/lindir/oidc/* OpenID Connect IdP (RS256/JWKS, refresh, public/PKCE)
source/lindir/webauthn/* Passkeys / WebAuthn (ES256, register + assert)
source/lindir/ldap/* Read-only LDAP gateway (BER + bind/search)
source/lindir/storage/* DB interface, memory, PostgreSQL, MySQL, migrations
source/lindir/vpn/* Pluggable VPN (Tailscale, Headscale, WireGuard)
source/lindir/fleet/* Native fleet (packages, labels, queries/scripts, energy)
source/lindir/net/* Shared HTTPS JSON client (libcurl)
cli/ lindir-admin Bearer API CLI
client/ lindir-client (sync applies IdM + fleet packages + energy)
sql/migrations/ Versioned schema (001 … 012_fleet_energy, …)

Host login

Sync = cache refresh. Each successful lindir-client sync writes NSS files (/var/lib/extrausers/), policy (cache.json), and password hashes (cache-auth.json), and renews the offline login window for offlineMaxAgeSeconds (default 72 hours from the sync timestamp).

While that window is open, password login works with the Lindir server down: PAM verifies PBKDF2 against the sync cache and evaluates HBAC locally. The sync timer keeps renewing the window while the host can reach the server; if sync stops, login eventually ages out (fail closed).

When the server is reachable, PAM still tries online auth first (short timeout) so lockout / must-change / live deny apply. HTTP 401/403 never fall back to the cache. See Client.

Concern Needs server?
Enroll Yes
Sync (refresh cache + renew TTL) Yes
Password login within TTL No (local cache)
Password login after TTL expiry Yes (sync again)

Naming

Name Meaning
lindir Project / package / config dir (/etc/lindir)
lindir-server Server daemon binary (dub build)
lindir-client Host agent (cd client && dub build)
lindir-admin Operator CLI (cd cli && dub build)

Toolchain

  • Compiler: LDC for production; DMD OK for local dev
  • Build: dub build (server → lindir-server), cd client && dub build, cd cli && dub build, cd admin && rm -rf node_modules && npm ci && npm run build
  • Dev DSN: memory:// or MySQL — see Storage
  • Operator guide: Operator handbook
  • Client setup: Client
  • Fleet: Fleet
  • HTTP API: openapi.json (served at GET /openapi.json)
  • Security: OWASP Controls