General-purpose Hotline server / tracker container images. They're usable for real deployments, and are also what GtkHx's CI pulls instead of rebuilding on every run.
Image (images/<dir>) |
Published tag | Default ports | Role |
|---|---|---|---|
mhxd |
mhxd |
5500 / 5501 | Hotline server (mhxd) |
janus |
janus |
5500 / 5501 (+TLS) | Hotline server (VesperNet Janus) |
argus |
argus |
5498 tcp / 5499 udp | Tracker (v1/v2/v3, VesperNet Argus) |
hxtrackd |
hxtrackd |
5498 tcp / 5499 udp | Tracker (pre-spec v1, mhxd's hxtrackd) |
Each image runs a general default config (features off, conventional
ports, no seeded content). Customise at runtime with env vars or by
mounting your own config — see below and each image's README.md.
All servers accept a mounted config file (over the image's default) and a few env knobs applied by the entrypoint:
- Janus —
JANUS_PORT,JANUS_TLS_PORT,JANUS_ENABLE_HOPE,JANUS_ENABLE_CHAT_HISTORY,JANUS_ENABLE_VOICE,JANUS_TLS_CERT/JANUS_TLS_KEY,TRACKERS. - mhxd —
TRACKERS,BANNER_MODE/BANNER_URL/BANNER_FILE. - Argus —
ARGUS_TCP_PORT,ARGUS_UDP_PORT. - hxtrackd — none (its ports are hardcoded); mount
hxtrackd.confto tune the drop interval etc.
Janus serves TLS when given a cert + key. Mount them and point Janus at them — no image rebuild, and certbot renewals are picked up on restart:
docker run -d --network host \
-v /etc/letsencrypt/live/example.com:/certs:ro \
-e JANUS_TLS_CERT=/certs/fullchain.pem \
-e JANUS_TLS_KEY=/certs/privkey.pem \
ghcr.io/mishan/janusGitHub Container Registry (GHCR), under the repo owner's namespace:
ghcr.io/mishan/mhxd:latest
ghcr.io/mishan/janus:latest
ghcr.io/mishan/argus:latest
ghcr.io/mishan/hxtrackd:latest
Each is also tagged with the commit SHA; server images get the git tag
name on v* releases. Two workflows publish (both push with the built-in
GITHUB_TOKEN — enable packages: write, already declared):
.github/workflows/publish-images.yml— the five server/proxy images, matrix-built with per-image GHA layer caching. Triggers onimages/**changes, weekly, and manually.
After the first run, make the packages public (or grant readers) on GHCR so they can be pulled without auth — new packages are private by default.
Each image is an independent server — run whichever one you need on its own. A typical deployment is a single server on its conventional port:
# mhxd Hotline server
docker run -d -p 5500:5500 -p 5501:5501 ghcr.io/mishan/mhxd
# Janus Hotline server (with HOPE + a Let's Encrypt cert)
docker run -d --network host \
-v /etc/letsencrypt/live/example.com:/certs:ro \
-e JANUS_ENABLE_HOPE=true \
-e JANUS_TLS_CERT=/certs/fullchain.pem \
-e JANUS_TLS_KEY=/certs/privkey.pem \
ghcr.io/mishan/janus
# Argus tracker
docker run -d -p 5498:5498 -p 5499:5499/udp ghcr.io/mishan/argus
# hxtrackd tracker
docker run -d -p 5498:5498 -p 5499:5499/udp ghcr.io/mishan/hxtrackdTo have a server register with a tracker, pass TRACKERS (mhxd/Janus) —
see each image's README.md. Use --network host for Janus if you're
running its WebRTC voice path.