Skip to content

Command line

github-actions[bot] edited this page Oct 14, 2026 · 5 revisions

Every command of mistgate and mistgate-node, with its flags, environment variables, defaults and examples.

Mistgate has two binaries: mistgate is the panel, mistgate-node is the node agent. Both take a command and then flags. Flags can be written with one dash or two (-data-dir or --data-dir); this page uses two. <command> -h prints the flags of a command.

Many flags fall back to an environment variable. A flag given on the command line wins over the variable. Every flag and variable of serve and setup is also described, with the layout of the data directory, in Configuration.

mistgate

Command What it does
serve Runs the panel.
setup Creates the data directory, the master key and the database; prints the admin URL and a one-time setup link.
backup keygen Makes the private recovery identity for encrypted panel backups and prints its public recipient.
backup restore Decrypts a downloaded panel backup into a new data directory, offline.
auth turnstile off Switches the Cloudflare captcha off on the sign-in and setup pages.
auth reset-login Gives an admin a new password and authenticator app, or adds a password login.
mcp A local stdio proxy to the panel's MCP endpoint, for agent clients that cannot speak HTTP.
release keygen Makes the owner's release key.
release build Builds release binaries the one reproducible way (CI and make build use it).
release sign Rebuilds the binaries and the edge bundle from the release tag, then signs the node bundle, the panel manifest and the edge manifest.
release trust-key On the panel server, after a key rotation: makes the binary's release key the installation's key.
edge deploy Deploys the Cloudflare edition (the panel on Cloudflare Workers) to your Cloudflare account. A preview.
edge setup-link Prints the one-time setup link from the key file that edge deploy wrote.
version Prints the version, the build time and the release key fingerprint.

mistgate exits with 0 on success, 1 on an error (printed as mistgate: <error>) and 2 for an unknown command or a missing one.

There is also a hidden command, panel-update-helper. Only the panel's updater starts it, as root: as a transient systemd unit when the panel itself runs as root, otherwise through the fixed root unit mistgate-panel-update.service. It is not meant to be run by hand; see Updates.

mistgate serve

Runs the panel in the foreground. Run it under systemd or another supervisor. Outside development mode it needs an installation made by mistgate setup.

mistgate serve --listen :443 --acme-domain panel.example.com
Flag Environment Default Meaning
--listen MISTGATE_LISTEN 127.0.0.1:8080 Address of the public listener: the decoy site, subscriptions, the admin (when it lives under a secret prefix or host) and the agent endpoint.
--data-dir MISTGATE_DATA_DIR /var/lib/mistgate (./.data with --dev) Data directory.
--tls-cert, --tls-key MISTGATE_TLS_CERT, MISTGATE_TLS_KEY none Your own certificate and key for the public listener. Given together. The certificate is reloaded when the file changes.
--acme-domain MISTGATE_ACME_DOMAIN (comma-separated) none Get a Let's Encrypt certificate for this host name. Repeatable. The public listener must be reachable on port 443. Using it accepts the CA's terms of service. The certificates are kept in <data-dir>/acme.
--acme-email MISTGATE_ACME_EMAIL none Contact address for Let's Encrypt.
--acme-http MISTGATE_ACME_HTTP :80 Listener for the ACME HTTP-01 challenge and the http → https redirect, used with --acme-domain. Empty switches it off.
--admin-listen MISTGATE_ADMIN_LISTEN the stored setting Separate admin listener (plain HTTP). Only for an installation set up with setup --admin-listen; anything else is refused at start.
--agent-listen MISTGATE_AGENT_LISTEN none (127.0.0.1:8082 with --dev) A separate TLS listener for the node agents. Without it agents use the public listener with the secret TLS name, which needs TLS on it (--tls-cert or --acme-domain).
--agent-addr MISTGATE_AGENT_ADDR --agent-listen when it names a host, else the public URL's host and port (443 when none) The host:port agents dial; it goes into the install command.
--decoy-dir MISTGATE_DECOY_DIR the built-in page A directory with your own decoy site. 404.html and 429.html in it replace the built-in error pages.
--trusted-proxy MISTGATE_TRUSTED_PROXY (comma-separated) none CIDR or IP of a reverse proxy whose X-Forwarded-For and Forwarded headers are believed. Repeatable. Without it the TCP peer is the client.
--update-service MISTGATE_UPDATE_SERVICE mistgate.service (none with --dev) The panel's own systemd unit, which the panel updater stops and starts again around the binary swap. Used when the panel runs as root; a panel running as another user starts the fixed root helper unit, whose command line names the unit itself.
--source-url MISTGATE_SOURCE_URL https://github.com/Mistgate/mistgate Where the source code of this build is published, linked next to the version in the admin (AGPL-3.0 section 13). A fork points it at its own repository; an empty value hides the link.
--dev MISTGATE_DEV (1, true, yes, on) off Development mode, see below.

Development mode. --dev uses ./.data, serves plain HTTP with the decoy on 127.0.0.1:8080 and the admin on 127.0.0.1:8081, puts the agent endpoint on 127.0.0.1:8082, uses localhost as the WebAuthn relying party, needs no setup, and prints a one-time setup link (http://localhost:8081/setup#…, valid 30 minutes) while no admin exists. Never use it on a server.

mistgate setup

Prepares a new installation: creates the data directory (mode 0700), the master key and the database, stores where the admin is reached, and prints how to get there. It is safe to run again: an existing configuration is kept, and a new setup link is issued only while no admin exists (earlier unused links stop working). When the database exists but master.key is missing, it refuses and asks for the key from your backup instead of creating a new one.

mistgate setup --public-url https://panel.example.com
Data dir:   /var/lib/mistgate
Admin URL:  https://panel.example.com/<secret prefix>/
Setup link: https://panel.example.com/<secret prefix>/setup#<token>
The link works once and expires in 30 minutes. Open it in a browser and create your admin (a passkey, or a password with an authenticator code).
Flag Environment Default Meaning
--data-dir MISTGATE_DATA_DIR /var/lib/mistgate Data directory (database, master key).
--public-url MISTGATE_PUBLIC_URL none URL of the public (decoy) site, for example https://panel.example.com. Also the base of the subscription links.
--admin-host MISTGATE_ADMIN_HOST none Serve the admin on this secret host name instead of a secret path prefix.
--admin-listen MISTGATE_ADMIN_LISTEN none Serve the admin on a separate listener, for example 127.0.0.1:8081. Cannot be combined with --admin-host.
--rp-id MISTGATE_RP_ID derived WebAuthn relying party id.
--rp-origins MISTGATE_RP_ORIGINS derived Comma-separated allowed WebAuthn origins.

One of --public-url, --admin-host or --admin-listen is required. Where the admin ends up:

Given Admin URL WebAuthn relying party
--public-url only <public url>/<24 random characters>/ the public host
--admin-host admin-k7q2.example.com https://admin-k7q2.example.com/ (scheme and port of --public-url when given) the admin host
--admin-listen 127.0.0.1:8081 http://localhost:8081/ localhost

Setup also generates the secret TLS name of the agent endpoint and the secret prefix of the subscription links. These settings cannot be changed by running setup again.

mistgate backup

The two offline commands of encrypted panel backups. The backups themselves are made by the running panel (Settings → Backups); these commands never talk to it or to the bucket.

mistgate backup keygen --identity-file FILE
mistgate backup restore --identity-file FILE --file BACKUP.tar.gz.age --data-dir NEW-DIR
Flag Meaning
keygen --identity-file Where to write the private age recovery identity. The file must not exist: an existing one is never overwritten. Missing parent directories are created with mode 0700, the file gets mode 0600.
restore --identity-file The private identity made by backup keygen.
restore --file The encrypted backup downloaded from the bucket (.tar.gz.age).
restore --data-dir A new directory for the restored data; it must not exist yet.

All flags are required; there are no environment variables. backup keygen runs once, on a trusted computer that is not the panel server. It prints the path and the public recipient (age1…) that goes into Settings → Backups; keep the identity file offline.

backup restore needs no network and no running panel. It decrypts the archive, checks every file against the archive's manifest, checks the master key and the database (an archive from a newer Mistgate, whose database this binary does not know, is refused with the version that made it; the database must pass an integrity check), unpacks into a temporary directory next to the target and renames it into place only when everything passed. Point serve --data-dir at the new directory; when systemd hands the panel master.key through LoadCredential=, replace that credential with the restored key first.

mistgate backup restore --identity-file ./mistgate-recovery.txt \
  --file ./backup.tar.gz.age --data-dir /var/lib/mistgate-restored

mistgate auth

Commands for the operator on the panel server. Both work with the panel stopped or running: it reads these settings on every request.

mistgate auth turnstile off [--data-dir DIR]
mistgate auth reset-login [<login>] [--admin ID] [--qr-invert] [--data-dir DIR]
Flag Environment Default Meaning
--data-dir MISTGATE_DATA_DIR /var/lib/mistgate (./.data with --dev) Data directory. The command refuses a directory without a panel database.
--dev MISTGATE_DEV off A development installation: data in ./.data.
--admin none none reset-login only: the admin id whose new password login this is.
--qr-invert none off reset-login only: draw the QR code for a light terminal background.

auth turnstile off switches the Cloudflare check off on the sign-in and setup pages; the keys stay stored. It is the way back in when Cloudflare is unreachable or the keys are wrong. Switch it on again in Settings → Security.

auth reset-login is the way back in after a lost phone:

  • mistgate auth reset-login lists the admins of the panel with their id, name, role, login and number of passkeys.
  • mistgate auth reset-login <login> gives that login a new password and a new authenticator app, lifts its lockouts and ends every session of that admin. Passkeys stay.
  • mistgate auth reset-login <new login> --admin <id> gives an admin who has passkeys only a password login (--admin picks which admin when there are several).

It prints the login, the new password, and the authenticator key as a QR code drawn in the terminal, as text in groups of four, and as an otpauth:// link. The password is shown only once. It needs the master key, so run it as the user that can read the data directory. Both commands are written to the audit log as "command line".

mistgate auth reset-login alice

mistgate mcp

A local MCP server on stdin and stdout for agent clients that can only start a command. It forwards every message to the panel's MCP endpoint (the admin URL plus mcp) and decides nothing itself: the panel answers, with the token's profile.

mistgate mcp --url https://panel.example.com/<prefix>/ --token-file ~/.config/mistgate/token
Flag Environment Meaning
--url MISTGATE_URL The admin URL that mistgate setup printed. Plain http is refused unless the host is localhost or a loopback address. The URL must not carry credentials, a query or a fragment.
--token-file MISTGATE_TOKEN_FILE A file whose first line is an API token (tk1_…). The token is read only from the file, never from the command line or the environment, and never printed. A warning is printed when others can read the file.

The proxy stops when the panel refuses the token (expired, revoked or the wrong profile). stdout carries only protocol messages; everything else goes to stderr. See MCP.

mistgate release keygen

mistgate release keygen --out ~/mistgate-release.key
Flag Meaning
--out File for the private key. It must not exist: an existing key is never overwritten. The file gets mode 0600.

Prints the public key and its fingerprint. Put the public key into the build: RELEASE_KEY=<public key> make build. Keep the key file offline and back it up. See Releases and signing.

mistgate release build

mistgate release build --version V [--built UNIX] [--key PUBLIC] [--source DIR] NAME... --out DIR
Flag Default Meaning
--version none Version stamped into the binaries, for example v0.1.4.
--built commit time of --source Unix time of the source commit; it orders releases.
--key none The release public key (base64). Without it the binaries cannot update themselves.
--source . The source checkout.
--out none Directory for the binaries.

NAME is mistgate-linux-amd64, mistgate-linux-arm64, mistgate-node-linux-amd64, mistgate-node-linux-arm64 or mistgate-edge.tar.gz (the Cloudflare edition: the five role wasm files, the six Worker scripts bundled with the pinned esbuild, web/dist and edge.json, in a deterministic tarball; it needs pnpm install --frozen-lockfile in edge/worker besides the SPA). The build is reproducible: CGO_ENABLED=0, -trimpath, -buildvcs=false, the Go toolchain named in go.mod (downloaded when the local Go is another version), GOAMD64=v1/GOARM64=v8.0 and the version, build time and key as the only -ldflags values. The panel binary embeds web/dist: build the SPA first (cd web && pnpm install --frozen-lockfile && pnpm build). The release workflow and make build call this command; it prints the SHA-256 of every binary.

mistgate release sign

mistgate release sign --key FILE --version V [--built UNIX] [--expires 30d] [--source DIR] BINARY... --out DIR
Flag Default Meaning
--key none The release private key file made by release keygen.
--version none The release tag, for example v0.1.4.
--built commit time of the tag When given, it must be the commit time of the tag.
--expires 30d How long the manifests stay installable: days (30d) or a Go duration (720h).
--source . A clean checkout of the tag --version (local changes to tracked files are refused).
--out none Directory for the manifests, their signatures and the copies of the binaries.

The binaries are named <name>-<os>-<arch>: mistgate-node-linux-* go into the node bundle (manifest.json, manifest.sig), mistgate-linux-* into the panel manifest (panel-manifest.json, panel-manifest.sig, signed in a separate Ed25519 context so neither verifies as the other). Before signing, the command rebuilds every binary from --source with release build and the public half of --key, and refuses any binary that differs byte for byte: you sign what the tag builds to, not what a CI runner uploaded. mistgate-edge.tar.gz given too is rebuilt the same way and gets its own edge-manifest.json and edge-manifest.sig, signed in a third context. Flags may come after the binaries. The command verifies what it wrote and prints every file with its size and the key fingerprint. A signer built locally from any version works: go build -o mistgate ./cmd/mistgate.

mistgate release sign --key ~/mistgate-release.key --version v0.1.4 --source ~/src/mistgate \
  downloaded/mistgate-node-linux-amd64 downloaded/mistgate-node-linux-arm64 \
  downloaded/mistgate-linux-amd64 downloaded/mistgate-linux-arm64 --out signed

See Releases and signing for the whole release.

mistgate release trust-key

mistgate release trust-key [--data-dir DIR] [--dev]

Run on the panel server, as the panel's service user or root, after you rotated the release key and installed a panel built with the new key. It writes the key compiled into this binary to <data-dir>/release.pub and prints the old and new fingerprints. Until then a panel whose compiled-in key differs from release.pub logs an error and trusts no bundle. Restart the panel afterwards. --data-dir falls back to MISTGATE_DATA_DIR, then /var/lib/mistgate; --dev (or MISTGATE_DEV) means ./.data. A binary built without a release key refuses.

mistgate edge

mistgate edge deploy --host HOST [--name NAME] [--d1-location LOC] [--bundle DIR | --version vX.Y.Z] [--resume] [--dry-run] [--insecure-skip-signature]
mistgate edge deploy --host HOST [--name NAME] --rollback [--dry-run]
mistgate edge setup-link --file FILE

edge deploy creates the D1 database and the six Worker scripts of the Cloudflare edition, attaches HOST as a custom domain and prints the admin address and a one-time setup link. It reads the API token only from CLOUDFLARE_API_TOKEN, and writes the keys of the new panel to mistgate-edge-<name>.json in the current directory: back that file up. --dry-run only reads from Cloudflare and prints the plan; --resume continues a run that stopped. Run again without --resume, it updates the deployment and uploads only the scripts that changed; --rollback puts every script back on the version it had before the last update. edge setup-link prints the stored setup link of a key file. Every flag, the token's permissions and the first sign-in are in Install the Cloudflare edition.

mistgate version

Prints mistgate <version>, then built <time> when the binary was built with a build time, then release key <fingerprint>, or release key: none (unsigned build, nodes are updated by hand).

mistgate-node

Command What it does
enroll Exchanges a one-time token for a node certificate.
install Writes the hardened systemd unit, enables and starts it.
run Runs the agent in the foreground.
cleanup-net Removes the agent's tunnel interfaces, WARP routes and nftables tables.
awg prepare-kernel Installs the AmneziaWG kernel module.
version Prints the version, the build time and the release key fingerprint.

enroll and run take --state-dir; give them the same directory. Exit codes: 0 success, 1 an error, 2 bad usage, 78 from run when the node is not enrolled (systemd does not restart the agent then).

The panel shows the whole install command when you add a node:

chmod +x /root/mistgate-node && /root/mistgate-node enroll --panel panel.example.com:443 --sni <secret name> \
  --ca-sha256 <fingerprint> --token <one-time token> && /root/mistgate-node install

mistgate-node enroll

Flag Environment Default Meaning
--panel MISTGATE_PANEL none Panel address, host:port.
--sni MISTGATE_AGENT_SNI none The secret TLS name of the panel's agent endpoint.
--ca-sha256 MISTGATE_CA_SHA256 none SHA-256 fingerprint of the panel's CA certificate (64 hex digits). The agent trusts the panel only by it.
--token MISTGATE_ENROLL_TOKEN none The one-time enrollment token. The variable keeps it out of the process list.
--token-stdin none off Read the token from stdin instead (one line, at most 256 bytes): it stays out of the process list and the shell history. Cannot be combined with --token or MISTGATE_ENROLL_TOKEN.
--state-dir MISTGATE_NODE_STATE_DIR /var/lib/mistgate-node State directory.
--force none off Replace an existing identity.
--resume-key none off Keep the new private key in enroll-pending.pem in the state directory until enrollment succeeds and use it again on the next try, so an interrupted enrollment can be retried: the panel answers a repeat with the same token and key within 10 minutes with the same certificate. With --force a new key is made.

--panel, --sni, --ca-sha256 and a token (--token, MISTGATE_ENROLL_TOKEN or --token-stdin) are required; without them enroll exits with 2. A token works once, within the time the panel showed (an hour by default). The panel's SSH install runs the same enroll and install over SSH, with the token on stdin and --token-stdin --resume-key. On success it prints the node id and the next step:

enrolled as nod_… with panel.example.com:443; state in /var/lib/mistgate-node
next: mistgate-node install   (or, in the foreground: mistgate-node run)

mistgate-node install

Linux only, as root, after enroll.

Flag Environment Default Meaning
--state-dir MISTGATE_NODE_STATE_DIR /var/lib/mistgate-node State directory; must be the one enroll used.
--bin none /usr/local/bin/mistgate-node Where the binary lives. The running binary is copied there if it is elsewhere.
--no-start none off Write and enable the unit, but do not start it.

It writes /etc/systemd/system/mistgate-node.service, then runs systemctl daemon-reload, enable and restart. The unit:

  • runs the agent as root with only two capabilities (network administration and binding low ports) and a read-only system, except the state directory, the binary's directory (for self-update), /etc/sysctl.d and /etc/systemd/journald.conf.d;
  • sizes its memory limits from the server's RAM;
  • restarts the agent 5 seconds after a failure, but not after exit code 78;
  • before every start, puts the previous binary back after a crash loop of a fresh update; after every stop, runs cleanup-net.

Running install again with a new binary is how a node is updated by hand (see Updates). Paths may contain only letters, digits and _ . / -.

mistgate-node run

Runs the agent in the foreground: what the unit does, and a way to try the agent without systemd.

Flag Environment Default Meaning
--state-dir MISTGATE_NODE_STATE_DIR /var/lib/mistgate-node State directory.
--log-level MISTGATE_LOG_LEVEL info debug, info, warn or error.
--log-format MISTGATE_LOG_FORMAT text text or json. Logs go to stderr.

It exits with 78 when the state directory holds no identity, and with 0 when the panel retired the node.

mistgate-node cleanup-net

Takes no arguments. Removes the tunnel interfaces of the agent, its tunnel nftables table and, when present, the WARP device, routes, rules and table. It needs no state and no panel. The unit runs it after every stop; the agent creates everything again when it starts.

mistgate-node awg prepare-kernel

Puts the AmneziaWG kernel module on the node. Linux only, as root. The default userspace backend needs no module.

mistgate-node awg prepare-kernel          # prints the plan, runs nothing
mistgate-node awg prepare-kernel --yes    # runs it
Flag Default Meaning
--yes off Run the commands. Without it the plan is only printed.
--verify-only off Only check a module that is already installed (loaded, the right interface version, loaded at boot).
--status-file none Write progress and the result to this file (used by the agent when the panel asks it to prepare the module).
--timeout 45m Hard limit of the run.

It installs packages with apt (non-interactive, waiting up to 30 minutes for another package manager's lock). Supported: Debian and Ubuntu, not a container, without Secure Boot, with systemd. See AmneziaWG.

mistgate-node version

Prints mistgate-node <version>, built <unix time>, and release key <fingerprint> or release key none (unsigned build: update by hand).


Edit this page · View on mistgate.app

Mistgate

English

Getting started

Guide

Operations

Roadmap

Reference

Русский

Начало работы

Руководство

Эксплуатация

План развития

Справочник

简体中文

入门

使用指南

运维

路线图

参考

Clone this wiki locally