Running in Docker
Two images — which one to run, and what is in each.
MeshHold ships two container images. They run the same daemon, from the same binary; what differs is which of other people's programs are installed beside it.
meshhold:<version>-<arch> |
meshhold:<version>-tools-<arch> |
|
|---|---|---|
| Base | distroless static | Debian slim |
| Size | ~14 MB compressed | many times that |
| Shell | none | yes |
| ffmpeg, LibreOffice | no | yes |
Which one
Take the plain image unless you know you want the other. It is a storage, sync, chat and VPN node, which is most of what MeshHold is, and it is a distroless image with no shell in it — a smaller thing to keep patched and a smaller thing to break into.
Take the -tools image when you want that node to do work on the files
it holds: convert documents, transcode video, make previews, or let office
files reach the search index. Every program on the
external tools page is already in it.
The two are interchangeable at any time. Nothing in a node's data depends on which image wrote it, so swapping the image and restarting is a supported move in both directions — and it is the quickest way to find out whether a job type you are missing is missing for want of a program.
Loading and running
The release publishes each image as a gzipped OCI tarball rather than to a registry:
gunzip -c meshhold-<version>-amd64.tar.gz | docker load
docker run -d --name meshhold \
-p 7777:7777/udp -p 7778:7778 -p 8080:8080 \
-v meshhold-data:/var/lib/meshhold \
-v /srv/meshhold/config.yaml:/etc/meshhold/config.yaml:ro \
-e MESHHOLD_PASSWORD='choose-something' \
meshhold:<version>-amd64
7777/udp (QUIC) and 7778/tcp (the TCP leg, for peers whose UDP does
not get through) are the ports peers reach this node on, and the ones worth
forwarding. A masquerade you enable in node.obfs needs its own port
published as well. 8080/tcp is the Web UI and REST API, and is not
something to expose to the internet without thinking about it first.
/var/lib/meshhold is the volume: the metadata store and the encrypted
blocks. The config file is deliberately not in it — it is a bind mount,
or absent entirely, in which case the daemon comes up in limited mode and
the Web UI walks you through setup.
MESHHOLD_PASSWORD is read once. If the store has no password hash yet, the
daemon writes an Argon2id hash of it on first boot and ignores the variable
from then on, so leaving it in a compose file does not keep resetting
anything.
The -tools image runs identically — same ports, same volume, same
entrypoint — under uid 65532, with HOME inside the volume so that anything
a tool writes for itself survives a restart.
Checking what the node can do
docker exec meshhold meshhold tools --api http://127.0.0.1:8080
On the plain image this lists everything as missing, which is correct and
expected. On the -tools image everything should read yes; anything that
does not is worth reporting, because that image exists precisely so nobody
has to install these by hand.
The same list is in the Web UI under Settings → Tools.
Building the images yourself
build_docker.bat
It expects the Linux binaries to already exist under distr/linux/<arch>/
from build_linux.bat, and deliberately does not build them itself: one Go
binary, several packagers, no chance of the .deb, the .msi and the image
drifting apart in toolchain version or build flags.
The tools image is slow to build — it installs LibreOffice — so
SKIP_TOOLS=1 skips it, and it is built for amd64 only unless you ask for
both:
set TOOLS_ARCHES=amd64 arm64