Troubleshooting
What to check when a device cannot connect to your Viaalink Relay, an address does not open, a certificate is not issued, a port is already in use, an SSH alias is not found, or the license reports a problem.
Where to start
Find the part that fails, then go to its section:
| What you see | Which part | Section |
|---|---|---|
| The client cannot log in, times out, or is refused | Device ↔ Relay | A device cannot connect |
| The client is connected, but the address does not open | Visitor ↔ address | An address does not open |
| The browser warns about the certificate | The Relay’s HTTPS | The HTTPS certificate is not issued |
| The Relay does not start | The Relay machine | A port is already in use |
ssh -J closes right after the Relay | SSH client ↔ Relay ↔ device | An SSH alias is not found |
| The setup page shows a license message | The license | License problems |
The three kinds of connection are explained on Three Kinds of Connection.
A device cannot connect
First ask the Relay to describe itself with your key. This logs in, reads what the Relay serves, and publishes nothing:
viaalink-relay info --server relay.example.com:2222 --key ~/.ssh/id_ed25519- It answers with the Relay’s domains: the network and your key are fine. Look at the address you ask for instead (An address does not open).
- It times out: the device cannot reach the Relay’s SSH port. Check that
2222is forwarded on the Relay’s router and allowed by its firewall, and that the network the device is on allows outgoing connections to that port. Some office and hotel networks only allow web ports. - Permission denied: the Relay does not know this key. Approve the public half (
.pub), as described in Access Control and Security. A laptop that jumps to a private alias needs its own approved key, too.
With OpenSSH, ssh -v -p 2222 relay.example.com shows the same steps in detail. Other causes:
- Too many keys. The Relay allows three login tries per connection. When your SSH agent offers several keys, the right one may never get its turn. Name the key and offer only that one:
ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 -p 2222 relay.example.com. - Slow login. A device must finish logging in within five seconds (
--cleanup-unauthed-timeout), or the Relay closes the connection. - IP or country rules. Rules set with
--banned-ips,--whitelisted-ips,--banned-countriesor--whitelisted-countriesapply to devices as well as visitors. A device outside an allowed network or country is refused before it can log in. - Free plan limit. When a Relay without a license already has its maximum of connected devices, a new device is refused with a message — see License problems.
An address does not open
Read the address from the latest output of the client: OpenSSH shows the Relay’s welcome text (leave out -N to see it), via prints the address. Then match what the browser shows:
| The browser shows | Meaning | What to do |
|---|---|---|
| “Server not found” | The name does not resolve | Add the wildcard record *.relay.example.com (DNS Configuration) and wait for it to spread |
| 404 | Nothing is published under this name right now | The client is not connected, or the name changed after a reconnect — read the current address |
| 502 Bad Gateway | The Relay reached the device, but nothing answers on the local port | Start the app, or fix the local port in the forward |
| 403 Forbidden | An IP or country rule blocks this visitor | See IP and country rules |
| A password prompt | The link has a password | Expected — see Password per link |
The name is not the one you asked for. With --bind-random-subdomains on (the default), the Relay gives every web address a random three-letter name and tells the client so (“The subdomain … is unavailable. Assigning a random subdomain.”). Turn it off on the Relay to let devices keep the names they ask for. With --force-requested-subdomains on as well, a name that is already taken makes the request fail instead of falling back to a random one — OpenSSH then prints Warning: remote port forwarding failed for listen port 80.
Only an http:// address is shown. The welcome text lists an HTTPS: line only when the Relay serves HTTPS: through Caddy (--caddy-https-enabled), its own listener (--https), or a proxy in front that handles HTTPS (--proxy-ssl-termination). Set up HTTPS as described in your installation guide.
The HTTPS certificate is not issued
The Relay (or Caddy in front of it) gets its certificates from Let’s Encrypt. When the browser warns about the certificate, check in this order:
- DNS. Both
relay.example.comand*.relay.example.compoint at the Relay’s public address. If you have anAAAA(IPv6) record, it must point at the Relay too: Let’s Encrypt tries IPv6 first. On Cloudflare, set both records to DNS only (grey cloud). - Port
80. For single-name certificates, Let’s Encrypt checks over plain HTTP on port80. Forward it to the Relay machine, even if visitors only use443. - Wildcard certificates. A certificate for
*.relay.example.comneeds the DNS check instead: your DNS provider’s credentials must be set. See Certificate lifecycle and DNS-01. - Certificates per address. When certificates are issued for each address as it is first opened, Caddy first asks the Relay whether that address exists (
/_relay/domain-check). The Relay only says yes for an address that is published at that moment — publish first, then open it. - Rate limits. Let’s Encrypt limits how many certificates and failed attempts it accepts per domain over a period. After many failed tries, fix the cause above and wait before trying again.
The Relay’s and Caddy’s logs show the reason Let’s Encrypt gave; see Relay Operations and Maintenance.
A port is already in use
If the Relay stops right after starting, its log says which listener failed, followed by address already in use:
Failed to start SSH listener
Failed to start HTTP listenerFind the program that holds the port (here 2222):
# Linux
sudo ss -ltnp | grep ':2222'
# macOS
sudo lsof -iTCP:2222 -sTCP:LISTEN
# Windows (PowerShell)
netstat -ano | findstr :2222Common cases:
- A web server already uses
80and443. Let the Relay listen on:8080and:8443(--http-address,--https-address) and put Caddy, or your existing web server, in front — as in the Docker and Linux guides. - A second Relay is still running, for example an old service next to a new container. Stop one of them.
- Your own SSH server uses
2222. Move one of the two; the Relay’s SSH port is set with--ssh-address. Devices then connect to the new port.
On the device side, a requested public TCP port can be taken too. With --bind-random-ports on (the default) the Relay picks a free port from --port-bind-range; with it off, a port that is taken makes OpenSSH print Warning: remote port forwarding failed for listen port.
An SSH alias is not found
Symptom: ssh -J relay.example.com:2222 alice@mybox logs in to the Relay and the connection closes at once, before the machine asks for anything. The Relay’s log shows Unable to load tcp alias.
Check:
- Is the machine connected? Its
ssh -R mybox:22:localhost:22(orviaalink-relay connect -F mybox:22:localhost:22) must be running. Leave out-Non the machine to see the welcome text with itsTCP Alias:line. - Did it get the name you use? With
--bind-random-aliaseson (the default), the alias gets a random name such ask3x:22, new on every reconnect. Turn it off on the Relay, and turn on--force-requested-aliasesso a taken name fails loudly. - Do name and port match?
HostName myboxin~/.ssh/configis the alias name, not a DNS name. If the machine publishedmybox:2200, addPort 2200. - Is your key allowed? With
--tcp-aliases-allowed-userson, only the keys the machine listed can reach its alias. - Is it the four-part form? With the built-in client,
-F mybox:22means a web address pointing at local port 22, not an alias. Usename:port:host:port.
The full guide is SSH through the Relay.
License problems
Note: These messages come with the first release of the Relay’s license support.
The setup page (/_relay/dashboard) shows the license status at the top. A Relay without a valid license runs the Free plan, and the status then starts with “Free plan” and shows how many devices are connected. What the messages mean:
| Message | What to do |
|---|---|
| This license is activated on another machine — re-activate or move it at viaalink.com/account | A license is bound to the machine it was activated on. A copy of the Relay’s data on new hardware does not take it along. Move the license in your account (3 times per 30 days) and activate the new machine with a new code. |
| This license must be activated | Activate this Relay with the activation code from viaalink.com/account. |
| This license has expired — renew it at viaalink.com/account | Renew it. Until then the Relay runs the Free plan; devices already connected stay connected. |
| Your server clock is behind — enable NTP | The machine’s clock is wrong, so dates in the license cannot be checked. Turn on automatic time sync. |
| This license file is not valid | The license file is damaged or not a Viaalink license. Download it again from your account. |
When the Free plan is full, a device that tries to connect is refused and its SSH client shows:
This Relay runs the Free plan: up to 10 connected devices. Add a license at viaalink.com/relay
Visitors who open your addresses are never counted. More on plans and moving a license: Relay Licensing.
Calls through firewalls do not connect
Calls in the Viaalink app use the Relay’s UDP port 3478 and the media ports 49152–49167. Test from a machine outside your network — from inside, the router often loops the request back and it succeeds even when the port is closed:
viaalink-relay stun-check relay.example.com:3478It prints OK with the address it saw, or FAIL with the reason, and exits with 1 on failure. Add --turn-realm and --turn-secret (the Relay’s values) to also test a media allocation. If it fails, forward the UDP ports from Requirements and Network Architecture to the Relay machine.
Still stuck
Collect the client’s output, the Relay’s log around the time of the problem, and the output of viaalink-relay --version, and send them to contact@viaalink.com.