This role installs and configures Tailscale on a Linux target.
Supported operating systems:
- Debian / Ubuntu
- CentOS / RedHat
- Rocky Linux / AlmaLinux
- Amazon Linux 2023 / Amazon Linux 2
- Fedora
- Arch Linux
- OpenSUSE
- Oracle Linux
- Raspbian
See the CI worfklow for the list of distribution versions actively tested in each pull request.
Tip
This role uses Ansible fully qualified collection names (FQCN) and therefore requires Ansible 2.11+. Ansible 2.12 is set as the minimum required version as this was the version tested for compatibility during the FQCN refactor.
If you or your organization gets value out of this role, I would very much appreciate one-time or recurring sponsorship of this role.
- Role Outputs
- Role Variables
- Dependencies
- Example Playbook
- State Tracking
- License
- Author Information
- Development and Contributing
This role will bubble up any stderr messages from the Tailscale binary
to resolve any end-user configuration errors with tailscale up
arguments.
The --authkey=
value will be redacted unless insecurely_log_authkey
is set to true
.
This role provides the IP v4 and v6 addresses of the Tailscale node as well as the output of tailscale whois
against the node as facts.
Several key pieces of whois
information are provided directly, with the rest of the whois output stored as a JSON fact for your convenience.
Outputted facts:
tailscale_node_ipv4 (string): The IPv4 address of the Tailscale node.
tailscale_node_ipv6 (string): The IPv6 address of the Tailscale node.
tailscale_node_hostname_full (string): The full hostname (node.domain.ts.net) of the Tailscale node.
tailscale_node_hostname_short (string): The short hostname (node) of the Tailscale node.
tailscale_node_created_at (string): The ISO-8601 timestamp the Tailscale node was created.
tailscale_node_tags (list): The tags assigned to the Tailscale node.
tailscale_node_services (list): The discovered services running on the Tailscale node.
tailscale_node_whois (dict): The full output of `tailscale whois` against the Tailscale node.
One of tailscale_authkey
or tailscale_up_skip
must be present.
In most cases you will use tailscale_authkey
.
If you are uninstalling Tailscale (state: absent
),
neither tailscale_authkey
nor tailscale_up_skip
is required.
If you are authenticating with an OAuth key, you must also set tailscale_tags
.
Is not required if tailscale_up_skip
is set to true
.
A Tailscale Node Authorization auth key.
A Node Authorization key can be generated under your Tailscale account. The role supports two type of keys:
- Auth key (
tskey-auth-XXX-YYYYY
) https://login.tailscale.com/admin/authkeys - OAuth key (
tskey-client-XXX-YYYY
) https://login.tailscale.com/admin/settings/oauth
Important
Using an OAuth key requires the following role variables:
tailscale_tags
(must be provided),
tailscale_oauth_ephemeral
(defaults to true
),
and tailscale_oauth_preauthorized
(defaults to false
).
Note that auth keys expire up to a maximum of 90 days after they are generated. OAuth secrets do not expire unless revoked, and the generated OAuth access token expires after 1 hour.
For more information, see Tailscale's OAuth clients page, especially Generating long-lived auth keys.
If an OAuth key is used, be sure to grant the write
Devices scope to the OAuth client.
This value should be treated as a sensitive secret.
Default: []
Apply supplied tags to the Tailscale nodes configured by this role
(via the --advertise-tags
flag to tailscale up
).
For more information, see What are tags?
Note
Tags are required for OAuth clients (tailscale_authkey
OAuth key).
Entries should not include tag:
.
For example, tailscale_tags: ['worker']
translates to --advertise-tags=tag:worker
.
If set to true, tailscale_authkey
is not required.
Default: false
Whether to install and configure Tailscale as a service but skip running tailscale up
.
Helpful when packaging up a Tailscale installation into a build process, such as AMI creation,
when the server should not yet authenticate to your Tailscale network.
Default: latest
Whether to install or uninstall Tailscale.
If defined, state
must be either latest
, present
, or absent
.
This role uses latest
by default to help ensure your software remains up-to-date
and incorporates the latest security and product features.
For users who desire more control over configuration drift,
present
will not update Tailscale if it is already installed.
Changes to tailscale_args
will be applied under both latest
and present
;
this parameter only impacts the version of Tailscale installed to the target system.
If set to absent
, this role will de-register the Tailscale node (if already authenticated)
and clean up or disable all Tailscale artifacts added to the system.
Note that neither tailscale_authkey
nor tailscale_up_skip
is required if state
is set to absent
.
Pass command-line arguments to tailscale up
.
Note that the command module is used,
which does not support subshell expressions ($()
) or bash operations like ;
and &
.
Only tailscale up
arguments can be passed in.
Caution
Do not use this for --authkey
.
Use the tailscale_authkey
variable instead.
Do not use this for --advertise-tags
.
Use the tailscale_tags
variable instead.
Do not use this for --timeout
.
Use the tailscale_up_timeout
variable instead.
Any stdout/stderr output from the tailscale
binary will be printed.
Since the tasks move quickly in this section, a 5 second pause is introduced
to grant more time for users to realize a message was printed.
Stderrs will continue to fail the role's execution.
The sensitive --authkey
value will be redacted by default.
If you need to view the unredacted value, see insecurely_log_authkey
.
Note
Used only when tailscale_authkey
is an OAuth key.
Default: true
Register as an ephemeral node, if true
.
Note
Used only when tailscale_authkey
is an OAuth key.
Default: false
Skip manual device approval, if true
.
Default: false
If set to true
, the "Bring Tailscale Up" command will include the raw value of the Tailscale authkey
when logging any errors encountered during tailscale up
.
By default, the authkey is not logged in successful task completions
and is redacted in the stderr
output by this role if an error occurs.
If you are encountering an error bringing Tailscale up
and want the "Bring Tailscale Up" task to not redact the value of the authkey,
set this variable to true
.
Regardless, if the authkey is invalid, the role will relay Tailscale's error message on that fact:
Default: stable
Whether to use the Tailscale stable or unstable track.
stable
:
Stable releases. If you're not sure which track to use, pick this one.
unstable
:
The bleeding edge. Pushed early and often. Expect rough edges!
Default: 120
Defines the timeout duration for the tailscale up
command in seconds.
--timeout duration
maximum amount of time to wait for tailscaled to enter a Running state
Default: false
Whether to output additional information during role execution. Helpful for debugging and collecting information to submit in a GitHub issue on this repository.
- name: Servers
hosts: all
roles:
- role: artis3n.tailscale
vars:
# Example pulling the API key from the env vars on the host running Ansible
tailscale_authkey: "{{ lookup('env', 'TAILSCALE_KEY') }}"
Enable Tailscale SSH:
- name: Servers
hosts: all
roles:
- role: artis3n.tailscale
vars:
# Example pulling the API key from the env vars on the host running Ansible
tailscale_authkey: "{{ lookup('env', 'TAILSCALE_KEY') }}"
tailscale_args: "--ssh"
Pass arbitrary command-line arguments:
- name: Servers
hosts: all
tasks:
- name: Use Headscale
include_role:
name: artis3n.tailscale
vars:
tailscale_args: "--login-server='http://localhost:8080'"
tailscale_authkey: "{{ lookup('env', 'HEADSCALE_KEY') }}"
Get verbose output:
- name: Servers
hosts: all
roles:
- role: artis3n.tailscale
vars:
verbose: true
tailscale_authkey: "{{ lookup('env', 'TAILSCALE_KEY') }}"
Connect using an OAuth client secret:
- name: Servers
hosts: all
roles:
- role: artis3n.tailscale
vars:
verbose: true
tailscale_authkey: "{{ lookup('env', 'TAILSCALE_OAUTH_CLIENT_SECRET') }}"
tailscale_tags:
- "oauth"
# Optionally, also include:
tailscale_oauth_ephemeral: true
tailscale_oauth_preauthorized: false
Install Tailscale, but don't authenticate to the network:
- name: Servers
hosts: all
roles:
- role: artis3n.tailscale
vars:
tailscale_up_skip: true
De-register and uninstall a Tailscale node:
- name: Servers
hosts: all
roles:
- role: artis3n.tailscale
vars:
state: absent
This role will create an artis3n-tailscale
directory in the target's XDG_STATE_HOME
directory,
or $HOME/.local/state
if the variable is not present,
in order to maintain a concept of state from the configuration of the arguments passed to tailscale up
.
This allows the role to idempotently update a Tailscale node's configuration when needed.
Deleting this directory will lead to this role re-configuring Tailscale when it is not needed,
but will not otherwise break anything.
However, it is recommended that you let this Ansible role manage this directory and its contents.
Note that:
Flags are not persisted between runs; you must specify all flags each time.
...
In Tailscale v1.8 or later, if you forget to specify a flag you added before, the CLI will warn you and provide a copyable command that includes all existing flags.
MIT
Ari Kalfus (@artis3n) dev@artis3nal.com
This GitHub repository uses a dedicated "test" Tailscale account to authenticate Tailscale during CI runs. Each Docker container creates a new authorized machine in that test account. The machines are authorized with ephemeral auth keys and are automatically cleaned up.
This authkey is stored in a GitHub Action secret with the name TAILSCALE_CI_KEY
.
To test OAuth authkey compatibility, a Tailscale OAuth client secret is stored as TAILSCALE_OAUTH_CLIENT_SECRET
.
If you are a Collaborator on this repository,
you can open a GitHub CodeSpace and these secrets will be pre-populated for you in the environment.
To test this role locally, store the Tailscale ephemeral auth key in a TAILSCALE_CI_KEY
env var
and, if running the oauth
Molecule scenario,
add an OAuth client secret in a TAILSCALE_OAUTH_CLIENT_SECRET
env var.
Alternatively for Molecule testing,
you can use a Headscale container that is spun up as part of the create/prepare steps.
To do this, set a USE_HEADSCALE
env variable.
For example:
USE_HEADSCALE=true molecule test