Skip to content

Common issues

Symptoms: The agent prints a pair URL but pairing never completes.

Causes:

  • The pair URL was never opened in a signed-in browser.
  • The agent can’t reach api.atreolink.com (firewall, DNS, or proxy issue).
  • The pairing token expired. They’re short-lived to limit the man-in-the-middle window.

Fix:

  1. Verify outbound connectivity: docker exec atreoagent wget -qO- https://api.atreolink.com/health.
  2. Re-print the pair URL by restarting the container. A fresh token is generated each run.
  3. Open the URL on a browser where you’re already signed in to atreoLINK.
  4. Confirm in the browser; check the agent logs for Device paired successfully.

See Pair your server for the full flow.

Symptoms: The atreoLINK app reports “Connected”, but apps fail to load and traffic to the per-app URLs hangs or times out.

Causes:

  • WireGuard sometimes reports the connection as up optimistically as soon as the interface is configured, before any handshake has actually succeeded.
  • The WireGuard UDP port isn’t reachable: no auto port-mapping (NAT-PMP / UPnP unsupported or disabled) and no manual port forward.
  • A firewall is blocking inbound UDP on the WireGuard listen port.
  • ISP-level CGNAT prevents inbound connections.

Fix:

  1. Check the agent logs for the port-mapping status:
    Terminal window
    docker logs atreoagent | grep -iE 'mapping|upnp|nat-pmp|forward UDP'
    A port mapping unavailable: forward UDP <port> line every cycle means auto-mapping isn’t working and you need a manual forward.
  2. Either enable NAT-PMP/UPnP on the router, or configure a manual port forward for the WireGuard UDP port.
  3. Confirm no firewall is dropping inbound UDP on the WireGuard listen port.
  4. If you’re behind CGNAT, the agent falls back to the CGNAT relay automatically — check the logs for a relay: session ready line (docker logs atreoagent | grep -i relay). A direct path performs better, so ask your ISP for a public IP if you want one.

Symptoms: A push notification saying your router assigned the wrong external port.

Causes:

  • Another device on your network requested the same external port via UPnP and won the race.
  • Router rebooted and reassigned ports differently.
  • UPnP lease expired and renewal handed out a different port.

Fix:

  1. Wait. The agent retries every 5 minutes and the issue often self-resolves.
  2. Reserve the port in your router’s UPnP settings if it offers that.
  3. Set up a static manual port forward on the WireGuard UDP port; a fixed forward can’t lose the UPnP port race.
  4. If the issue is persistent, disable auto port-mapping (WG_UPNP_ENABLED=false or --no-upnp) and rely on the manual forward alone.

Symptoms: Browser shows certificate warnings when accessing apps.

Causes:

  • ACME DNS-01 challenge failed (atreoLINK’s DNS relay couldn’t be reached).
  • The certificate hasn’t been provisioned yet (first startup, or just after pair).
  • Certificate expired and renewal failed.

Fix:

  1. Check logs for ACME errors:
    Terminal window
    docker logs atreoagent | grep -iE 'acme|cert|tls'
  2. Verify outbound connectivity to atreoLINK (DNS-01 needs it).
  3. Restart the container to trigger a re-check.
  4. Confirm certs.email is set in the config. Let’s Encrypt requires it.

Symptoms: A self-hosted app gets 550 unknown recipient from the SMTP gateway.

Causes:

  • The recipient address doesn’t match a member’s atreoLINK account email exactly.
  • The SMTP server is bound to a different interface than the sender expects.
  • The sending host’s IP isn’t in the SMTP source-IP allowlist, so the connection is rejected before AUTH.

Fix:

  1. Check the recipient against the member’s email in app.atreolink.com → Members. Match exactly, including case (the agent normalises to lowercase, but use the canonical address to be safe).
  2. Verify SMTP_LISTEN and the sender’s configured SMTP host are the same interface.
  3. If the connection is refused or closed before AUTH, confirm the sender’s IP falls within smtp.trusted_networks (or SMTP_TRUSTED_NETWORKS). The default list covers loopback, RFC 1918, link-local, IPv6 ULA, and the tunnel subnet; add the sender’s LAN CIDR if it sits outside those.
  4. Check the agent logs: docker logs atreoagent | grep -i smtp.

Symptoms: You enabled browser notifications, paired a server, but no notifications arrive.

Causes:

  • Browser notification permission is denied.
  • The browser’s Service Worker hasn’t been registered (private window, hard reload mid-pairing).

Fix:

  1. “Notifications are blocked at the browser level” means revoke and re-allow at the browser level.
  2. If the page looks fine but pushes don’t arrive, click Disable on the affected server and Pair this browser again to redo the handshake.

Symptoms: A member can connect via the tunnel but gets 403 when opening an app.

Causes:

  • The member doesn’t have the app in their allowedApps.
  • A recent change hasn’t reached the agent yet.
  • The member’s status is not active.

Fix:

  1. In the atreoLINK dashboard, confirm the member has the app ticked under Members → Edit.
  2. Verify the agent’s view of the ACL: docker exec atreoagent atreoagent apps.
  3. ACL changes propagate automatically. If the agent looks stale, restart the container to force a reconnect; atreoLINK pushes a complete signed state on connect.

Symptoms: A server is badged Suspended in the dashboard, the agent’s connection attempts are refused, and the CGNAT relay and push notifications stop working.

Cause: The account’s subscription was cancelled or lapsed. On cancellation, servers and members are suspended, not deleted — nothing is lost, but coordination services stop until the server is reactivated.

Fix:

  1. To restore everything at once, resubscribe to a paid plan from Settings → Billing. Suspension lifts across your whole account and the agents reconnect on their own.
  2. To stay on the free plan, get your account within free-plan limits (1 server, 1 member): unpair any extra servers and remove extra members or pending invites, then open the server and choose Reactivate on free plan.

If reactivation is refused with a limit error, the dashboard names what’s still over (too many servers, or too many members on that server).

Symptoms: Container exits immediately or crashes on startup.

Causes:

  • Missing NET_ADMIN capability.
  • /dev/net/tun not available.
  • WireGuard kernel module not loaded on the host.
  • Port conflict (another service on 51820/udp, 443/tcp, or 9091/tcp).
  • The tunnel firewall is enabled (the default) but iptables or ip6tables is unavailable or its rules can’t be applied. The firewall confines peers on both IPv4 and IPv6 and now fails closed: rather than start with tunnel peers unconfined, the agent exits with an error.

Fix:

  1. Verify your Compose file includes cap_add: [NET_ADMIN] and devices: [/dev/net/tun].
  2. Confirm WireGuard is available: docker exec atreoagent wg --version.
  3. Load the WireGuard module on the host: sudo modprobe wireguard.
  4. Check for port conflicts: sudo ss -tulnp | grep -E '51820|443|9091'.
  5. If the logs show the firewall couldn’t be configured, make iptables and ip6tables usable inside the container: keep cap_add: [NET_ADMIN] and ensure the host’s iptables/ip_tables and ip6tables/ip6_tables modules are loaded (sudo modprobe ip_tables iptable_filter ip6_tables ip6table_filter). The official Docker image bundles both iptables and ip6tables, so Docker users normally don’t need to do anything — ip6tables only matters for non-Docker installs or a stripped-down host, where the firewall fails closed without it. Only as a last resort, set wireguard.firewall_enabled: false (or WG_FIREWALL_ENABLED=false) to start without the firewall — this exposes every host port bound to 0.0.0.0 to every paired peer and bypasses the per-app ACL, so it’s discouraged.

WireGuard is a registered trademark of Jason A. Donenfeld.