{"slug":"troubleshooting-aperture-by-tailscale","title":"Troubleshooting Aperture by Tailscale","tags":["tailscale"],"agent_summary":"Last validated: Apr 9, 2026","trigger_phrases":[],"runnable":false,"markdown":"\r\n# Troubleshooting Aperture by Tailscale\r\n\r\nLast validated: Apr 9, 2026\r\n\r\nUse the following sections to diagnose and resolve common issues with [Aperture by Tailscale](https://tailscale.com/docs/aperture).\r\n\r\n| Symptom | Likely cause |\r\n| --- | --- |\r\n| [Cannot connect using hostname](https://tailscale.com/docs/aperture/troubleshooting#cannot-connect-to-aperture-using-hostname) | MagicDNS disabled, wrong URL |\r\n| [HTTP 403 error](https://tailscale.com/docs/aperture/troubleshooting#http-403-access-denied-error) | Missing grant |\r\n| [Instance becomes unreachable](https://tailscale.com/docs/aperture/troubleshooting#aperture-instance-becomes-unreachable) | Key expiry |\r\n| [HTTP 429 errors](https://tailscale.com/docs/aperture/troubleshooting#http-429-rate-limit-errors) | Quota misconfiguration |\r\n| [Mullvad exit nodes](https://tailscale.com/docs/aperture/troubleshooting#intermittent-failures-with-mullvad-exit-nodes) | Mullvad IP collision |\r\n| [All sessions from same user](https://tailscale.com/docs/aperture/troubleshooting#all-sessions-appear-to-come-from-the-same-user) | Tag-based identity |\r\n| [HTTPS connection issues](https://tailscale.com/docs/aperture/troubleshooting#https-connection-issues) | Use `http://` |\r\n| [Client connection issues](https://tailscale.com/docs/aperture/troubleshooting#client-connection-issues) | Wrong base URL or missing auth |\r\n\r\n## [Client connection issues](https://tailscale.com/docs/aperture/troubleshooting\\#client-connection-issues)\r\n\r\nIf a client tool does not connect to Aperture or requests do not appear in the Aperture logs:\r\n\r\n- Confirm the base URL in your client configuration matches your Aperture hostname. For most tools, the URL is `http://ai` or `http://ai/v1`.\r\n- Confirm your client has a valid authentication entry. Most tools require a placeholder API key (such as `-`) even though Aperture injects the real credentials.\r\n- Verify your device can reach Aperture by opening `http://ai/ui/` in a browser.\r\n- If you connect through ts-unplug, confirm ts-unplug is running and use `http://localhost:<PORT_NUMBER>` instead of `http://ai`.\r\n\r\nFor tool-specific configuration, refer to the [Set up LLM clients](https://tailscale.com/docs/aperture/use-your-tools) guides, or refer to individual guides for [Claude Code](https://tailscale.com/docs/aperture/how-to/use-claude-code), [Codex](https://tailscale.com/docs/aperture/how-to/use-codex), or [OpenAI-compatible tools](https://tailscale.com/docs/aperture/how-to/use-openai-compatible-tools). If you use the [CLI launcher](https://tailscale.com/docs/aperture/cli-launcher), it handles base URLs and authentication automatically.\r\n\r\n## [All sessions appear to come from the same user](https://tailscale.com/docs/aperture/troubleshooting\\#all-sessions-appear-to-come-from-the-same-user)\r\n\r\nIf you use tag-based identities to authenticate user devices, all LLM sessions from those devices appear to come from the same user. This happens because Tailscale tags do not provide per-user identity. The intended use of tags is service account or server device authentication, not individual user authentication. For example, you might use a tag identity for a fleet of PostgreSQL database servers. Refer to the [tags documentation](https://tailscale.com/docs/features/tags) for more information.\r\n\r\nTo resolve this issue, ensure that users connect to Aperture from devices associated with their individual Tailscale accounts. For details on how Aperture resolves identity for tagged nodes, refer to the [tagged device identity documentation](https://tailscale.com/docs/aperture/how-aperture-works#tagged-node-identity).\r\n\r\n## [HTTPS connection issues](https://tailscale.com/docs/aperture/troubleshooting\\#https-connection-issues)\r\n\r\nIf you encounter HTTPS connection issues when accessing the [Aperture dashboard](https://tailscale.com/docs/aperture/reference/dashboard) or using LLM clients, verify that you're using `http://` and not `https://` for the Aperture URL. For example, use `http://ai/ui/` (replace `ai` with your Aperture hostname). For more information on configuring Aperture, refer to the [Aperture configuration reference](https://tailscale.com/docs/aperture/configuration).\r\n\r\nIf the hostname does not resolve at all, the problem might be that MagicDNS is disabled rather than an HTTPS issue. Refer to [cannot connect to Aperture using hostname](https://tailscale.com/docs/aperture/troubleshooting#cannot-connect-to-aperture-using-hostname).\r\n\r\n## [Cannot connect to Aperture using hostname](https://tailscale.com/docs/aperture/troubleshooting\\#cannot-connect-to-aperture-using-hostname)\r\n\r\nIf you cannot connect to Aperture using its short hostname (for example, `http://ai`), [MagicDNS](https://tailscale.com/docs/features/magicdns) might be disabled in your tailnet. Aperture relies on MagicDNS to resolve its hostname. When MagicDNS is off, the hostname does not resolve, and connection attempts fail.\r\n\r\nDo not use `tailscale ping` to diagnose this issue. `tailscale ping` succeeds even when MagicDNS is disabled because it routes traffic through DERP relay using the Tailscale IP address directly. Instead, run `tailscale dns status` to verify that MagicDNS is active, or check the [DNS](https://login.tailscale.com/admin/dns) settings page of the Tailscale admin console. You can also run `nslookup <hostname>.<tailnet>.ts.net` to test resolution directly. Replace `<hostname>` with your Aperture hostname (`ai` is the default, but it might be a custom name). If the generated client configurations show a placeholder URL such as `http://your-aperture-host`, MagicDNS is likely not enabled.\r\n\r\nTo resolve this issue, enable MagicDNS in the Tailscale admin console under [DNS](https://login.tailscale.com/admin/dns) settings. Refer to the [MagicDNS documentation](https://tailscale.com/docs/features/magicdns) for setup instructions. Alternatively, bypass hostname resolution by using the Tailscale IP address directly (for example, `http://<tailscale-ip>/` instead of `http://ai/`). You can find the IP address of the admin console under [Machines](https://login.tailscale.com/admin/machines).\r\n\r\n## [HTTP 403 access denied error](https://tailscale.com/docs/aperture/troubleshooting\\#http-403-access-denied-error)\r\n\r\nIf you receive an HTTP 403 error with the message `access denied: no role granted`, the issue is a missing or misconfigured access rule. Aperture uses two independent layers of access control, and both must be configured correctly:\r\n\r\n1. **tailnet grant**: A tailnet access rule that permits connections to the Aperture device. Without this rule, the connection fails before reaching Aperture.\r\n2. **Aperture grant**: A configuration-level rule that grants a user or group access to specific models and assigns a role. Without a matching grant, Aperture returns a 403 error.\r\n\r\nThe most common causes are a missing grant entry in the tailnet policy file, a missing grant entry in the [Aperture configuration](https://tailscale.com/docs/aperture/configuration), or an incorrect `src` pattern in either grant. For step-by-step instructions on configuring grants, refer to [Control model access](https://tailscale.com/docs/aperture/how-to/grant-model-access) and [Set up admin access](https://tailscale.com/docs/aperture/how-to/set-up-admin-access). The `src` field requires an exact match. For tagged devices, the `src` value must match the exact comma-joined tag string that Aperture generates. Refer to the [tagged device identity documentation](https://tailscale.com/docs/aperture/how-aperture-works#tagged-node-identity) for details on how Aperture matches tagged devices.\r\n\r\nTo help diagnose this issue, use the [Preview rules](https://login.tailscale.com/admin/acls/preview) in the Tailscale admin console to check that the user's device can reach the Aperture instance. Then check that the Aperture configuration includes a grant entry with a `src` pattern matching the connecting user or tag. If the 403 errors are intermittent and correlate with VPN use, refer to [intermittent failures with Mullvad exit nodes](https://tailscale.com/docs/aperture/troubleshooting#intermittent-failures-with-mullvad-exit-nodes) for a related cause.\r\n\r\n## [Aperture instance becomes unreachable](https://tailscale.com/docs/aperture/troubleshooting\\#aperture-instance-becomes-unreachable)\r\n\r\nIf an Aperture instance that was previously working becomes unreachable, the most likely cause is node key expiry. When the key expires, the instance repeatedly restarts and waits for reauthorization that never completes, remaining in a `NeedsLogin` state. The same behavior occurs if you accidentally delete the device from the Tailscale admin console. Check the admin console to determine whether the device is listed as expired or missing.\r\n\r\nAperture displays a warning banner of the admin console when a node key is within 7 days of expiring. This banner is visible only to admin users.\r\n\r\nThere is no way to recover an expired instance. You must deploy a new Aperture instance and reconfigure your clients. To prevent this, disable key expiry for the Aperture device from the admin console, or deploy Aperture as a [tagged device](https://tailscale.com/docs/features/tags). Refer to the [key expiry documentation](https://tailscale.com/docs/features/access-control/key-expiry) for more information.\r\n\r\n## [HTTP 429 rate limit errors](https://tailscale.com/docs/aperture/troubleshooting\\#http-429-rate-limit-errors)\r\n\r\nIf you receive an HTTP 429 rate limit error when you expect to have access, the issue is likely a misconfigured quota in the Aperture configuration. Aperture's quota system fails closed: if the quota configuration cannot be parsed, Aperture rejects all requests matching that quota with a 429 error. Common causes include a typo in the quota bucket name, an invalid quota value, or a quota limit set to zero.\r\n\r\nCheck the Aperture configuration for quota fields and verify that bucket names are spelled correctly and that values are valid. Refer to the [quota configuration documentation](https://tailscale.com/docs/aperture/configuration#quotas) for the expected syntax. To resolve the issue, correct the quota value in the configuration. If you do not need custom quotas, remove the quota field entirely to use the default settings. For step-by-step instructions on checking and refilling budgets, refer to [Check and refill budgets](https://tailscale.com/docs/aperture/how-to/check-and-refill-budgets).\r\n\r\n## [Intermittent failures with Mullvad exit nodes](https://tailscale.com/docs/aperture/troubleshooting\\#intermittent-failures-with-mullvad-exit-nodes)\r\n\r\nIf you experience intermittent 403 errors or connection failures when accessing Aperture while a Mullvad exit node is active, this is due to an IP address range collision. Tailscale assigns device addresses from the CGNAT range `100.64.0.0/10`, and Mullvad also uses addresses in this range. When a Mullvad exit node is active, traffic destined for Tailscale addresses can be misrouted through Mullvad, causing grant evaluation failures that are indistinguishable from [grant permission issues](https://tailscale.com/docs/aperture/troubleshooting#http-403-access-denied-error).\r\n\r\nTo confirm this is the cause, disconnect from the Mullvad exit node and retry the connection. If the errors stop, use [Tailscale exit nodes](https://tailscale.com/docs/features/exit-nodes) instead, or exclude the Tailscale interface from Mullvad's routing configuration if your Mullvad client supports split tunneling.\r\n\r\n![Project Logo](https://cdn.brandfetch.io/tailscale.com/fallback/lettermark/theme/dark/h/256/w/256/icon?c=1bfwsmEH20zzEfSNTed)\r\n\r\nAsk AI\r\n\r\nreCAPTCHA\r\n\r\nRecaptcha requires verification.\r\n\r\nprotected by **reCAPTCHA**\r\n","html":"<h1>Troubleshooting Aperture by Tailscale</h1>\n<p>Last validated: Apr 9, 2026</p>\n<p>Use the following sections to diagnose and resolve common issues with <a href=\"https://tailscale.com/docs/aperture\">Aperture by Tailscale</a>.</p>\n<p>| Symptom | Likely cause |\r\n| --- | --- |\r\n| <a href=\"https://tailscale.com/docs/aperture/troubleshooting#cannot-connect-to-aperture-using-hostname\">Cannot connect using hostname</a> | MagicDNS disabled, wrong URL |\r\n| <a href=\"https://tailscale.com/docs/aperture/troubleshooting#http-403-access-denied-error\">HTTP 403 error</a> | Missing grant |\r\n| <a href=\"https://tailscale.com/docs/aperture/troubleshooting#aperture-instance-becomes-unreachable\">Instance becomes unreachable</a> | Key expiry |\r\n| <a href=\"https://tailscale.com/docs/aperture/troubleshooting#http-429-rate-limit-errors\">HTTP 429 errors</a> | Quota misconfiguration |\r\n| <a href=\"https://tailscale.com/docs/aperture/troubleshooting#intermittent-failures-with-mullvad-exit-nodes\">Mullvad exit nodes</a> | Mullvad IP collision |\r\n| <a href=\"https://tailscale.com/docs/aperture/troubleshooting#all-sessions-appear-to-come-from-the-same-user\">All sessions from same user</a> | Tag-based identity |\r\n| <a href=\"https://tailscale.com/docs/aperture/troubleshooting#https-connection-issues\">HTTPS connection issues</a> | Use <code>http://</code> |\r\n| <a href=\"https://tailscale.com/docs/aperture/troubleshooting#client-connection-issues\">Client connection issues</a> | Wrong base URL or missing auth |</p>\n<h2><a href=\"https://tailscale.com/docs/aperture/troubleshooting#client-connection-issues\">Client connection issues</a></h2>\n<p>If a client tool does not connect to Aperture or requests do not appear in the Aperture logs:</p>\n<ul>\n<li>Confirm the base URL in your client configuration matches your Aperture hostname. For most tools, the URL is <code>http://ai</code> or <code>http://ai/v1</code>.</li>\n<li>Confirm your client has a valid authentication entry. Most tools require a placeholder API key (such as <code>-</code>) even though Aperture injects the real credentials.</li>\n<li>Verify your device can reach Aperture by opening <code>http://ai/ui/</code> in a browser.</li>\n<li>If you connect through ts-unplug, confirm ts-unplug is running and use <code>http://localhost:&#x3C;PORT_NUMBER></code> instead of <code>http://ai</code>.</li>\n</ul>\n<p>For tool-specific configuration, refer to the <a href=\"https://tailscale.com/docs/aperture/use-your-tools\">Set up LLM clients</a> guides, or refer to individual guides for <a href=\"https://tailscale.com/docs/aperture/how-to/use-claude-code\">Claude Code</a>, <a href=\"https://tailscale.com/docs/aperture/how-to/use-codex\">Codex</a>, or <a href=\"https://tailscale.com/docs/aperture/how-to/use-openai-compatible-tools\">OpenAI-compatible tools</a>. If you use the <a href=\"https://tailscale.com/docs/aperture/cli-launcher\">CLI launcher</a>, it handles base URLs and authentication automatically.</p>\n<h2><a href=\"https://tailscale.com/docs/aperture/troubleshooting#all-sessions-appear-to-come-from-the-same-user\">All sessions appear to come from the same user</a></h2>\n<p>If you use tag-based identities to authenticate user devices, all LLM sessions from those devices appear to come from the same user. This happens because Tailscale tags do not provide per-user identity. The intended use of tags is service account or server device authentication, not individual user authentication. For example, you might use a tag identity for a fleet of PostgreSQL database servers. Refer to the <a href=\"https://tailscale.com/docs/features/tags\">tags documentation</a> for more information.</p>\n<p>To resolve this issue, ensure that users connect to Aperture from devices associated with their individual Tailscale accounts. For details on how Aperture resolves identity for tagged nodes, refer to the <a href=\"https://tailscale.com/docs/aperture/how-aperture-works#tagged-node-identity\">tagged device identity documentation</a>.</p>\n<h2><a href=\"https://tailscale.com/docs/aperture/troubleshooting#https-connection-issues\">HTTPS connection issues</a></h2>\n<p>If you encounter HTTPS connection issues when accessing the <a href=\"https://tailscale.com/docs/aperture/reference/dashboard\">Aperture dashboard</a> or using LLM clients, verify that you're using <code>http://</code> and not <code>https://</code> for the Aperture URL. For example, use <code>http://ai/ui/</code> (replace <code>ai</code> with your Aperture hostname). For more information on configuring Aperture, refer to the <a href=\"https://tailscale.com/docs/aperture/configuration\">Aperture configuration reference</a>.</p>\n<p>If the hostname does not resolve at all, the problem might be that MagicDNS is disabled rather than an HTTPS issue. Refer to <a href=\"https://tailscale.com/docs/aperture/troubleshooting#cannot-connect-to-aperture-using-hostname\">cannot connect to Aperture using hostname</a>.</p>\n<h2><a href=\"https://tailscale.com/docs/aperture/troubleshooting#cannot-connect-to-aperture-using-hostname\">Cannot connect to Aperture using hostname</a></h2>\n<p>If you cannot connect to Aperture using its short hostname (for example, <code>http://ai</code>), <a href=\"https://tailscale.com/docs/features/magicdns\">MagicDNS</a> might be disabled in your tailnet. Aperture relies on MagicDNS to resolve its hostname. When MagicDNS is off, the hostname does not resolve, and connection attempts fail.</p>\n<p>Do not use <code>tailscale ping</code> to diagnose this issue. <code>tailscale ping</code> succeeds even when MagicDNS is disabled because it routes traffic through DERP relay using the Tailscale IP address directly. Instead, run <code>tailscale dns status</code> to verify that MagicDNS is active, or check the <a href=\"https://login.tailscale.com/admin/dns\">DNS</a> settings page of the Tailscale admin console. You can also run <code>nslookup &#x3C;hostname>.&#x3C;tailnet>.ts.net</code> to test resolution directly. Replace <code>&#x3C;hostname></code> with your Aperture hostname (<code>ai</code> is the default, but it might be a custom name). If the generated client configurations show a placeholder URL such as <code>http://your-aperture-host</code>, MagicDNS is likely not enabled.</p>\n<p>To resolve this issue, enable MagicDNS in the Tailscale admin console under <a href=\"https://login.tailscale.com/admin/dns\">DNS</a> settings. Refer to the <a href=\"https://tailscale.com/docs/features/magicdns\">MagicDNS documentation</a> for setup instructions. Alternatively, bypass hostname resolution by using the Tailscale IP address directly (for example, <code>http://&#x3C;tailscale-ip>/</code> instead of <code>http://ai/</code>). You can find the IP address of the admin console under <a href=\"https://login.tailscale.com/admin/machines\">Machines</a>.</p>\n<h2><a href=\"https://tailscale.com/docs/aperture/troubleshooting#http-403-access-denied-error\">HTTP 403 access denied error</a></h2>\n<p>If you receive an HTTP 403 error with the message <code>access denied: no role granted</code>, the issue is a missing or misconfigured access rule. Aperture uses two independent layers of access control, and both must be configured correctly:</p>\n<ol>\n<li><strong>tailnet grant</strong>: A tailnet access rule that permits connections to the Aperture device. Without this rule, the connection fails before reaching Aperture.</li>\n<li><strong>Aperture grant</strong>: A configuration-level rule that grants a user or group access to specific models and assigns a role. Without a matching grant, Aperture returns a 403 error.</li>\n</ol>\n<p>The most common causes are a missing grant entry in the tailnet policy file, a missing grant entry in the <a href=\"https://tailscale.com/docs/aperture/configuration\">Aperture configuration</a>, or an incorrect <code>src</code> pattern in either grant. For step-by-step instructions on configuring grants, refer to <a href=\"https://tailscale.com/docs/aperture/how-to/grant-model-access\">Control model access</a> and <a href=\"https://tailscale.com/docs/aperture/how-to/set-up-admin-access\">Set up admin access</a>. The <code>src</code> field requires an exact match. For tagged devices, the <code>src</code> value must match the exact comma-joined tag string that Aperture generates. Refer to the <a href=\"https://tailscale.com/docs/aperture/how-aperture-works#tagged-node-identity\">tagged device identity documentation</a> for details on how Aperture matches tagged devices.</p>\n<p>To help diagnose this issue, use the <a href=\"https://login.tailscale.com/admin/acls/preview\">Preview rules</a> in the Tailscale admin console to check that the user's device can reach the Aperture instance. Then check that the Aperture configuration includes a grant entry with a <code>src</code> pattern matching the connecting user or tag. If the 403 errors are intermittent and correlate with VPN use, refer to <a href=\"https://tailscale.com/docs/aperture/troubleshooting#intermittent-failures-with-mullvad-exit-nodes\">intermittent failures with Mullvad exit nodes</a> for a related cause.</p>\n<h2><a href=\"https://tailscale.com/docs/aperture/troubleshooting#aperture-instance-becomes-unreachable\">Aperture instance becomes unreachable</a></h2>\n<p>If an Aperture instance that was previously working becomes unreachable, the most likely cause is node key expiry. When the key expires, the instance repeatedly restarts and waits for reauthorization that never completes, remaining in a <code>NeedsLogin</code> state. The same behavior occurs if you accidentally delete the device from the Tailscale admin console. Check the admin console to determine whether the device is listed as expired or missing.</p>\n<p>Aperture displays a warning banner of the admin console when a node key is within 7 days of expiring. This banner is visible only to admin users.</p>\n<p>There is no way to recover an expired instance. You must deploy a new Aperture instance and reconfigure your clients. To prevent this, disable key expiry for the Aperture device from the admin console, or deploy Aperture as a <a href=\"https://tailscale.com/docs/features/tags\">tagged device</a>. Refer to the <a href=\"https://tailscale.com/docs/features/access-control/key-expiry\">key expiry documentation</a> for more information.</p>\n<h2><a href=\"https://tailscale.com/docs/aperture/troubleshooting#http-429-rate-limit-errors\">HTTP 429 rate limit errors</a></h2>\n<p>If you receive an HTTP 429 rate limit error when you expect to have access, the issue is likely a misconfigured quota in the Aperture configuration. Aperture's quota system fails closed: if the quota configuration cannot be parsed, Aperture rejects all requests matching that quota with a 429 error. Common causes include a typo in the quota bucket name, an invalid quota value, or a quota limit set to zero.</p>\n<p>Check the Aperture configuration for quota fields and verify that bucket names are spelled correctly and that values are valid. Refer to the <a href=\"https://tailscale.com/docs/aperture/configuration#quotas\">quota configuration documentation</a> for the expected syntax. To resolve the issue, correct the quota value in the configuration. If you do not need custom quotas, remove the quota field entirely to use the default settings. For step-by-step instructions on checking and refilling budgets, refer to <a href=\"https://tailscale.com/docs/aperture/how-to/check-and-refill-budgets\">Check and refill budgets</a>.</p>\n<h2><a href=\"https://tailscale.com/docs/aperture/troubleshooting#intermittent-failures-with-mullvad-exit-nodes\">Intermittent failures with Mullvad exit nodes</a></h2>\n<p>If you experience intermittent 403 errors or connection failures when accessing Aperture while a Mullvad exit node is active, this is due to an IP address range collision. Tailscale assigns device addresses from the CGNAT range <code>100.64.0.0/10</code>, and Mullvad also uses addresses in this range. When a Mullvad exit node is active, traffic destined for Tailscale addresses can be misrouted through Mullvad, causing grant evaluation failures that are indistinguishable from <a href=\"https://tailscale.com/docs/aperture/troubleshooting#http-403-access-denied-error\">grant permission issues</a>.</p>\n<p>To confirm this is the cause, disconnect from the Mullvad exit node and retry the connection. If the errors stop, use <a href=\"https://tailscale.com/docs/features/exit-nodes\">Tailscale exit nodes</a> instead, or exclude the Tailscale interface from Mullvad's routing configuration if your Mullvad client supports split tunneling.</p>\n<p><img src=\"https://cdn.brandfetch.io/tailscale.com/fallback/lettermark/theme/dark/h/256/w/256/icon?c=1bfwsmEH20zzEfSNTed\" alt=\"Project Logo\"></p>\n<p>Ask AI</p>\n<p>reCAPTCHA</p>\n<p>Recaptcha requires verification.</p>\n<p>protected by <strong>reCAPTCHA</strong></p>\n"}