How to Install Tailscale on Flatcar for VPN Access

Tailscale is a powerful tool that allows remote access to your UMH instances running on edge devices without the need to physically be on site. In this tutorial, we will walk you through the steps to install Tailscale on Flatcar, ensuring secure and reliable VPN access to your IT/OT infrastructure.

Instructions

There are three options to install it. Our recommendation is to go for beginners with option 1 and leverage our Management Console in the future. Advanced users running their own deployment infrastructure using matchbox, can also check out option 2.

ℹ️
If you want to understand exactly what happens during the flatcar installation, how we deploy our IT / OT architecture and what ignition files are, check out our blog article about the reason we use flatcar.

To install Tailscale on Flatcar using the recommended method, you will need to have an instance of Flatcar already running and SSH access to it.

Step 1: Create three files

Create the following three files on your Flatcar instance:

/opt/tailscale-install.sh

#!/usr/bin/env bash
set -e

# Only re-download if not already existing
if ! test -e /etc/tailscale; then
echo "Downloading tailscale"
wget https://pkgs.tailscale.com/stable/tailscale_1.34.1_amd64.tgz -O tailscale_1.34.1.tgz

echo "Unpacking tailscale"
tar xvf tailscale_1.34.1.tgz -C /tmp

echo "Removing tgz"
rm tailscale_1.34.1.tgz

echo "Moving binaries (if not exist)"
sudo mkdir -p /etc/tailscale
sudo cp -n /tmp/tailscale_1.34.1_amd64/tailscale /etc/tailscale/tailscale
sudo cp -n /tmp/tailscale_1.34.1_amd64/tailscaled /etc/tailscale/tailscaled

echo "Enabling service"
sudo systemctl enable tailscaled.service

echo "Reloading systemd"
systemctl daemon-reload

echo "Cleaning up tmp folder"
rm -r /tmp/tailscale_1.34.1_amd64
fi

echo "Starting service"
sudo systemctl restart tailscaled.service

echo "Allowing IP forwarding"
sudo rm -f /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf

sudo /etc/tailscale/tailscale up --advertise-routes=172.16.104.0/24 --qr
⚠️
Please change the command sudo /etc/tailscale/tailscale up --advertise-routes=172.16.104.0/24 --qr according to your needs. The default command advertises the entire subnet 172.16.104.0/24 to tailscale. If you just want to access the host, you can remove the --advertise-routes option

/etc/systemd/system/tailscale-install.service

[Unit]
Description=Run Tailscale installation script
Wants = network-online.target
After = network.target network-online.target
ConditionPathExists=/opt/tailscale-install.sh
ConditionPathExists=!/etc/tailscale/tailscaled
[Service]
Type=forking
TimeoutStartSec=180
RemainAfterExit=yes
KillMode=process
ExecStartPre=/bin/sleep 30
ExecStart=/usr/bin/sh -c "/opt/tailscale-install.sh"
[Install]
WantedBy=multi-user.target

/etc/systemd/system/tailscaled.service

[Unit]
Description=Tailscale node agent
Documentation=https://tailscale.com/kb/
Wants=network-pre.target tailscale-install.service
After=network-pre.target NetworkManager.service systemd-resolved.service
[Service]
User=0
Group=0
ExecStartPre=/etc/tailscale/tailscaled --cleanup
ExecStart=/etc/tailscale/tailscaled --state=/var/lib/tailscale/tailscaled.state --socket=/run/tailscale/tailscaled.sock --port=41641
ExecStopPost=/etc/tailscale/tailscaled --cleanup
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/bin:/etc/tailscale"
Restart=on-failure
RuntimeDirectory=tailscale
RuntimeDirectoryMode=0755
StateDirectory=tailscale
StateDirectoryMode=0700
CacheDirectory=tailscale
CacheDirectoryMode=0750
Type=notify
[Install]
WantedBy=multi-user.target

Step 2: Reboot the system and wait a few minutes.

After creating these files, reboot the system and wait a few minutes for the services to start up.

Step 3: Authorize the device with your Tailscale instance

If everything was successful, you will receive a link to authorize the device with your Tailscale instance using this command:

sudo journalctl -u tailscale-install.service

Alternatively, if you prefer to wait, you can take advantage of the upcoming feature in the Management Console to leverage immutable infrastructure without the need to run your own deployment infrastructure.

Option 2: for advanced users in the ignition file

This method is recommended for advanced users who want to install Tailscale on Flatcar during installation and follow the immutable infrastructure approach for easy replication.

Step 1: Add the Following Code to the Ignition File

storage:
  files:
    - path: /opt/tailscale-install.sh
      filesystem: root
      mode: 777
      contents:
        inline: |
          #!/usr/bin/env bash
          set -e
          
          # Only re-download if not already existing
          if ! test -e /etc/tailscale; then
          echo "Downloading tailscale"
          wget https://pkgs.tailscale.com/stable/tailscale_1.34.1_amd64.tgz -O tailscale_1.34.1.tgz
          
          echo "Unpacking tailscale"
          tar xvf tailscale_1.34.1.tgz -C /tmp
          
          echo "Removing tgz"
          rm tailscale_1.34.1.tgz
          
          echo "Moving binaries (if not exist)"
          sudo mkdir -p /etc/tailscale
          sudo cp -n /tmp/tailscale_1.34.1_amd64/tailscale /etc/tailscale/tailscale
          sudo cp -n /tmp/tailscale_1.34.1_amd64/tailscaled /etc/tailscale/tailscaled
          
          echo "Enabling service"
          sudo systemctl enable tailscaled.service
          
          echo "Reloading systemd"
          systemctl daemon-reload
          
          echo "Cleaning up tmp folder"
          rm -r /tmp/tailscale_1.34.1_amd64
          fi
          
          echo "Starting service"
          sudo systemctl restart tailscaled.service
          
          echo "Allowing IP forwarding"
          sudo rm -f /etc/sysctl.d/99-tailscale.conf
          echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
          echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
          sudo sysctl -p /etc/sysctl.d/99-tailscale.conf
          
          sudo /etc/tailscale/tailscale up --advertise-routes=172.16.104.0/24 --qr
⚠️
Modify the command sudo /etc/tailscale/tailscale up --advertise-routes=172.16.104.0/24 --qr according to your needs. The default command advertises the entire subnet 172.16.104.0/24 to Tailscale. If you only want to access the host, you can remove the --advertise-routes option.

Step 2: Add the Following Code to the Ignition File

systemd:
  units:
    - name: tailscale-install.service
      enabled: true
      contents: |
        [Unit]
        Description=Run Tailscale installation script
        Wants = network-online.target
        After = network.target network-online.target
        ConditionPathExists=/opt/tailscale-install.sh
        ConditionPathExists=!/etc/tailscale/tailscaled
        [Service]
        Type=forking
        TimeoutStartSec=180
        RemainAfterExit=yes
        KillMode=process
        ExecStartPre=/bin/sleep 30
        ExecStart=/usr/bin/sh -c "/opt/tailscale-install.sh"
        [Install]
        WantedBy=multi-user.target
    - name: tailscaled.service
      enabled: true
      contents: |
        [Unit]
        Description=Tailscale node agent
        Documentation=https://tailscale.com/kb/
        Wants=network-pre.target tailscale-install.service
        After=network-pre.target NetworkManager.service systemd-resolved.service
        [Service]
        User=0
        Group=0
        ExecStartPre=/etc/tailscale/tailscaled --cleanup
        ExecStart=/etc/tailscale/tailscaled --state=/var/lib/tailscale/tailscaled.state --socket=/run/tailscale/tailscaled.sock --port=41641
        ExecStopPost=/etc/tailscale/tailscaled --cleanup
        Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/bin:/etc/tailscale"
        Restart=on-failure
        RuntimeDirectory=tailscale
        RuntimeDirectoryMode=0755
        StateDirectory=tailscale
        StateDirectoryMode=0700
        CacheDirectory=tailscale
        CacheDirectoryMode=0750
        Type=notify
        [Install]
        WantedBy=multi-user.target

Step 3: Authorize the device with your Tailscale instance

If everything was successful, you will receive a link to authorize the device with your Tailscale instance using this command:

sudo journalctl -u tailscale-installer.service

Alternatively, if you prefer to wait, you can take advantage of the upcoming feature in the Management Console to leverage immutable infrastructure without the need to run your own deployment infrastructure.