{"slug":"tailscale-on-heroku","title":"Tailscale on Heroku","tags":["tailscale","setup"],"agent_summary":"Last validated: Dec 4, 2025","trigger_phrases":[],"runnable":false,"markdown":"\r\n# Tailscale on Heroku\r\n\r\nLast validated: Dec 4, 2025\r\n\r\nHeroku is a popular cloud-hosting platform for running applications without managing servers yourself. However, it can be difficult to use Tailscale on Heroku, since it doesn't provide a /dev/net/tun device that Tailscale needs.\r\n\r\nYou can use Tailscale's [userspace networking mode](https://tailscale.com/docs/concepts/userspace-networking) to connect your apps to your Tailscale network.\r\n\r\n## [Step 1: Generate an auth key to authenticate your Heroku apps](https://tailscale.com/docs/install/cloud/heroku\\#step-1-generate-an-auth-key-to-authenticate-your-heroku-apps)\r\n\r\nFirst, we'll generate an [auth key](https://tailscale.com/docs/features/access-control/auth-keys) to allow Heroku to authenticate our app to join our network.\r\n\r\nGo to [Keys](https://login.tailscale.com/admin/settings/keys) of the admin console and create an auth key. We recommend using an [ephemeral key](https://tailscale.com/docs/features/ephemeral-nodes) for this purpose, since it will automatically clean up devices after they shut down.\r\n\r\n![Tailscale's auth key generation page](https://tailscale.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fephemeral-keys.de85b7fd.png&w=750&q=75)\r\n\r\nThe **Pre-approved** option will only display in the dialog if [device approval](https://tailscale.com/docs/features/access-control/device-management/device-approval) is enabled in your Tailscale network.\r\n\r\nNext, go to your [Heroku app's settings](https://dashboard.heroku.com/apps) and then the configuration variables section. From here, add a new configuration variable named `TAILSCALE_AUTHKEY`, with the `tskey-<key>` value you just created.\r\n\r\n![Heroku's config var interface](https://tailscale.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fheroku-config-vars.752b9615.png&w=3840&q=75)\r\n\r\n## [Step 2: Configure your Dockerfile to install Tailscale](https://tailscale.com/docs/install/cloud/heroku\\#step-2-configure-your-dockerfile-to-install-tailscale)\r\n\r\nWe recommend using a [multistage Dockerfile](https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds) where the first stage builds your application, and the second stage pulls application code and Tailscale into the final image to be uploaded to Heroku.\r\n\r\nCreate a `Dockerfile` at the root of your app. In that `Dockerfile` add something like:\r\n\r\n```docker\r\nFROM golang:1.16.2-alpine3.13 as builder\r\nWORKDIR /app\r\nCOPY . ./\r\n# This is where one could build the application code as well.\r\n\r\n# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds\r\nFROM alpine:latest\r\nRUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/*\r\n\r\n# Copy binary to production image.\r\nCOPY --from=builder /app/start.sh /app/start.sh\r\n\r\n# Copy Tailscale binaries from the tailscale image on Docker Hub.\r\nCOPY --from=docker.io/tailscale/tailscale:stable /usr/local/bin/tailscaled /app/tailscaled\r\nCOPY --from=docker.io/tailscale/tailscale:stable /usr/local/bin/tailscale /app/tailscale\r\nRUN mkdir -p /var/run/tailscale /var/cache/tailscale /var/lib/tailscale\r\n\r\n# Run on container startup.\r\nCMD [\"/app/start.sh\"]\r\n```\r\n\r\nThe Dockerfile specifies `/app/start.sh` as the initial process to run. This script needs to bring Tailscale up and then start the application binary. This is where we can use the `TAILSCALE_AUTHKEY` variable we defined earlier.\r\n\r\nThen, create a file named `start.sh` at the root of your app:\r\n\r\n```shell\r\n#!/bin/sh\r\n\r\n/app/tailscaled --tun=userspace-networking --socks5-server=localhost:1055 &\r\n/app/tailscale up --auth-key=${TAILSCALE_AUTHKEY} --hostname=heroku-app\r\necho Tailscale started\r\nALL_PROXY=socks5://localhost:1055/ /app/my-app\r\n```\r\n\r\nThe next time your Heroku app deploys, it will be able to connect to your private Tailscale network.\r\n\r\n## [Remove ephemeral nodes from a tailnet](https://tailscale.com/docs/install/cloud/heroku\\#remove-ephemeral-nodes-from-a-tailnet)\r\n\r\nWhen an ephemeral node goes offline, it is automatically removed from your tailnet. You can also control ephemeral node removal using the [`tailscale logout`](https://tailscale.com/docs/reference/tailscale-cli#logout) command to either manually force the removal or incorporate the command into the [`tailscaled`](https://tailscale.com/docs/reference/tailscaled) Tailscale daemon. For more information, refer to [Ephemeral nodes](https://tailscale.com/docs/features/ephemeral-nodes#faq).\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>Tailscale on Heroku</h1>\n<p>Last validated: Dec 4, 2025</p>\n<p>Heroku is a popular cloud-hosting platform for running applications without managing servers yourself. However, it can be difficult to use Tailscale on Heroku, since it doesn't provide a /dev/net/tun device that Tailscale needs.</p>\n<p>You can use Tailscale's <a href=\"https://tailscale.com/docs/concepts/userspace-networking\">userspace networking mode</a> to connect your apps to your Tailscale network.</p>\n<h2><a href=\"https://tailscale.com/docs/install/cloud/heroku#step-1-generate-an-auth-key-to-authenticate-your-heroku-apps\">Step 1: Generate an auth key to authenticate your Heroku apps</a></h2>\n<p>First, we'll generate an <a href=\"https://tailscale.com/docs/features/access-control/auth-keys\">auth key</a> to allow Heroku to authenticate our app to join our network.</p>\n<p>Go to <a href=\"https://login.tailscale.com/admin/settings/keys\">Keys</a> of the admin console and create an auth key. We recommend using an <a href=\"https://tailscale.com/docs/features/ephemeral-nodes\">ephemeral key</a> for this purpose, since it will automatically clean up devices after they shut down.</p>\n<p><img src=\"https://tailscale.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fephemeral-keys.de85b7fd.png&#x26;w=750&#x26;q=75\" alt=\"Tailscale&#x27;s auth key generation page\"></p>\n<p>The <strong>Pre-approved</strong> option will only display in the dialog if <a href=\"https://tailscale.com/docs/features/access-control/device-management/device-approval\">device approval</a> is enabled in your Tailscale network.</p>\n<p>Next, go to your <a href=\"https://dashboard.heroku.com/apps\">Heroku app's settings</a> and then the configuration variables section. From here, add a new configuration variable named <code>TAILSCALE_AUTHKEY</code>, with the <code>tskey-&#x3C;key></code> value you just created.</p>\n<p><img src=\"https://tailscale.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fheroku-config-vars.752b9615.png&#x26;w=3840&#x26;q=75\" alt=\"Heroku&#x27;s config var interface\"></p>\n<h2><a href=\"https://tailscale.com/docs/install/cloud/heroku#step-2-configure-your-dockerfile-to-install-tailscale\">Step 2: Configure your Dockerfile to install Tailscale</a></h2>\n<p>We recommend using a <a href=\"https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds\">multistage Dockerfile</a> where the first stage builds your application, and the second stage pulls application code and Tailscale into the final image to be uploaded to Heroku.</p>\n<p>Create a <code>Dockerfile</code> at the root of your app. In that <code>Dockerfile</code> add something like:</p>\n<pre><code class=\"language-docker\">FROM golang:1.16.2-alpine3.13 as builder\r\nWORKDIR /app\r\nCOPY . ./\r\n# This is where one could build the application code as well.\r\n\r\n# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds\r\nFROM alpine:latest\r\nRUN apk update &#x26;&#x26; apk add ca-certificates &#x26;&#x26; rm -rf /var/cache/apk/*\r\n\r\n# Copy binary to production image.\r\nCOPY --from=builder /app/start.sh /app/start.sh\r\n\r\n# Copy Tailscale binaries from the tailscale image on Docker Hub.\r\nCOPY --from=docker.io/tailscale/tailscale:stable /usr/local/bin/tailscaled /app/tailscaled\r\nCOPY --from=docker.io/tailscale/tailscale:stable /usr/local/bin/tailscale /app/tailscale\r\nRUN mkdir -p /var/run/tailscale /var/cache/tailscale /var/lib/tailscale\r\n\r\n# Run on container startup.\r\nCMD [\"/app/start.sh\"]\n</code></pre>\n<p>The Dockerfile specifies <code>/app/start.sh</code> as the initial process to run. This script needs to bring Tailscale up and then start the application binary. This is where we can use the <code>TAILSCALE_AUTHKEY</code> variable we defined earlier.</p>\n<p>Then, create a file named <code>start.sh</code> at the root of your app:</p>\n<pre><code class=\"language-shell\">#!/bin/sh\r\n\r\n/app/tailscaled --tun=userspace-networking --socks5-server=localhost:1055 &#x26;\r\n/app/tailscale up --auth-key=${TAILSCALE_AUTHKEY} --hostname=heroku-app\r\necho Tailscale started\r\nALL_PROXY=socks5://localhost:1055/ /app/my-app\n</code></pre>\n<p>The next time your Heroku app deploys, it will be able to connect to your private Tailscale network.</p>\n<h2><a href=\"https://tailscale.com/docs/install/cloud/heroku#remove-ephemeral-nodes-from-a-tailnet\">Remove ephemeral nodes from a tailnet</a></h2>\n<p>When an ephemeral node goes offline, it is automatically removed from your tailnet. You can also control ephemeral node removal using the <a href=\"https://tailscale.com/docs/reference/tailscale-cli#logout\"><code>tailscale logout</code></a> command to either manually force the removal or incorporate the command into the <a href=\"https://tailscale.com/docs/reference/tailscaled\"><code>tailscaled</code></a> Tailscale daemon. For more information, refer to <a href=\"https://tailscale.com/docs/features/ephemeral-nodes#faq\">Ephemeral nodes</a>.</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"}