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.
$ 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.
| Feature | What 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.
- browseranywhere
Asks for docs.example.org.
- TLSvpsingress
Reads the name in the TLS ClientHello and passes the connection on.
- WireGuardnastarget
Terminates TLS with a certificate from Let's Encrypt.
- HTTP127.0.0.1:8080service
Receives the decrypted connection.
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
relayto 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.