Documentation
Everlock architecture
Everlock is organized around a simple rule: transport and service logic do not live in the same crate.
flowchart LR
subgraph Frontends
SSH[frontend-ssh]
HTTP[frontend-http]
DNS[frontend-dns]
SMTP[frontend-smtp]
IMAP[frontend-imap]
MDNS[frontend-mdns]
end
subgraph Backends
GIT[backend-git-ssh]
AI[backend-ai-ssh]
ADMINS[backend-admin-ssh]
ADMINH[backend-admin-http]
SITE[backend-site-http]
IMAGE[backend-image-http]
OCI[backend-oci-http]
CAL[backend-calendar-http]
CONTACTS[backend-contacts-http]
OAUTH[backend-oauth-http]
DNSH[backend-dns-http]
DNSB[backend-dns-dns]
MAIL[backend-mail-smtp]
MAILI[backend-mail-imap]
end
subgraph Primitives
subgraph VS [versioned-storage]
SYSSTORE[everlock-system]
DNSSTORE[everlock-dns]
MAILSTORE[everlock-mail]
CALSTORE[everlock-calendar]
CONTACTSSTORE[everlock-contacts]
SITESTORE["<site-name>"]
OCISTORE["<registry-name>"]
IMGSTORE["<image-name>"]
end
USER[user]
JOBS[jobs]
end
SSH --> GIT
SSH --> AI
SSH --> ADMINS
HTTP --> SITE
HTTP --> IMAGE
HTTP --> OCI
HTTP --> ADMINH
HTTP --> CAL
HTTP --> CONTACTS
HTTP --> OAUTH
HTTP --> DNSH
DNS --> DNSB
SMTP --> MAIL
IMAP --> MAILI
GIT --> SITESTORE
SITE --> SITESTORE
MAIL --> MAILSTORE
MAILI --> MAILSTORE
CAL --> CALSTORE
CONTACTS --> CONTACTSSTORE
OCI --> OCISTORE
IMAGE --> IMGSTORE
ADMINS --> SYSSTORE
ADMINH --> SYSSTORE
OAUTH --> SYSSTORE
DNSH --> DNSSTORE
DNSB --> DNSSTORE
ADMINS --> JOBS
JOBS --> SYSSTOREThe broker model
At the top level, Everlock is one binary that loads configuration, starts the enabled modules, and routes requests to the right backend instances. A frontend answers the question, "how does a client arrive here?" A backend answers, "what domain operation is this system performing?"
Frontends
The current transport model documented in the repository includes:
| Frontend | Role |
|---|---|
frontend-ssh | SSH listener for Git commands and admin PTY sessions |
frontend-http | Virtual-host HTTP transport that mounts backend instances |
frontend-dns | Zone-dispatch DNS transport |
frontend-smtp | Inbound mail transport, plus authenticated submission |
frontend-imap | IMAPS on port 993 (and optional STARTTLS on 143) for mail clients |
frontend-mdns | Local-link announcement layer for hostnames |
The HTTP frontend is explicitly vhost-driven. It does not assume a global route table.
Backends
Backends are grouped by domain and stay transport-agnostic. Today the repository includes implemented backend families for Git, sites, images, OCI, mail (SMTP + IMAP), DNS, calendars, contacts, OAuth, AI, and the two admin flows (SSH REPL + HTTP dashboard).
The naming scheme reflects that separation:
backend-git-sshbackend-site-httpbackend-dns-dnsbackend-admin-sshbackend-admin-http
Shared primitives
The architecture doc anchors every service on three reusable primitives:
| Primitive | Why it exists |
|---|---|
| Versioned storage | Audit-friendly mutable records using Git-backed storage |
| User | Shared principals, groups, credentials, and access paths |
| Jobs | Async task scheduling for things like indexing and derived work |
This keeps the project from fragmenting into backend-specific identity and storage models. If a backend needs a custom file layout, that layout belongs to the backend rather than to a generic shared storage layer.
Two further shared crates sit alongside the primitives — not "primitives" themselves, but resource owners that more than one backend depends on:
| Crate | Owns | Consumed by |
|---|---|---|
everlock-mail-storage | Mail tree layout, IMAP UID/UIDVALIDITY, the shared MailEventBus | backend-mail-smtp, backend-mail-imap |
everlock-ai-runtime | Embedded GGUF model bytes, llama.cpp worker, AiTool / ImageInferenceProvider traits | backend-ai-ssh (text prompts + tools), backend-image-http (image captions) |
The pattern is the same in both cases: one crate owns the heavy resource, exposes small traits, and backends register or consume those traits through the BackendRegistry.
Security posture
One of the most important architectural constraints in the project is the "embed over execute" rule. Everlock is not meant to shell out to git, sh, or other host tools. That keeps the static binary contract intact and reduces avoidable command-injection and environment-leak problems.