Install
Install juist as a system package on every device that should be in a network. Each release comes with ready-made packages and a signed list of their checksums.
Supported systems #
juist runs on Linux and FreeBSD. It comes as a .deb for Debian and Ubuntu,
an RPM for Fedora, and a pkg package for FreeBSD 15. Every
release has packages for
amd64 and arm64, except the RPM, which is only available for x86_64. On
another Linux with systemd, Arch or Gentoo say, make install installs it
from the source (Building from source). A phone
joins with the app instead; see Android.
Installing the package #
juist’s package repository installs juist, and the system’s own updates then bring each new release. The repository has the release’s packages for Debian, Ubuntu, Fedora and FreeBSD. To install a single file, take the release’s package instead (From a release).
From the package repository #
On Debian, Ubuntu and Fedora:
curl -fsSL https://juist.nning.io/install | shOn FreeBSD 15, as root:
fetch -o - https://juist.nning.io/install | shThe script adds the repository and its key to apt, dnf or pkg, installs
juist, and on FreeBSD starts the daemon; where it is not root, it takes sudo.
To read it first, download it to install.sh and run sh install.sh. By
hand, the steps are these:
Add the repository and its key, then install juist:
sudo install -d -m 755 /etc/apt/keyrings
sudo curl -fsSL -o /etc/apt/keyrings/juist.gpg https://pkg.juist.nning.io/juist/key.gpg
echo "deb [signed-by=/etc/apt/keyrings/juist.gpg] https://pkg.juist.nning.io/juist/deb/ ./" | sudo tee /etc/apt/sources.list.d/juist.list
sudo apt update && sudo apt install juistThis is the same for amd64 and arm64.
Add the repository, then install juist:
sudo tee /etc/yum.repos.d/juist.repo <<'EOF'
[juist]
name=juist
baseurl=https://pkg.juist.nning.io/juist/rpm
gpgcheck=0
repo_gpgcheck=1
gpgkey=https://pkg.juist.nning.io/juist/key.asc
EOF
sudo dnf install juistThe key signs the repository’s index, which holds each package’s checksum, so the RPM stays the release’s file, unsigned itself.
As root, add the repository and its key, install juist, then start the daemon:
mkdir -p /usr/local/etc/pkg/repos /usr/local/etc/pkg/keys
fetch -o /usr/local/etc/pkg/keys/juist.pub https://pkg.juist.nning.io/juist/freebsd.pub
cat > /usr/local/etc/pkg/repos/juist.conf <<'EOF'
juist: {
url: "https://pkg.juist.nning.io/juist/freebsd/${ABI}",
signature_type: "pubkey",
pubkey: "/usr/local/etc/pkg/keys/juist.pub"
}
EOF
pkg install -r juist juist
sysrc juistd_enable=YES && service juistd startThis is the same for amd64 and arm64; what juist does with pf is under
From a release. sha256 /usr/local/etc/pkg/keys/juist.pub
prints the key’s checksum,
c649f2cd073f9e72825b0c1b8a2682f25c5c55405a178ea6d8a0f8b65ed89e3d.
dnf shows the key’s fingerprint when it imports it, and
gpg --show-keys /etc/apt/keyrings/juist.gpg shows it on Debian and Ubuntu:
1D57474BAAC54CEEAD9168110EBE32412D806005.
From a release #
Download the package and install it:
curl -LO https://github.com/nning/juist/releases/latest/download/juist_amd64.deb
sudo apt install ./juist_amd64.debOn arm64, use juist_arm64.deb.
Install the package:
sudo dnf install https://github.com/nning/juist/releases/latest/download/juist.x86_64.rpmAs root, install the package with pkg, then start the daemon:
pkg add https://github.com/nning/juist/releases/latest/download/juist-freebsd15-amd64.pkg
sysrc juistd_enable=YES && service juistd startOn arm64, use juist-freebsd15-aarch64.pkg. On Linux the package starts the
daemon itself; on FreeBSD you start it once, as shown above.
On FreeBSD, juistd runs pf with rules of its own, which keep the device’s
network addresses to the tunnel: the LAN does not reach them. If the host
loads pf rules of its own, /etc/pf.conf has to call juist’s anchors,
nat-anchor "juist/*", rdr-anchor "juist/*" and anchor "juist/*", before
any rule that passes quick; otherwise juist health warns.
Installing a newer release later replaces the old one, and the device keeps its state; Updating juist has the details. A package from the repository and one from a release are the same, so either updates the other.
Verifying a download #
Each release lists the SHA-256 checksums of its files in SHA256SUMS, signed
with the key in packaging/release-signers.
Put that file, the download, SHA256SUMS and SHA256SUMS.sig in one
directory and run:
ssh-keygen -Y verify -f release-signers -I juist -n juist-release -s SHA256SUMS.sig < SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMSThe first command prints Good "juist-release" signature for juist with ED25519 key SHA256:a2nq8txrPWVfLfF4XGzyKrFo4t71aXkcDOGZNQJABLM, the second prints OK
for each file you downloaded.
Building from source #
Building needs Go 1.21 or newer and make. make has Go download go1.27.3
and builds with it, so that a given commit produces the same bytes on any
machine.
git clone https://github.com/nning/juist
cd juist
make install # gmake install, as root, on FreeBSDmake install builds the package for the system it runs on (the .deb on
Debian and Ubuntu, the RPM on Fedora, the pkg package on FreeBSD) and installs
it. Run it again later to install a new build over the old one.
Where there is neither apt, dnf nor pkg, on another Linux with systemd,
make install installs the RPM’s files to the same places itself, creates
the juist user and starts juistd. It does not install over a juist from
a package. make uninstall removes them again, and without the source tree
sudo /usr/lib/juist/manual-install.sh uninstall; the users and
/var/lib/juist, which holds the device’s keys, stay.
To install juist on a machine that should not build it, build only the package and copy it over:
| System | Build | Install on the other machine |
|---|---|---|
| Debian, Ubuntu | make deb | sudo apt install ./juist_*.deb |
| Fedora | make rpm | sudo dnf install ./juist-*.rpm |
| FreeBSD | make pkg-freebsd | pkg add ./juist-*.pkg |
The packages end up in build/deb, build/rpm/RPMS and build/freebsd.
make deb DEB_ARCH=arm64 builds the .deb for another architecture; armhf
and i386 work the same way.
In a container #
An app in a container can be a device of its own, with its own addresses and
its own place in the access policy: juistd
runs in a second container that shares the app’s network namespace and makes
juist0 there. Whatever the app opens to a member’s address goes through the
tunnel. The image comes from make image in the source tree, followed by
docker load.
juist invite appIn a compose.yaml, a service of its own, netns, holds the namespace, so
that juist and the app keep it when either restarts; JUIST_JOIN takes the
invite link:
services:
netns:
image: registry.k8s.io/pause:3.10
restart: unless-stopped
juist:
image: juist:VERSION
network_mode: service:netns
user: "0:0"
cap_drop: [ALL]
cap_add: [NET_ADMIN]
devices: [/dev/net/tun]
environment:
JUIST_JOIN: "juist:…"
volumes:
- type: volume
source: juist
target: /var/lib/juist
volume:
nocopy: true
restart: unless-stopped
app:
image: … # the app
network_mode: service:netns
depends_on: [juist]
restart: unless-stopped
volumes:
juist: {}docker compose up -ddocker compose logs juist shows how the join went, and
docker compose exec juist juist status the device’s addresses. Once
joined, the link is spent and JUIST_JOIN ignored.
- juistd needs
CAP_NET_ADMINand/dev/net/tun, notprivileged. Docker gives a capability to root alone, so juistd runs as root there, with no other capability, on a volume of root’s:nocopykeeps the image’s user from owning it. Podman gives it to the image’s own user; add the example’scompose.podman.yamlthere. - The network’s names do not resolve in the containers, which have no
systemd-resolved, and
juist healthsays so. Use the addressesjuist deviceslists, or put names in the namespace’s/etc/hostswithextra_hostsonnetns, with the IPv6 address, which renumbering does not change. - If
netnsrestarts,docker compose restart netnsrestarts juist and the app with it; they are left in its old namespace otherwise. - A Tailscale container in userspace mode can hold the namespace instead of
netns, withnetwork_mode: service:tailscale; the two do not get in each other’s way.
The same with comments, an .env and Podman’s override:
examples/sidecar
in the repository.
What the package installs #
- The command
juistand the daemonjuistd. How juist works explains which does what. - On Linux, the
juistdservice. It starts right away and waits until you create or join a network. It runs as the userjuist, with onlyCAP_NET_ADMIN, plusCAP_NET_BIND_SERVICEon a relay on port 443. Further networks run as the usersjuist1tojuist9, which the package also creates. - On Linux, two more services:
juist-ingressfor an ingress, started byjuist ingress serve, andjuist-serve, juist’s TLS terminator, which systemd starts whenjuist publishorjuist shareneeds it. - Firewall profiles for ufw and firewalld:
juist,juist-relay,juist-relay-443,juist-inviteandjuist-ingress. If ufw or firewalld runs, the package also allows traffic onjuist0, which log sync and published services need. It does this only on the first install, so an upgrade leaves your firewall alone. - A polkit rule that lets juistd set the network’s DNS through
systemd-resolved. It needs polkit, which the package recommends; minimal
installs such as Fedora Cloud lack it. On Ubuntu 22.04, whose polkit reads
no rules, the .deb puts the same permission in
/var/lib/polkit-1/localauthority/10-vendor.d/60-juist.pkla. - Shell completion for bash, zsh and fish, and the man pages
juist(1)andjuistd(8).
To check that the daemon is running:
$ juist status
nas · no network
Next, create your first network.
Uninstalling #
To leave a network but keep juist installed, run juist reset instead; see
Removing a device.
If the device is in a network, take it out of the network first, so that the
network does not keep listing it: an admin runs juist remove nas on their
own device. Then remove the package:
sudo apt remove juist # Debian, Ubuntu
sudo dnf remove juist # Fedora
pkg delete juist # FreeBSD, as rootThis stops juistd for every network on the device and undoes what juist set
up on the host. On Linux, that is the firewall rule for juist0, an ingress,
a relay on port 443, and the changes made by juist exit serve.
What stays after uninstalling #
- On Linux, the device’s keys and log stay in
/var/lib/juist, a further network’s in/var/lib/juist1and so on, and the system usersjuist,juist1tojuist9,juist-ingressandjuist-servestay too. On Debian and Ubuntu,sudo apt purge juistremoves each of these directories only if it is empty, and otherwise says:juist: kept /var/lib/juist, which still holds this device's keys and log. /var/lib/juist-servestays as well (on FreeBSD,/var/db/juist-serve). It holds the TLS terminator’s ACME account, which the CAA records of your published names may refer to.sudo apt purge juiston Debian and Ubuntu, andsudo dnf remove juiston Fedora, say so:juist: kept /var/lib/juist-serve, the terminator's ACME account, which CAA records may name.- On FreeBSD, the removal prints a single line starting with
juist: keptthat lists everything that stays. - Your admin keys in
~/.config/juistare not part of the package, so removing it does not touch them.
Troubleshooting #
make installsaysmake install knows apt (Debian, Ubuntu), dnf (Fedora) and pkg (FreeBSD); use make deb, rpm or pkg-freebsd: this system uses none of these package managers. Build the package for one of the supported systems and install it there.juist statussaysjuist0 · not running, or on FreeBSD before juistd is enabledjuistd not running: start the daemon withsudo systemctl enable --now juistd, or on FreeBSD, as root, withsysrc juistd_enable=YES && service juistd start.- On Linux,
journalctl -u juistdshows the daemon’s log; on FreeBSD it is/var/log/juistd.log.