Project Pharos is a highly performant, read-optimized client-server ecosystem based on RFC 2378 (Phonebook Protocol).
System Overview
The following diagram illustrates the high-level architecture of Pharos, showing the interaction between CLI clients and the server components.
graph TD
subgraph Clients
PH[ph CLI - People]
MDB[mdb CLI - Machines]
SCAN[pharos-scan - Discovery]
end
subgraph "Pharos Server"
TCP[TCP Listener :2378]
Parser[RFC 2378 Parser]
Auth[Auth Manager - SSH Keys]
Metrics[Metrics Engine - Prometheus]
StorageTrait[Storage Trait]
subgraph "Storage Backends"
Mem[MemoryStorage - Dev]
File[FileStorage - Home Lab]
LDAP[LdapStorage - Enterprise]
end
end
PH -->|RFC 2378| TCP
MDB -->|RFC 2378| TCP
SCAN -->|mDNS / Port Probes| LAN((Local Network))
LAN --> SCAN
SCAN -->|RFC 2378| TCP
TCP --> Parser
Parser --> Auth
Auth --> StorageTrait
StorageTrait --> Mem
StorageTrait --> File
StorageTrait --> LDAP
Metrics -.->|Observe| StorageTrait
Metrics -.->|Observe| TCP
Storage Tiering Logic
🏠Home Lab: Persistent File Storage
Pharos uses a file-level, restart-survivable JSON storage engine optimized for LXC containers. This ensures high performance with minimal configuration.
graph LR
File[FileStorage]
File -.->|Persistent| JSON[(Local JSON File)]Core Protocol: RFC 2378 (Modified)
Pharos implements the Phonebook Protocol with extensions for modern infrastructure management and secure authentication.
Message Flow
- QUERY: Client sends a search string.
- DISCRIMINATE: Server identifies if the target is a
personormachine. - AUTH (if Write): Server issues an SSH challenge. Client signs and returns.
- RESPONSE: Server returns records in Ph format.
ADD, CHANGE, and DELETE all follow the same AUTH-then-commit flow shown below for ADD —
CHANGE additionally requires a make (or force) clause to separate its selection criteria from
the fields it modifies, per RFC 2378 §3.10.
sequenceDiagram
participant Client
participant Server
participant Auth
participant Storage
Client->>Server: QUERY "name=John"
Server->>Storage: Search(people, "John")
Storage-->>Server: [Records]
Server-->>Client: 200: [Ph Records]
Note over Client,Server: Write Operation
Client->>Server: ADD "name=Jane"
Server->>Auth: Challenge(SSH-Key)
Auth-->>Client: Challenge
Client-->>Auth: Signed-Response
Auth-->>Server: Verified
Server->>Storage: Commit(Jane)
Server-->>Client: 200: Success
Known RFC 2378 Deviations
RFC 2378 Protocol Deviations
Pharos deliberately deviates from RFC 2378 in several places — here’s what’s intentional and what’s still an open gap.
1. No Field-Level Attribute or ACL System
RFC 2378 defines per-field keywords (e.g., Public, Private, LocalPub, Sacred, Unique, Encrypt, Indexed, NoMeta, NoPeople, Turn, Any, Always, Default, ForcePub, Change) governing visibility and mutability on a per-field basis.
In contrast, Pharos’s Record structure is implemented as a flat, metadata-free HashMap<String, String> inside storage.rs. Authorization is handled strictly at the record level (enforcing fingerprint/team ownership in change_record and delete_record). This is a deliberate, load-bearing design choice (Pharos’s target use cases of home labs and small teams do not require field-level access controls).
- Downstream Consequence: Because there is no concept of field-level access control, schema discovery via the
fieldscommand is global. It reports field names (never values) harvested across all stored records regardless of which team owns them.
2. SSH-Key Challenge-Response Authentication
The native password-based and Kerberos login mechanisms described in RFC 2378 are replaced entirely by a modern, high-rigor SSH key-based challenge-response flow.
While the login command is supported, it is only dispatched to generate a challenge for the Pharos-specific auth command (which verifies cryptographic signatures using local SSH keys). Other RFC-defined authentication commands, such as answer (encrypted password response), clear (cleartext password), email (port/domain-based authentication), and xlogin (Kerberos v4/v5, GSSAPI, ANSI X9.9), parse successfully into Command variants but have zero dispatch logic behind them.
3. Parseable Commands Without Dispatch Logic
The parser recognizes all standard RFC 2378 commands. However, the server does not implement dispatch logic for the following seven commands:
SiteInfoLogoutAnswerClearEmailXLoginHelpAny attempt to call these commands falls through to the generic Pharos extension response code597:Command recognized, but not yet implemented(deliberately distinct from a598syntax error).
4. Inert set Command Options
The set command is implemented in lib.rs with real enforcement for two safety-critical options: limit (capping the number of entries a change or delete may affect) and addonly (preventing fields from being overwritten).
The other five RFC-defined options—echo, charset, verbose, nolog, and external—are settable and reportable (via set with no arguments) but have no behavioral effect on the server:
echodoes not echo commands back.charsetis accepted but no character set conversions are performed.verbosedoes not emit interim progress lines.nologdoes not affect logging.externaldoes not hide any fields because there is no field-keyword concept.
5. Response Code Alignments
Pharos aligns its response codes with Appendix B of RFC 2378. Two permanent design characteristics of this alignment include:
- Extension Code
597: Pharos introduces the597response code specifically to denote a command that is recognized by the parser but not implemented by the dispatcher, distinguishing it from598(which indicates an unknown/unparseable command). - Authorization Gaps: Where RFC 2378 does not provide specific codes for authorization failures, Pharos uses
511(“not authorized to add entries”) foradd,510(“not authorized to change this entry”) forchange, and516(“no authorization for request”) as a fallback for all other permission checks (such as unauthorized deletion or failed signature verification).
6. Wildcard Matching Escape Limitation
Pharos supports RFC 2378 wildcard matching for the *, +, ?, and [abc] forms in any position or combination using a hand-rolled dynamic programming matcher (avoiding regular expression backtracking vulnerabilities and escaping complexity).
However, a deliberate limitation exists: there is no escape mechanism. Literal wildcard characters (such as *, +, ?, [, or ]) cannot be matched in search values, as they are always interpreted as pattern syntax.
Core Components
1. Pharos Server (pharos-server)
The backend engine handling connection lifecycle, protocol parsing, and storage abstraction.
- Protocol: RFC 2378 (Ph) with
authextension. - Authentication: SSH-key based challenge-response for Write operations.
- Metrics: Integrated Prometheus scrape point (
:9090/metrics) and health monitoring.
2. CLI Clients
ph: Optimized for human contact management.mdb: Optimized for machine/infrastructure asset management.pharos-scan: Automated discovery engine using mDNS and port probes to identify and provision assets into Pharos.- All clients support automatic authentication via local SSH private keys and share a common async core.
3. Storage Tiering
- Development: Zero-configuration in-memory storage.
- Home Lab: File-level, restart-survivable JSON storage (optimized for LXC).
- Enterprise: LDAP-backed storage utilizing standard schemas (
inetOrgPerson,ipHost).
4. Multi-Server Synchronization
Set PHAROS_SYNC_ADDR to have a node advertise itself as a replication peer and relay its own
add/change/delete writes to every other peer it’s aware of. Set PHAROS_BOOTSTRAP_PEER
alongside it to pull an existing peer’s full record set on startup. Peer awareness today is
gained through bootstrapping, not announced automatically in both directions — see the
Server Setup guide before relying on this for a production multi-node cluster.
Multi-Tenant & Triple-Tier Security
Pharos implements a flexible security model designed to scale from a single user’s “YOLO Lab” to a multi-tenant Enterprise environment.
🏠Home Lab: The “YOLO” Security Model
In Home Lab environments, Pharos prioritizes speed and accessibility.
- Open Access: Read operations are anonymous and unauthenticated.
- SSH Challenge: Write operations still require a valid signature from an authorized SSH key for basic safety.
- Use Case: Single-user labs or trusted home networks.
The Dual-Site Ecosystem
Pharos distinguishes between documentation (static) and management (dynamic) to ensure high availability and security.
graph LR
User((User))
Agent((AI Agent))
subgraph "Public Internet"
Marketing[Marketing Site / Docs]
Marketing -.->|Self-Help| User
end
subgraph "Private Network / Lab"
Server[Pharos Server]
Console[Pharos Console]
Pulse[pharos-pulse Agents]
Console --- Server
Pulse -->|Heartbeat| Server
Console -.->|WebMCP| Agent
Agent -.->|Tool Calls| Console
User --- Console
end
1. Marketing & Documentation (iamrichardd.com/pharos/)
- Type: Static Site (Astro/MDX).
- Purpose: Architecture guides, “How-To” tutorials, and open-source advocacy.
- Why: Ensures that even if your Pharos server is down, you still have access to the documentation on how to fix it.
2. Pharos Console (pharos-console)
- Type: Dynamic Web Application & MCP Server.
- Purpose: Real-time TUI/Web dashboard, SSH key management, and AI Agent orchestration.
- Features:
- WebMCP Bridge: Allows your browser to act as a secure proxy for AI Agents.
- MDB Search: High-performance inventory querying with visual search results.
- Enrollment: One-click provisioning for new nodes.