Skip to content

CLI reference

This reference reflects the current code in cmd/mytunnel, cmd/mytunneld, and scripts.

Top-level usage:

usage: mytunnel <http|ls|stop|rm|doctor> [args]

Version:

Terminal window
mytunnel --version
mytunnel -v

Usage:

mytunnel http <local_port> [flags]

Starts a tunnel to a local HTTP service.

FlagDefaultMeaning
--edge <host>requiredSSH destination for the edge.
--ssh-bin <path>sshSSH binary.
--no-ssh-muxfalseDisable SSH muxing for short control commands.
--remote-bin <path>mytunneldRemote daemon binary.
--name <slug>generatedRequested slug.
--owner <owner>local user envCompatibility only; server ignores it.
--forcefalseForce-replace existing active slug, admin users only.
--ttl <duration>daemon defaultRequested lease TTL.
--reconnecttrueReconnect SSH tunnel when dropped.

Remote config override flags are also accepted: --db-path, --base-domain, --caddy-admin-url, --caddy-server, --min-port, --max-port, --lease-ttl, --cleanup-interval, --reconcile-interval, --health-timeout, --log-format, and --max-leases-per-owner.

Example:

Terminal window
mytunnel http 3000 --edge mytunnel-edge --base-domain tunnel.example.com --name portal

Success output:

url: https://portal.tunnel.example.com
lease: <id>

Usage:

mytunnel ls [flags]

Lists leases owned by the SSH user.

Flags:

FlagMeaning
--edge <host>SSH destination for the edge.
--jsonEmit JSON output.
common remote flagsSame remote flags as http.

Example:

Terminal window
mytunnel ls --edge mytunnel-edge --json

JSON shape:

[
{
"lease_id": "lease_test",
"slug": "demo",
"host": "demo.tunnel.example.com",
"owner": "alice",
"edge_bind_port": 21000,
"created_at": "2026-05-05T12:00:00Z",
"updated_at": "2026-05-05T12:00:00Z",
"expires_at": "2026-05-05T12:02:00Z",
"state": "active"
}
]

Usage:

mytunnel stop <lease_id|host> [flags]

Releases an active lease.

Example:

Terminal window
mytunnel stop lease_test --edge mytunnel-edge

Text output:

released lease_test (released-lease_test.invalid)

Usage:

mytunnel rm <lease_id|host|slug> [flags]

Deletes a lease by ID, host, or slug.

Example:

Terminal window
mytunnel rm portal --edge mytunnel-edge --json

Usage:

mytunnel doctor [flags]

Runs edge health and dry-run reconcile checks.

Example:

Terminal window
mytunnel doctor --edge mytunnel-edge
mytunnel doctor --edge mytunnel-edge --json

JSON shape:

{
"status": "ok",
"edge": "mytunnel-edge",
"checked_at": "2026-05-05T12:00:00Z",
"findings": [],
"health": {
"status": "ok",
"checked_at": "2026-05-05T12:00:00Z",
"checks": [],
"stats": {}
}
}

Top-level usage:

usage: mytunneld <serve|ctl> [args]
ctl subcommands: allocate, heartbeat, release, delete, list, health, reconcile, stats

Version:

Terminal window
mytunneld --version
mytunneld -v

Runs the daemon loop. The systemd unit normally starts this command.

Required:

  • --base-domain <domain> or MYTUNNEL_BASE_DOMAIN

Config flags:

FlagEnv keyDefault
--db-pathMYTUNNEL_DB_PATH/var/lib/mytunneld/leases.db
--base-domainMYTUNNEL_BASE_DOMAINnone
--caddy-admin-urlMYTUNNEL_CADDY_ADMIN_URLhttp://127.0.0.1:2019
--caddy-serverMYTUNNEL_CADDY_SERVERsrv0
--min-portMYTUNNEL_MIN_PORT20000
--max-portMYTUNNEL_MAX_PORT29999
--lease-ttlMYTUNNEL_LEASE_TTL2m
--cleanup-intervalMYTUNNEL_CLEANUP_INTERVAL30s
--reconcile-intervalMYTUNNEL_RECONCILE_INTERVAL60s
--health-timeoutMYTUNNEL_HEALTH_TIMEOUT5s
--log-formatMYTUNNEL_LOG_FORMATtext
--max-leases-per-ownerMYTUNNEL_MAX_LEASES_PER_OWNER5
--admin-usersMYTUNNEL_ADMIN_USERSempty

Usage shape:

Terminal window
mytunneld ctl allocate --local-port 3000 --name portal

Flags:

FlagMeaning
--local-port <port>Required local port metadata.
--name <slug>Requested slug.
--owner <owner>Ignored; owner is SSH OS user.
--forceAdmin-only active slug takeover.
--ttl <duration>Lease TTL.

Returns a TunnelLease JSON object.

Terminal window
mytunneld ctl heartbeat --lease <lease_id|host> --ttl 2m

Refreshes an owner-scoped lease.

Terminal window
mytunneld ctl release --lease <lease_id|host>

Removes the Caddy route and tombstones the lease.

Exactly one of --lease or --slug is required.

Terminal window
mytunneld ctl delete --lease <lease_id|host>
mytunneld ctl delete --slug portal
Terminal window
mytunneld ctl list

Returns JSON leases owned by the caller.

Terminal window
mytunneld ctl health
mytunneld ctl health --json

Text output includes one line per check.

Terminal window
mytunneld ctl reconcile --dry-run --json
mytunneld ctl reconcile --apply --json

--apply and --dry-run are mutually exclusive. Without either flag, the command reports dry-run mode.

Terminal window
mytunneld ctl stats
mytunneld ctl stats --json

Stats include cleanup and reconcile counters plus last-run timestamps when available.

ScriptMutates hostPurpose
scripts/install-edge.shyesapt-based edge install with optional Infomaniak Caddy bootstrap.
scripts/bootstrap-edge.shyesInstall daemon binary, env file, data dir, and systemd service.
scripts/install-edge-ssh-key.shyesInstall forced-command SSH key for a tunnel user.
scripts/install-local.shyesInstall client binary to /usr/local/bin/mytunnel.
scripts/install-client.shyesCompatibility wrapper around install-local.sh.
scripts/check-edge.shnoRead-only edge diagnostics.
scripts/check-client.shnoRead-only client diagnostics.
scripts/upgrade-edge.shyesEdge binary upgrade with backup, verification, and rollback.
scripts/upgrade-local.shyesClient binary upgrade.
scripts/uninstall-edge.shyesRemove edge service/binary/config, optionally data. Supports dry-run.
scripts/uninstall-local.shyesRemove local client binary. Supports dry-run.
scripts/test-ssh-gate.shnoTest forced-command gate behavior locally.
scripts/real-system-validation.shyes on test leaseEnd-to-end tunnel validation against a real edge.

mytunneld writes JSON error envelopes to stderr:

{
"error_code": "permission_denied",
"message": "permission denied",
"details": {}
}

Known codes:

CodeMeaning
lease_not_foundLease ID, host, or slug did not resolve.
slug_in_useActive lease already owns the slug.
lease_limit_exceededOwner reached MYTUNNEL_MAX_LEASES_PER_OWNER.
no_available_portNo bind port is available in the configured edge range.
permission_deniedCaller does not own the lease or is not privileged for --force.
edge_unreachableEdge health failed.
caddy_unreachableCaddy Admin API failed.
reconcile_failedOne or more reconcile apply actions failed.
internal_errorUnmapped error.