A mesh VPN with no coordination server

WireGuard carries the traffic. Who belongs to the network is a log signed by your admins, and every device checks that log for itself.

Install →
No server in the middle
Devices find each other on the LAN, through each other, or through the public BitTorrent DHT. They punch through NAT, and fall back to a relay that one of your own devices runs.
Changes need your admins
Admitting or removing a device takes a quorum of admins, each with a key on their own devices. The keys stay in the keystore; the daemon never holds them.
Fail-closed
Once a network has vouchers, a device that too few of them vouched for in 48 hours keeps tunnels only to vouchers. It cannot keep a removed device connected.

Your first network #

On the first device, juist create makes a network and juist invite prints a code for the LAN and a link for anywhere else. The new device joins with either. Both then show four words, and the invite admits the device only once you have compared them.

laptop
$ juist create home
created network "home"
$ juist invite
invite to "home", expires in 1h; on the new device:

  juist join 'juist:Kx7q…@192.168.1.20:41642'

  juist join 42-drumbeat-tolerance-glucose  # same LAN

nas wants to join; compare with the words it shows:
  atlas-amulet-banjo-asteroid
same? [y/N] y
admitting nas (nid:fcRW83T_…)
admitted nas at 198.18.36.2
nas joined

Features #

Made for networks of up to about 100 devices with a few admins. A network holds at most 512 devices.

FeatureWhat it does
Mesh and NAT traversal #WireGuard tunnels between every pair of devices, direct where NAT allows.→ Servers without open SSH
Quantum-safe #Every handshake mixes in a key a quantum computer cannot recover, each pair of devices has its own, and every change is signed with ML-DSA.
Invites #A code for the LAN or a link for anywhere. Both devices show four words to compare.
Android #A phone with Android 12 or newer joins with the invite's QR code or code, reaches the members at their addresses, and shows how each one is reached.
Containers Linux only #An app in a container is a device of its own, through a juist container sharing its network namespace.→ An app in a container
Admins and quorum #Every change needs k of n admins. If it needs more approvals, it is passed on to the other admins' devices.
Access policy #Which device may open what on which other device, and which exit node or subnet it may use. Everything else is refused.→ Your own services, through the tunnel · Tools for members alone · Servers without open SSH
Several networks #One device in several networks, each with its own admin key.
Exit nodes #A device's internet traffic and DNS, sent through another member.→ Safe on public Wi-Fi
Subnet routers #The LAN behind one member, reachable from the others.→ Your home LAN from anywhere
Multicast #Printers, media servers and LAN games find the members by mDNS, SSDP or their own groups, as on one LAN.
UDP broadcast Linux only #Local IPv4 UDP broadcasts, including NetBIOS, reach the members too, while the originals stay on the LAN; no port configuration.
Names #Every member as DEVICE.NETWORK.juist, and public names pointed at members.→ Your own services, through the tunnel
Publishing services #A member's service, reachable from the internet by name through an ingress.→ A homelab on the internet
HTTP/3 #Published names over QUIC through the ingress, for browsers that discover it themselves or learn of it from DNS.→ A homelab on the internet
Members-only names #A published name with a certificate from the CA that the internet cannot reach. Only the members the access policy allows can open it.→ Tools for members alone
TCP services #A game server or any other TCP service on its own port on every ingress, passed on without being read.→ A game server for friends
Sharing #A file, a directory or a web server, on the internet right away under the device's own name. A directory downloads as a ZIP.→ Share from your laptop
Status page #Devices, how they are reached, published names and the log's changes on one page for members, and as much of it for everyone else as you choose.
Relays #Where NAT prevents a direct connection, traffic goes through a member with a public address.→ From locked-down networks
HTTPS only #From a network that lets only HTTPS out, to every member through one relay on port 443, the ingress's by itself, and through a company's proxy.→ From locked-down networks
Renaming and renumbering #Give the network or a device a new name, or the devices new IPv4 addresses, without setting anything up again.
Key backups #An admin key as one line, for a password manager.
Break-glass #A secret shown once at creation and kept offline ends the network for good, with no admin needed.
Freshness and removal #A removed device learns that it was removed. With vouchers, a device cut off for 48 hours keeps tunnels only to vouchers.

Every feature runs on Linux and FreeBSD unless marked otherwise; the Android app joins as a member.

Publishing services #

A member’s service, such as a NAS at home, can be reached from the internet by name. A device with a public address, the ingress, reads the name the client asks for and passes the connection through the tunnel. TLS ends at the member, so the ingress never sees the content.

  1. browseranywhere

    Asks for docs.example.org.

  2. TLSvpsingress

    Reads the name in the TLS ClientHello and passes the connection on.

  3. WireGuardnastarget

    Terminates TLS with a certificate from Let's Encrypt.

  4. HTTP127.0.0.1:8080service

    Receives the decrypted connection.

The ingress sees the name, the client's address, sizes and timing, not the content.

How to set it up is in the handbook.

Trade-offs #

Without a server in the middle, some things are weaker than with one. Each entry says what can happen, why juist accepts it, and what you can change. All of them are in 02-threat-model.md.

Membership #

Revocation is eventually consistent #

juist admins vouchers M

What happens
A device cut off from the network keeps tunnels to a removed device until it hears of the removal.
Why accepted
There is no server that every device could ask. The freshness lease bounds it: a device no voucher has vouched for in 48 h keeps tunnels only to vouchers.
What you can do
Make always-on devices vouchers, and require M of them, so that the bound holds against M − 1 dishonest ones. A new network has no vouchers, and so no bound.

Losing a quorum of admin keys is final #

more admins than the quorum needs

What happens
With fewer than k admin keys left, no change can be signed again, ever.
Why accepted
A way around the quorum would be one for an attacker too.
What you can do
Give the network more admins than the quorum needs, each with their own devices.

Reachability #

Symmetric NAT everywhere needs a relay #

juist grant vps relay

What happens
Where every device sits behind symmetric NAT, no direct tunnel forms.
Why accepted
The relay is one of your own members and sees only WireGuard ciphertext.
What you can do
Grant relay to a device with a public address.

Public helpers see addresses #

--no-dht --no-stun

What happens
The public BitTorrent DHT and STUN servers see the addresses that use them.
Why accepted
Nothing they return is trusted. A compromised helper can delay connections, but cannot change who belongs to the network.
What you can do
Run juistd without them, and give devices addresses at which they can reach each other.

Cryptography #

A tunnel starts on the group's key #

no setting

What happens
Two devices get their own key one log sync after their tunnel comes up. Until then, their traffic is protected by a key any member could derive.
Why accepted
Against everyone outside the network it is quantum-safe from the start. Only a member, or a device removed since, with a quantum computer could read those first seconds.
What you can do
Nothing; it lasts until the next log sync between the two.