Network Reference
Jiji creates a project-isolated WireGuard mesh. Each server owns a routed container subnet and runs a per-project agent. Agents replicate desired placement, the service catalog, and DNS data directly over the mesh (membership is pushed separately, over SSH by the CLI, not agent-to-agent). There is no central coordinator.
Project Isolation
Every project derives its own WireGuard interface, UDP port, bridge, agent
unit, state directory, Unix socket, DNS address, and replication ports from
project:. Multiple projects can share a physical server. jiji-proxy is the
one host-global component and is attached to each project bridge that owns
routes on that host.
Jiji derives a /24 management range and /16 container range from
project:. Sixty-four default range slots exist, so this is not a global
allocator. Before a network change, Jiji checks host routes and active range
markers from other projects on the host. Configure explicit non-overlapping
CIDRs for a LAN, VPN, cloud VPC, or reported project collision.
The current control-plane limit is 32 servers per project. Configuration validation also limits a project to 500 services and 2,000 logical replicas. These are product limits, not limits implied by the number of generated CIDR slots.
Addressing
jiji network plan deterministically assigns:
- one management
/32per server; - one routed
/21container subnet per server; - bridge gateway, agent DNS, and jiji-proxy infrastructure addresses.
Service addresses are not compiled into the plan. The owner agent allocates a durable address lease when a deployment is created. Infrastructure addresses, network, and broadcast addresses are reserved. Released leases enter quarantine before reuse.
Each replacement receives a unique deployment ID and can coexist with the current Active deployment during a health check.
A service configured with network_mode: service:<upstream> is the one
exception: it never allocates an address of its own, and instead shares
whichever container its upstream is currently running as (--network container:<name>, the standard VPN-killswitch/sidecar pattern). See the
Configuration Reference
for the full dependency/cascade behavior.
Distributed DNS
Every project agent is authoritative for:
{project}-{service}.jiji, all reachable healthy Active replicas;{project}-{service}-{server}.jiji, healthy Active replicas owned by one server.
Agents answer UDP and TCP DNS on the project’s DNS address. Candidate, Draining, Stopped, Tombstoned, unhealthy, and unreachable-owner records are excluded. A new replica appears after its owner publishes it Active; no cluster-wide network generation or DNS reload is required.
Jiji-managed service containers receive their project DNS address explicitly. Docker and Podman IPAM do not understand Jiji’s infrastructure reservations, so containers attached manually to a Jiji bridge should always use an explicit address.
A service container’s resolv.conf has only the project’s own DNS address
as its nameserver, so any query outside the .jiji zone (a normal internet
hostname an application needs, such as a third-party API) is forwarded to
network.dns_forwarders (default 1.1.1.1/8.8.8.8, see the
Configuration Reference) rather
than answered locally. The first forwarder to answer wins; if every
configured forwarder is unreachable the query fails with SERVFAIL, not a
false NXDOMAIN.
Membership and Replication
Membership has no key material and no peer-to-peer relay: the CLI computes
it locally from jiji.yml and pushes it directly over SSH to every
reachable host, so a host’s trust boundary is “this file was installed by
root,” not a signature. Catalog and desired-placement records are different:
they are genuinely node-originated at runtime and stay continuously
converged through direct-only peer-to-peer anti-entropy between hosts.
Because WireGuard’s own peer authentication makes a connection’s source
address unspoofable within the mesh, a receiver authenticates an inbound
record by resolving the TCP connection’s source address against its local
membership view, rather than by checking a signature. Agents converge after
duplicate, reordered, or delayed delivery.
A filtered jiji server setup -H new-node connects to that host directly
over SSH and pushes it the current membership file; no other host needs to
be reachable. Adding or removing actual servers changes membership;
deploying or scaling services does not.
WireGuard UDP must be allowed between server public addresses on the
project-specific port shown by jiji network plan.
Service Placement and Scale
services.*.servers is the literal deploy target list — every listed
server gets a deployment. scale is the instance count on each listed
server, not a total across them.
jiji service scale writes a replicated desired-placement record before it
changes containers. Scale-up and scale-down are resumable. Scale-to-zero
withdraws DNS records and proxy routes and retires every deployment.
Proxy Routing
Each ingress route is rebuilt from healthy Active catalog records and may contain local and remote targets. Jiji reconciles the route on every eligible ingress owner. A deployment is admitted only after direct health checks pass; proxy reconciliation failure rolls back the candidate and keeps the previous Active deployment serving.
Recovery
Agent state is durable. After an agent or server restart, membership, desired placement, leases, and catalog history are loaded before replication catches up. DNS returns persisted healthy records immediately, with reachability used as a reversible eligibility overlay.
Explicit tombstones, not timeouts, remove durable membership or catalog ownership. A temporary partition can suppress unreachable replicas from DNS without deleting them.
Important Paths and Units
For project slug {slug}:
| Resource | Location |
|---|---|
| Mesh generations | /etc/jiji/network/{slug}/generations/ |
| Current mesh | /etc/jiji/network/{slug}/current |
| WireGuard config | /etc/wireguard/{interface}.conf |
| Agent root | /etc/jiji/agent/{slug}/ |
| Agent state | /etc/jiji/agent/{slug}/state/ |
| Agent socket | /etc/jiji/agent/{slug}/agent.sock |
| Agent unit | jiji-agent-{slug}.service |
jiji-agent-{slug}.service is the only Jiji-authored systemd unit installed
per project. The agent brings up its own WireGuard interface, bridge
network, DNS binding, and proxy attachment at startup and repairs them if
torn down externally — there is no separate restore/bring-up unit, and
nothing needs to reload when a peer or address changes.
Network setup removes exact legacy jiji-dns-{slug},
jiji-service-nat-{slug}, and (from installations predating agent-native
bring-up) jiji-network-restore-{slug} artifacts when upgrading an older
installation. They are not part of the current runtime.
Verification
jiji network plan
jiji network catalog
jiji network diagnostics
jiji server exec "wg show"
jiji server exec "systemctl status jiji-agent-<slug>"From a server, query its planned DNS address:
dig +short @<dns-address> myproject-web.jiji