{"slug":"tailscale-with-gitlab-cicd","title":"Tailscale with GitLab CI/CD","tags":["tailscale"],"agent_summary":"Last validated: Dec 4, 2025","trigger_phrases":[],"runnable":false,"markdown":"\r\n# Tailscale with GitLab CI/CD\r\n\r\nLast validated: Dec 4, 2025\r\n\r\nThe [Tailscale GitLab configuration](https://gitlab.com/tailscale-dev/gitlab-ci-cd) enables connecting your Tailscale network\r\n(known as a tailnet) to a [GitLab Runner](https://docs.gitlab.com/runner).\r\n\r\nWith this configuration, you can access nodes in your tailnet directly from your GitLab Runner. Some example uses are:\r\n\r\n- Securely deploy your application to an internal server\r\n- Securely reach your private test runners for specific platforms\r\n- Reach your database of test data without leaving it exposed on the internet\r\n- Access an internal deployment monitoring tool\r\n\r\n## [How it works](https://tailscale.com/docs/integrations/gitlab/gitlab-runner\\#how-it-works)\r\n\r\nWhen you add the Tailscale GitLab configuration to your runner, subsequent steps in your runner\r\ncan then access nodes in your tailnet. For example, the runner could access a node that has a\r\ndatabase of test data.\r\n\r\nThe Tailscale GitLab configuration requires an [auth key](https://tailscale.com/docs/features/access-control/auth-keys), which is tagged, reusable, ephemeral, and (if applicable) pre-approved. You store the auth key as an\r\n[external GitLab secret](https://docs.gitlab.com/ee/ci/secrets). The tag grants the access permission\r\nto any node created by your runner.\r\n\r\nWhen your runner executes, it uses the auth key to create an\r\n[ephemeral node](https://tailscale.com/docs/features/ephemeral-nodes). The node can then access nodes in your tailnet, subject to the\r\naccess applied to the tags.\r\n\r\nBecause the node is ephemeral, shortly after the action completes, the node is automatically removed\r\nfrom your tailnet. The next time the action runs, it creates a new ephemeral node, available only\r\nfor the new runner.\r\n\r\nAny node that the Tailscale GitLab configuration creates is [pre-approved](https://tailscale.com/docs/features/access-control/auth-keys#types-of-auth-keys) on\r\ntailnets that use [device approval](https://tailscale.com/docs/features/access-control/device-management/device-approval).\r\n\r\n## [Add Tailscale to a GitLab Runner](https://tailscale.com/docs/integrations/gitlab/gitlab-runner\\#add-tailscale-to-a-gitlab-runner)\r\n\r\n1. Create at least one [tag](https://tailscale.com/docs/features/tags) for the nodes that the GitLab configuration will create.\r\nFor example, `tag:ci`, which is used for this example. The access permissions that you grant to\r\nthe tags are applied to the nodes that will be created by the runner.\r\n\r\n2. Create an [auth key](https://tailscale.com/docs/features/access-control/auth-keys). We recommend that the [key type](https://tailscale.com/docs/features/access-control/auth-keys#types-of-auth-keys) is tagged,\r\nreusable, and ephemeral. If the tailnet uses [device approval](https://tailscale.com/docs/features/access-control/device-management/device-approval), ensure that the\r\nkey type is also pre-approved.\r\n\r\n3. Create a [GitLab secret](https://docs.gitlab.com/ee/ci/secrets) with the name `TAILSCALE_AUTHKEY` and the value set to your auth key.\r\nThen use the `authkey` field to reference the secret in your runner. For example:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n```shell\r\ntailscale up --auth-key=${TAILSCALE_AUTHKEY} --hostname=\"gitlab-$(cat /etc/hostname)\" --accept-routes\r\n```\r\n\r\n\r\nWhen the action runs, it creates an ephemeral node. The node can access nodes in your tailnet,\r\nsubject to the access rules applied to the specified tag or tags. In the rest of your runner,\r\naccess other nodes in your tailnet as needed.\r\n\r\nThe ephemeral node is automatically cleaned up shortly after the action finishes.\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 with GitLab CI/CD</h1>\n<p>Last validated: Dec 4, 2025</p>\n<p>The <a href=\"https://gitlab.com/tailscale-dev/gitlab-ci-cd\">Tailscale GitLab configuration</a> enables connecting your Tailscale network\r\n(known as a tailnet) to a <a href=\"https://docs.gitlab.com/runner\">GitLab Runner</a>.</p>\n<p>With this configuration, you can access nodes in your tailnet directly from your GitLab Runner. Some example uses are:</p>\n<ul>\n<li>Securely deploy your application to an internal server</li>\n<li>Securely reach your private test runners for specific platforms</li>\n<li>Reach your database of test data without leaving it exposed on the internet</li>\n<li>Access an internal deployment monitoring tool</li>\n</ul>\n<h2><a href=\"https://tailscale.com/docs/integrations/gitlab/gitlab-runner#how-it-works\">How it works</a></h2>\n<p>When you add the Tailscale GitLab configuration to your runner, subsequent steps in your runner\r\ncan then access nodes in your tailnet. For example, the runner could access a node that has a\r\ndatabase of test data.</p>\n<p>The Tailscale GitLab configuration requires an <a href=\"https://tailscale.com/docs/features/access-control/auth-keys\">auth key</a>, which is tagged, reusable, ephemeral, and (if applicable) pre-approved. You store the auth key as an\r\n<a href=\"https://docs.gitlab.com/ee/ci/secrets\">external GitLab secret</a>. The tag grants the access permission\r\nto any node created by your runner.</p>\n<p>When your runner executes, it uses the auth key to create an\r\n<a href=\"https://tailscale.com/docs/features/ephemeral-nodes\">ephemeral node</a>. The node can then access nodes in your tailnet, subject to the\r\naccess applied to the tags.</p>\n<p>Because the node is ephemeral, shortly after the action completes, the node is automatically removed\r\nfrom your tailnet. The next time the action runs, it creates a new ephemeral node, available only\r\nfor the new runner.</p>\n<p>Any node that the Tailscale GitLab configuration creates is <a href=\"https://tailscale.com/docs/features/access-control/auth-keys#types-of-auth-keys\">pre-approved</a> on\r\ntailnets that use <a href=\"https://tailscale.com/docs/features/access-control/device-management/device-approval\">device approval</a>.</p>\n<h2><a href=\"https://tailscale.com/docs/integrations/gitlab/gitlab-runner#add-tailscale-to-a-gitlab-runner\">Add Tailscale to a GitLab Runner</a></h2>\n<ol>\n<li>\n<p>Create at least one <a href=\"https://tailscale.com/docs/features/tags\">tag</a> for the nodes that the GitLab configuration will create.\r\nFor example, <code>tag:ci</code>, which is used for this example. The access permissions that you grant to\r\nthe tags are applied to the nodes that will be created by the runner.</p>\n</li>\n<li>\n<p>Create an <a href=\"https://tailscale.com/docs/features/access-control/auth-keys\">auth key</a>. We recommend that the <a href=\"https://tailscale.com/docs/features/access-control/auth-keys#types-of-auth-keys\">key type</a> is tagged,\r\nreusable, and ephemeral. If the tailnet uses <a href=\"https://tailscale.com/docs/features/access-control/device-management/device-approval\">device approval</a>, ensure that the\r\nkey type is also pre-approved.</p>\n</li>\n<li>\n<p>Create a <a href=\"https://docs.gitlab.com/ee/ci/secrets\">GitLab secret</a> with the name <code>TAILSCALE_AUTHKEY</code> and the value set to your auth key.\r\nThen use the <code>authkey</code> field to reference the secret in your runner. For example:</p>\n</li>\n</ol>\n<pre><code class=\"language-shell\">tailscale up --auth-key=${TAILSCALE_AUTHKEY} --hostname=\"gitlab-$(cat /etc/hostname)\" --accept-routes\n</code></pre>\n<p>When the action runs, it creates an ephemeral node. The node can access nodes in your tailnet,\r\nsubject to the access rules applied to the specified tag or tags. In the rest of your runner,\r\naccess other nodes in your tailnet as needed.</p>\n<p>The ephemeral node is automatically cleaned up shortly after the action finishes.</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"}