Skip to content

Self-Hosted Availability Profile

The self-hosted profile groups Lattice’s relay/AutoNAT, peer-discovery rendezvous, encrypted pairing rendezvous, mailbox, and encrypted object-storage services for a NAS, home server, or VPS. The services remain separate processes with separate state directories and system accounts, plus separate identities and capability keys where their protocols require them. Failure of any optional service does not stop its siblings or direct online peer sync.

The profile does not automatically start a password-vault daemon or helper replica. Those processes can decrypt vault content and must be provisioned separately when the host is intended to hold a trusted replica.

For only the relay and rendezvous services, see Self-Hosting the Edge Services, the packaged lattice-edge.target, and packaging/install/lattice-self-hosted.sh.

Service Service listener Private metrics or probes
Relay and AutoNAT TCP/UDP 4001 127.0.0.1:9474
Peer rendezvous TCP/UDP 4201 127.0.0.1:9477
Pairing rendezvous 127.0.0.1:4211 HTTP /healthz, /readyz on 127.0.0.1:4211
Mailbox TCP/UDP 4101 127.0.0.1:9475
Object storage TCP/UDP 4102 127.0.0.1:9476

Expose the required TCP and UDP peer-service ports through the host firewall and upstream NAT. Keep every metrics listener and the pairing rendezvous on loopback. Public pairing uses an HTTPS reverse proxy on the same host; do not open port 4211 directly. Lattice does not change firewall or router rules.

The packaged peer-rendezvous configuration is an allowlisted libp2p discovery service. Add every client daemon Peer ID for private operation, or omit allowed_peer_ids (or set it to []) for public operation. Public mode accepts any authenticated libp2p Peer ID but retains the configured registration, discovery, and connection limits. Pairing rendezvous is a different HTTP service: it accepts bounded, opaque encrypted envelopes for 10-minute pairing sessions and does not receive the LPM1-... capability or pairing plaintext.

Build as the normal user:

Terminal window
cargo build --release --locked

Review and run the privileged installation steps explicitly:

Terminal window
sudo install -Dm0755 target/release/lattice /usr/bin/lattice
sudo install -Dm0644 packaging/systemd/lattice.sysusers.conf \
/usr/lib/sysusers.d/lattice.conf
sudo install -Dm0644 packaging/systemd/lattice.tmpfiles.conf \
/usr/lib/tmpfiles.d/lattice.conf
sudo systemd-sysusers /usr/lib/sysusers.d/lattice.conf
sudo systemd-tmpfiles --create /usr/lib/tmpfiles.d/lattice.conf
sudo install -Dm0644 packaging/systemd/lattice-infrastructure.service \
/etc/systemd/system/lattice-infrastructure.service
sudo install -Dm0644 packaging/systemd/lattice-rendezvous.service \
/etc/systemd/system/lattice-rendezvous.service
sudo install -Dm0644 packaging/systemd/lattice-pairing-rendezvous.service \
/etc/systemd/system/lattice-pairing-rendezvous.service
sudo install -Dm0644 packaging/systemd/lattice-mailbox.service \
/etc/systemd/system/lattice-mailbox.service
sudo install -Dm0644 packaging/systemd/lattice-object-storage.service \
/etc/systemd/system/lattice-object-storage.service
sudo install -Dm0644 packaging/systemd/lattice-self-hosted.target \
/etc/systemd/system/lattice-self-hosted.target
sudo install -Dm0644 packaging/lattice-infrastructure.toml \
/etc/lattice-infrastructure/config.toml
sudo install -Dm0644 packaging/lattice-rendezvous.toml \
/etc/lattice-rendezvous/config.toml
sudo install -Dm0644 packaging/lattice-pairing-rendezvous.toml \
/etc/lattice-pairing-rendezvous/config.toml
sudo install -Dm0644 packaging/lattice-mailbox.toml \
/etc/lattice-mailbox/config.toml
sudo install -Dm0644 packaging/lattice-object-storage.toml \
/etc/lattice-object-storage/config.toml

Replace every example DNS name and either configure the peer-rendezvous allowlist or remove it for public operation, then validate all five configs before startup:

Terminal window
lattice infrastructure config-check --config /etc/lattice-infrastructure/config.toml
lattice rendezvous config-check --config /etc/lattice-rendezvous/config.toml
lattice pairing-rendezvous config-check \
--config /etc/lattice-pairing-rendezvous/config.toml
lattice mailbox config-check --config /etc/lattice-mailbox/config.toml
lattice object-storage config-check --config /etc/lattice-object-storage/config.toml
sudo systemctl daemon-reload
sudo systemctl enable --now lattice-self-hosted.target

The target uses Wants= rather than Requires=, while each grouped service uses PartOf= so target stop and restart operations propagate without making a single service failure stop its siblings. Inspect individual service health when the target is active:

Terminal window
systemctl status lattice-self-hosted.target
systemctl status lattice-infrastructure.service lattice-mailbox.service \
lattice-object-storage.service lattice-rendezvous.service \
lattice-pairing-rendezvous.service
curl --fail http://127.0.0.1:9474/readyz
curl --fail http://127.0.0.1:9475/readyz
curl --fail http://127.0.0.1:9476/readyz
curl --fail http://127.0.0.1:9477/readyz
curl --fail http://127.0.0.1:4211/healthz
curl --fail http://127.0.0.1:4211/readyz

The packaged pairing service deliberately listens only on 127.0.0.1:4211. Put an HTTPS reverse proxy in front of only /v1/sessions/*, keep /healthz and /readyz private, and preserve request bodies and the x-lattice-expires-at response/request header without transformation. Configure ordinary request-rate and connection limits at the proxy in addition to the service’s session, byte, envelope-size, and expiry limits.

The client default is https://pair.latticepm.net. This repository packages the loopback backend and service units; it does not assert that DNS, certificates, the reverse proxy, or that public endpoint have been deployed. A different operator endpoint is selected on both devices with --server <https-url>. Plain HTTP is accepted only for a loopback URL.

The user target groups the same processes without root access:

Terminal window
install -Dm0755 target/release/lattice ~/.local/bin/lattice
install -Dm0644 packaging/systemd/user/lattice-infrastructure.service \
~/.config/systemd/user/lattice-infrastructure.service
install -Dm0644 packaging/systemd/user/lattice-rendezvous.service \
~/.config/systemd/user/lattice-rendezvous.service
install -Dm0644 packaging/systemd/user/lattice-pairing-rendezvous.service \
~/.config/systemd/user/lattice-pairing-rendezvous.service
install -Dm0644 packaging/systemd/user/lattice-mailbox.service \
~/.config/systemd/user/lattice-mailbox.service
install -Dm0644 packaging/systemd/user/lattice-object-storage.service \
~/.config/systemd/user/lattice-object-storage.service
install -Dm0644 packaging/systemd/user/lattice-self-hosted.target \
~/.config/systemd/user/lattice-self-hosted.target
install -Dm0600 packaging/lattice-infrastructure.toml \
~/.config/lattice-infrastructure/config.toml
install -Dm0600 packaging/lattice-rendezvous.toml \
~/.config/lattice-rendezvous/config.toml
install -Dm0600 packaging/lattice-pairing-rendezvous.toml \
~/.config/lattice-pairing-rendezvous/config.toml
install -Dm0600 packaging/lattice-mailbox.toml \
~/.config/lattice-mailbox/config.toml
install -Dm0600 packaging/lattice-object-storage.toml \
~/.config/lattice-object-storage/config.toml
~/.local/bin/lattice pairing-rendezvous config-check
systemctl --user daemon-reload
systemctl --user enable --now lattice-self-hosted.target

Rootless services use separate directories but share one Unix identity. Use the system profile when host-level account isolation is required. Enable user lingering separately when services must survive logout.

Service Peer IDs are stable only while their private identity keys survive. For system services, inspect them through the owning service accounts:

Terminal window
sudo -u lattice-infrastructure /usr/bin/lattice infrastructure peer-id \
--identity /var/lib/lattice-infrastructure/infrastructure-identity.key
sudo -u lattice-rendezvous /usr/bin/lattice rendezvous peer-id \
--identity /var/lib/lattice-rendezvous/rendezvous-identity.key
sudo -u lattice-mailbox /usr/bin/lattice mailbox peer-id \
--identity /var/lib/lattice-mailbox/mailbox-identity.key
sudo -u lattice-object-storage /usr/bin/lattice object-storage peer-id \
--identity /var/lib/lattice-object-storage/object-storage-identity.key

Capability issuance must use the same config and state directories as the running service. The following commands make that context explicit:

Terminal window
sudo -u lattice-mailbox env \
CONFIGURATION_DIRECTORY=/etc/lattice-mailbox \
STATE_DIRECTORY=/var/lib/lattice-mailbox \
RUNTIME_DIRECTORY=/run/lattice-mailbox \
/usr/bin/lattice mailbox issue <mailbox-id> receive
sudo -u lattice-object-storage env \
CONFIGURATION_DIRECTORY=/etc/lattice-object-storage \
STATE_DIRECTORY=/var/lib/lattice-object-storage \
RUNTIME_DIRECTORY=/run/lattice-object-storage \
/usr/bin/lattice object-storage issue <repo-id> reader

Issue deposit/publisher capabilities separately and install all bearer tokens through stdin as described in docs/services/mailbox.md and docs/services/object-storage.md.

Back up each state boundary independently while its service is stopped:

  • /var/lib/lattice-infrastructure: stable relay/AutoNAT identity.
  • /var/lib/lattice-rendezvous: stable peer-rendezvous identity.
  • /var/lib/lattice-pairing-rendezvous: opaque, expiring pairing sessions and service quota state. It contains no pairing plaintext and does not need a long-term backup; losing it aborts in-flight sessions, which must be restarted.
  • /var/lib/lattice-mailbox: identity, capability key, envelopes, and quota state.
  • /var/lib/lattice-object-storage: identity, capability key, metadata, objects, publications, and quota state.
  • /etc/lattice-*: validated non-secret service configs.

Restore a directory to the same service account with private permissions before starting that service. Restoring an identity without its capability key, or a capability key without its durable state, creates a different operational boundary and requires client reprovisioning. Test restores on a non-production host and verify stable Peer IDs, policy discovery, readiness, and one complete offline publish/fetch cycle.

An always-on trusted replica is separate from the availability target. Complete the targeted recovery bootstrap in docs/guide/helper.md, then enable either the normal daemon or lattice-helper.service; never both against the same vault state directory.