Use a tunnels.yaml config file
Declare every tunnel — port, subdomain, password — in one YAML file and let the CLI hot-reload on edit.
You want to stop typing the same justtunnel <port> --subdomain ... --password ... invocation every morning. A tunnels.yaml file lets you declare every tunnel in one place and start them all with one command — and the CLI watches the file so adding or removing entries hot-reloads without a restart.
You'll need an authenticated CLI (justtunnel auth) and a directory you'd like to store the YAML in (the project root works fine).
Steps
1. Create tunnels.yaml
Save this minimal example next to your project (the field shape mirrors the reference file in the CLI repo):
tunnels:
- port: 8080
name: api
subdomain: jt-dev
Each tunnel entry is one item in the tunnels: list. The full set of supported fields:
| Field | Required | Notes |
|---|---|---|
port | Yes | Local port the tunnel forwards to. Must be 1-65535 and unique across the file. |
name | No | Display name shown in the TUI. Defaults to :<port> when omitted. |
subdomain | No | Request a specific subdomain for this tunnel. Reserved names need a paid plan — see Reserve a custom subdomain. |
password | No | Password-protect the tunnel. Must be 4 to 128 characters when set. |
A richer example with multiple tunnels and a mix of options:
tunnels:
- port: 3000
name: frontend
subdomain: acme-frontend
- port: 8080
name: api
subdomain: acme-api
password: 'staging-only'
- port: 9000
name: webhook-receiver
2. Start the tunnels
justtunnel --config-file tunnels.yaml
When stdout is a terminal, the CLI launches a TUI that shows every tunnel side-by-side with its own request log. In a non-TTY context (a pipe, a CI runner) the CLI requires a port argument — config-file-only mode is interactive.
3. Edit the file while the CLI is running
Add a new entry, save, and watch the TUI pick it up:
tunnels:
- port: 3000
name: frontend
subdomain: acme-frontend
- port: 8080
name: api
subdomain: acme-api
- port: 9090 # NEW
name: metrics
The CLI uses fsnotify to watch the file, debounces edits over a short window, and then diffs the desired config against the running tunnels. New entries are added; entries you removed are torn down. Existing tunnels whose entries did not change are left alone — they do not reconnect.
If the file is invalid (bad YAML, duplicate port, password out of range), the CLI prints a reload error to the TUI status line and keeps the previous tunnels running untouched.
Verify
While the CLI is running with the example above, list your tunnel URLs:
NAME URL
frontend https://acme-frontend.justtunnel.dev
api https://acme-api.justtunnel.dev
metrics https://chosen-randomly.justtunnel.dev
Hit each:
curl -I https://acme-frontend.justtunnel.dev
curl -I https://acme-api.justtunnel.dev
Each should return whatever the corresponding local server returns. Edit tunnels.yaml, save, and confirm in the TUI that the change took effect — added entries appear, removed entries disappear.
Common issues
tunnel[N]: invalid port <P>. A port is outside the1-65535range. Fix the value.tunnel[N]: duplicate port <P>. Two entries share the same port. Each port can appear at most once.tunnel "<name>" password must be between 4 and 128 characters. Apasswordfield is set but too short or too long.- Editor "save-via-rename" patterns. The watcher handles editors that rename a temp file over the original (vim, IntelliJ, etc.) — but if your editor unlinks the file completely without recreating it, you'll see a reload error until the file reappears.
Related
justtunnel [port]— root command, including--config-file.- Run multiple tunnels at once — when to use a YAML file vs separate processes.
- Password-protect a tunnel — the
passwordfield's behavior. - Reserve a custom subdomain — how
subdomaininteracts with plan tier.