Difference between revisions of "Tailscale"

From Indie IT Wiki
 
(32 intermediate revisions by the same user not shown)
Line 10: Line 10:
  
 
A Tailscale network (tailnet) is private network which Tailscale assigns to a user in terms of private users or an organisation.
 
A Tailscale network (tailnet) is private network which Tailscale assigns to a user in terms of private users or an organisation.
 +
 +
You can run Tailscale as an '''SSH Server''' and as an '''Exit Node''' - which means you can remove any SSH ports and have the Tailscale handle all the authentication and use itself as a '''Gateway''' for any node on your Tailscale network.  Amazing.
  
 
== Self Hosting ==
 
== Self Hosting ==
  
You can self host a Tailscale server with Headscale + Headscale UI.
+
You can self host a Tailscale server with Headscale + Headscale Admin.
  
 
'''[https://github.com/juanfont/headscale Headscale]''' is an open source, self-hosted implementation of the Tailscale control server. Headscale's goal is to provide self-hosters and hobbyists with an open-source server they can use for their projects and labs. It implements a narrow scope, a single Tailnet, suitable for a personal use, or a small open-source organisation.
 
'''[https://github.com/juanfont/headscale Headscale]''' is an open source, self-hosted implementation of the Tailscale control server. Headscale's goal is to provide self-hosters and hobbyists with an open-source server they can use for their projects and labs. It implements a narrow scope, a single Tailnet, suitable for a personal use, or a small open-source organisation.
  
'''[https://github.com/gurucomputing/headscale-ui Headscale UI]''' is a web frontend for the headscale Tailscale-compatible coordination server.
+
'''[https://github.com/GoodiesHQ/headscale-admin Headscale Admin]''' is a web frontend for the headscale Tailscale-compatible coordination server.
  
 
[https://www.youtube.com/watch?v=OECp6Pj2ihg YouTube - Jim's Garage - Self Host Tailscale with Headscale]
 
[https://www.youtube.com/watch?v=OECp6Pj2ihg YouTube - Jim's Garage - Self Host Tailscale with Headscale]
Line 25: Line 27:
 
=== Docker ===
 
=== Docker ===
  
You can self host a Tailscale server with Headscale + Headscale UI + Traefik docker containers.
+
You can self host a Tailscale server with Headscale + Headscale Admin + Traefik docker containers.
  
 
Follow the instructions on the respective web sites and the YouTube (outdated though!) video to get started, including grabbing copies of the docker compose and '''headscale config/config.yaml files''', then edit the first 3 options as follows ...
 
Follow the instructions on the respective web sites and the YouTube (outdated though!) video to get started, including grabbing copies of the docker compose and '''headscale config/config.yaml files''', then edit the first 3 options as follows ...
Line 49: Line 51:
 
  3 directories, 5 files
 
  3 directories, 5 files
  
... and this is the docker compose YAML file which has both Headscale and Headscale UI containers ...
+
... and this is the docker compose YAML file which has both Headscale and Headscale Admin containers ...
  
 
  services:
 
  services:
Line 73: Line 75:
 
       - "traefik.enable=true"
 
       - "traefik.enable=true"
 
       - "traefik.docker.network=traefik"
 
       - "traefik.docker.network=traefik"
       - "traefik.http.routers.headscale.rule=PathPrefix(`/`) && Host(`headscale.mydomain.com`)"
+
       - "traefik.http.routers.headscale.rule=Host(`headscale.mydomain.com`) && PathPrefix(`/`)"
 
       - "traefik.http.routers.headscale.entrypoints=websecure"
 
       - "traefik.http.routers.headscale.entrypoints=websecure"
 
       - "traefik.http.routers.headscale.service=headscale"
 
       - "traefik.http.routers.headscale.service=headscale"
Line 79: Line 81:
 
       - "traefik.http.services.headscale.loadbalancer.server.scheme=http"
 
       - "traefik.http.services.headscale.loadbalancer.server.scheme=http"
 
   
 
   
   headscale-ui:
+
   headscale-admin:
     image: ghcr.io/gurucomputing/headscale-ui:latest
+
     image: goodieshq/headscale-admin:latest
    pull_policy: always
+
     container_name: headscale-admin
     container_name: headscale-ui
 
 
     restart: unless-stopped
 
     restart: unless-stopped
 +
    environment:
 +
      - TZ=Europe/London
 +
    volumes:
 +
        - ./config:/etc/headscale/
 +
        - ./data:/var/lib/headscale/
 +
        - ./run:/var/run/headscale/
 
     ports:
 
     ports:
        - 9999:80
+
      - 9999:80
 
     networks:
 
     networks:
 
       traefik:
 
       traefik:
Line 92: Line 99:
 
       - "traefik.enable=true"
 
       - "traefik.enable=true"
 
       - "traefik.docker.network=traefik"
 
       - "traefik.docker.network=traefik"
       - "traefik.http.routers.headscale-ui.rule=PathPrefix(`/web`) && Host(`headscale.mydomain.com`)"
+
       - "traefik.http.routers.headscale-admin.rule=Host(`headscale.mydomain.com`) && PathPrefix(`/admin`)"
       - "traefik.http.routers.headscale-ui.entrypoints=websecure"
+
       - "traefik.http.routers.headscale-admin.entrypoints=websecure"
       - "traefik.http.routers.headscale-ui.service=headscale-ui"
+
       - "traefik.http.routers.headscale-admin.service=headscale-admin"
       - "traefik.http.routers.headscale-ui.middlewares=auth"
+
       - "traefik.http.routers.headscale-admin.middlewares=auth"
       - "traefik.http.services.headscale-ui.loadbalancer.server.port=80"
+
       - "traefik.http.services.headscale-admin.loadbalancer.server.port=80"
       - "traefik.http.services.headscale-ui.loadbalancer.server.scheme=http"
+
       - "traefik.http.services.headscale-admin.loadbalancer.server.scheme=http"
 
       - "traefik.http.middlewares.auth.basicauth.users=funkyusername:xxxxxxxxxxxxxxxxhashedxxxxpasswordxxxxxxxxxxxxxxx"
 
       - "traefik.http.middlewares.auth.basicauth.users=funkyusername:xxxxxxxxxxxxxxxxhashedxxxxpasswordxxxxxxxxxxxxxxx"
 
   
 
   
Line 106: Line 113:
 
Start up the containers, and you should see these lines in the docker logs ...
 
Start up the containers, and you should see these lines in the docker logs ...
  
  headscale     | 2024-05-31T10:53:13+01:00 INF Opening database database=sqlite3 path=/var/lib/headscale/db.sqlite
+
  headscale       | 2024-05-31T10:53:13+01:00 INF Opening database database=sqlite3 path=/var/lib/headscale/db.sqlite
  headscale     | 2024-05-31T10:53:13+01:00 INF Setting up a DERPMap update worker frequency=86400000
+
  headscale       | 2024-05-31T10:53:13+01:00 INF Setting up a DERPMap update worker frequency=86400000
  headscale     | 2024-05-31T10:53:13+01:00 INF listening and serving HTTP on: 0.0.0.0:8080
+
  headscale       | 2024-05-31T10:53:13+01:00 INF listening and serving HTTP on: 0.0.0.0:8080
  headscale-ui | {"level":"info","ts":1717149193.3994539,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
+
  headscale-admin | {"level":"info","ts":1717149193.3994539,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
  headscale-ui | {"level":"info","ts":1717149193.4059176,"msg":"serving initial configuration"}
+
  headscale-admin | {"level":"info","ts":1717149193.4059176,"msg":"serving initial configuration"}
  
 
Test the headscale server with curl and the docker image ...
 
Test the headscale server with curl and the docker image ...
Line 120: Line 127:
 
  docker exec headscale headscale apikeys list
 
  docker exec headscale headscale apikeys list
  
Navigate to the Headscale UI web address you provided in the config.yml file with /web at the end - <nowiki>https://headscale.mydomain.com/web</nowiki>) and then you will see an error about Authentication and missing API key.
+
Navigate to the Headscale Admin web address you provided in the config.yml file with /admin at the end - <nowiki>https://headscale.mydomain.com/admin</nowiki>) and then you will see an error about Authentication and missing API key.
  
 
Generate your server's API key. '''You only get one chance to see this''' ...
 
Generate your server's API key. '''You only get one chance to see this''' ...
Line 126: Line 133:
 
  docker exec headscale headscale apikeys create
 
  docker exec headscale headscale apikeys create
  
... copy it, then go the Headscale UI Settings page and paste it there with your 'server_url' from the config file.
+
... copy it, then go the Headscale Admin Settings page and paste it there with your 'server_url' from the config file.
  
There is NO save settings button, it does it automatically but you can then press the '''Test Server Settings''' button.
+
Then press the SAVE button.
  
 
Yay - you have successfuly set up your own self-hosted Tailscale server!  :-)
 
Yay - you have successfuly set up your own self-hosted Tailscale server!  :-)
Line 135: Line 142:
  
 
== Client Devices ==
 
== Client Devices ==
 +
 +
=== Windows ===
 +
 +
https://tailscale.com/download/windows
 +
 +
[https://forum.tailscale.com/t/prevent-auto-connect-on-restart-login/4002/10 Prevent Auto-Connect on Restart/Login]
  
 
=== Linux ===
 
=== Linux ===
  
Generate a User on the Headscale server first, then register a Node linked to that User.
+
=== Software Installation ===
 +
 
 +
'''Native'''
 +
 
 +
Install the software ...
 +
 
 +
curl -fsSL <nowiki>https://tailscale.com/install.sh</nowiki> | sh
 +
 
 +
Go to your Admin server and grab your pre-auth key.
 +
 
 +
Join the tailnet ...
 +
 
 +
tailscale up --login-server=<nowiki>https://headscale.mydomain.uk</nowiki> --authkey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --accept-dns=false
 +
 
 +
'''WEB'''
 +
 
 +
There is a built-in web interface with tailscale, which you can access by running this command ...
  
==== Users ====
+
sudo tailscale set --webclient
  
docker exec headscale headscale users create <USER_NAME>
+
... and then pointing your web browser at the address it tells you to - e.g. <nowiki>http://100.64.0.1:5252</nowiki>
  
==== Nodes ====
+
To stop the web interface, run this command ...
  
===== Software Installation =====
+
sudo tailscale set --webclient=false
  
'''Native'''
+
'''GUI'''
  
curl -fsSL <nowiki>https://tailscale.com/install.sh</nowiki> | sh
+
https://github.com/DeedleFake/trayscale
  
 
'''Docker'''
 
'''Docker'''
  
To be done.
+
https://hub.docker.com/r/tailscale/tailscale
 +
 
 +
https://tailscale.com/kb/1282/docker
 +
 
 +
Create your ''pre-auth key'' on your Headscale server using Headscale Admin.
 +
 
 +
Pull the image ...
 +
 
 +
docker pull tailscale/tailscale:latest
 +
 
 +
Start the docker passing the login server and pre-auth key environment variables ...
 +
 
 +
docker run -d --name=tailscale -v /var/lib:/var/lib -v /dev/net/tun:/dev/net/tun --network=host --cap-add=NET_ADMIN --cap-add=NET_RAW --env TS_STATE_DIR=/var/lib/tailscale --env TS_AUTHKEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --env TS_EXTRA_ARGS=--login-server=<nowiki>https://headscale.domain.uk</nowiki> --advertise-exit-node --env TS_HOSTNAME=mynodehostname tailscale/tailscale
 +
 
 +
Test ...
 +
 
 +
docker exec tailscale tailscale --socket /tmp/tailscaled.sock status
 +
 
 +
Ping a node ...
 +
 
 +
docker exec tailscale tailscale --socket /tmp/tailscaled.sock ping nameofnode
 +
 
 +
Job, done.
  
https://hub.docker.com/r/tailscale/tailscale
+
Here is the '''Docker Compose''' for all that ...
 +
 
 +
services:
 +
  tailscale:
 +
    container_name: tailscale
 +
      volumes:
 +
        - /var/lib:/var/lib
 +
        - /dev/net/tun:/dev/net/tun
 +
      network_mode: host
 +
      cap_add:
 +
        - NET_ADMIN
 +
        - NET_RAW
 +
      environment:
 +
        - TS_STATE_DIR=/var/lib/tailscale
 +
        - TS_USERSPACE=false
 +
        - TS_AUTHKEY=f85ff211b94078a1xxxxxxxxxxxxxxx079bae00769e51
 +
        - TS_EXTRA_ARGS=--login-server=<nowiki>https://headscale.mydomain.uk</nowiki> --advertise-exit-node
 +
        - TS_HOSTNAME=mynodehostname
 +
      image: tailscale/tailscale
 +
      restart: unless-stopped
 +
 
 +
'''Cloud Init'''
 +
 
 +
https://www.youtube.com/watch?v=e-X5FJwrkaA
 +
 
 +
=== Users ===
 +
 
 +
Generate a User on the Headscale server first, then register a Node linked to that User.
 +
 
 +
docker exec headscale headscale users create <USER_NAME>
 +
 
 +
=== Nodes ===
  
===== Node Registration =====
+
==== Registration ====
  
 
'''Method 1: Register a machine using normal login'''
 
'''Method 1: Register a machine using normal login'''
  
On a client machine, run the tailscale login command, which will output a machine key ...
+
On a client machine, run the tailscale login command, which will output a machine key (mkey) ...
  
 
  sudo tailscale up --login-server <YOUR_HEADSCALE_URL>
 
  sudo tailscale up --login-server <YOUR_HEADSCALE_URL>
  
On the server, run the headscale nodes command to register that client machine node using that key to a User ...
+
On the server, run the headscale nodes command to register that client machine node using that mkey to a User ...
  
  docker exec headscale headscale nodes register --key <YOUR_MACHINE_KEY> --user <USER_NAME>
+
  docker exec headscale headscale nodes register --key <mkey:YOUR_MACHINE_KEY> --user <USER_NAME>
  
 
'''Method 2: Register a machine using a pre authenticated key'''
 
'''Method 2: Register a machine using a pre authenticated key'''
Line 179: Line 261:
  
 
  sudo tailscale up --login-server <YOUR_HEADSCALE_URL> --authkey <YOUR_AUTH_KEY>
 
  sudo tailscale up --login-server <YOUR_HEADSCALE_URL> --authkey <YOUR_AUTH_KEY>
 +
 +
==== Testing ====
 +
 +
On the server, run the command to list the connected nodes ...
 +
 +
docker exec headscale headscale nodes list
 +
 +
ID | Hostname      | Name          | MachineKey | NodeKey | User  | IP addresses                  | Ephemeral | Last seen          | Expiration          | Connected | Expired
 +
1  | paully-laptop | paully-laptop | [v6BuV]    | [E5A+n] | paully | 100.64.0.1, fd7a:115c:a1e0::1 | false    | 2024-05-31 12:56:23 | 0001-01-01 00:00:00 | online    | no
 +
 +
== Exit Node ==
 +
 +
Want to hide your real IP address or "be in a different country"?
 +
 +
'''Server'''
 +
 +
Spin up your virtual private server in France and when you join that node to your tailnet, just advertise it as an 'exit node' ...
 +
 +
sudo tailscale up --login-server=<nowiki>https://headscale.mydomain.uk</nowiki> --authkey=a8590d89ca494b27cxxxxxxxxxxx5e3e923cc2ad974ee1be '''--advertise-exit-node''' --hostname=exit-node-fr-1 --accept-dns=false
 +
 +
Then toggle the option in your client to use the exit node in France 'exit-node-fr-1' and check your IP address at https://ipinfo.io
 +
 +
'''Client'''
 +
 +
List exit nodes on your tailnet ...
 +
 +
sudo tailscale exit-node list
 +
 +
IP              HOSTNAME                                        COUNTRY    CITY      STATUS     
 +
100.64.0.2      nodename.username.tailscale.tailnet.name        -          -        -         
 +
 +
Then set your traffic to go through that exit node ...
 +
 +
sudo tailscale set --exit-node=100.64.0.2
 +
 +
https://tailscale.com/kb/1103/exit-nodes
 +
 +
== Subnet Routers ==
 +
 +
https://tailscale.com/kb/1019/subnets
 +
 +
== Pi-Hole with Tailscale ==
 +
 +
https://shotor.com/blog/run-your-own-mesh-vpn-and-dns-with-tailscale-and-pihole/
 +
 +
== HowTos ==
 +
 +
What's my tailnet name?
 +
 +
tailscale status --json | jq -j '.MagicDNSSuffix'
 +
 +
How do I list my tailnets?
 +
 +
sudo tailscale switch --list
 +
 +
How do I switch tailnets?
 +
 +
sudo tailscale switch --list
 +
sudo tailscale switch <account> [flags]
 +
 +
== Links ==
 +
 +
[https://tailscale.com/kb/1080/cli?tab=bash Tailscale CLI]
 +
 +
[https://github.com/cterence/tailout Tailout] - a command-line tool for quickly creating a cloud-based exit node in your tailnet.
  
 
== Authentication ==
 
== Authentication ==
Line 188: Line 335:
 
[https://tailscale.com/use-cases/remote-access Remote Access using Tailscale]
 
[https://tailscale.com/use-cases/remote-access Remote Access using Tailscale]
  
RustDesk > settings > Network > Direct IP Access + IP Address Whitelisting
+
* RustDesk > Settings > Security > Direct IP Access + IP Whitelisting (e.g. tailscale IP range = 100.64.0.x)
 +
* RustDesk > Settings > Security > Password > Use Permanent Password

Latest revision as of 14:23, 9 September 2024

Introduction

Tailscale is a VPN service that uses WireGuard to create a fast, secure, and simple peer-to-peer network. Tailscale is a zero config VPN that works on any platform, service, or runtime. It encrypts all connections using WireGuard and integrates with 100+ tools for easy deployment and management.

Tailscale is a modern VPN built on top of Wireguard. It works like an overlay network between the computers of your networks - using NAT traversal.

Everything in Tailscale is Open Source, except the GUI clients for proprietary OS (Windows and macOS/iOS), and the control server.

The control server works as an exchange point of Wireguard public keys for the nodes in the Tailscale network. It assigns the IP addresses of the clients, creates the boundaries between each user, enables sharing machines between users, and exposes the advertised routes of your nodes.

A Tailscale network (tailnet) is private network which Tailscale assigns to a user in terms of private users or an organisation.

You can run Tailscale as an SSH Server and as an Exit Node - which means you can remove any SSH ports and have the Tailscale handle all the authentication and use itself as a Gateway for any node on your Tailscale network. Amazing.

Self Hosting

You can self host a Tailscale server with Headscale + Headscale Admin.

Headscale is an open source, self-hosted implementation of the Tailscale control server. Headscale's goal is to provide self-hosters and hobbyists with an open-source server they can use for their projects and labs. It implements a narrow scope, a single Tailnet, suitable for a personal use, or a small open-source organisation.

Headscale Admin is a web frontend for the headscale Tailscale-compatible coordination server.

YouTube - Jim's Garage - Self Host Tailscale with Headscale

Configure and run Headscale

Docker

You can self host a Tailscale server with Headscale + Headscale Admin + Traefik docker containers.

Follow the instructions on the respective web sites and the YouTube (outdated though!) video to get started, including grabbing copies of the docker compose and headscale config/config.yaml files, then edit the first 3 options as follows ...

server_url: https://headscale.mydomain.com
listen_addr: 0.0.0.0:8080
metrics_listen_addr: 0.0.0.0:9090

Running headscale in a container

This is the directory layout for a Docker Compose method ...

/root/docker/stacks/headscale
|-- config
|   `-- config.yaml
|-- data
|   |-- db.sqlite
|   `-- noise_private.key
|-- docker-compose.yaml
`-- run
    `-- headscale.sock

3 directories, 5 files

... and this is the docker compose YAML file which has both Headscale and Headscale Admin containers ...

services:

  headscale:
    container_name: headscale
    volumes:
        - ./config:/etc/headscale/
        - ./data:/var/lib/headscale/
        - ./run:/var/run/headscale/
    ports:
        - 8080:8080
        - 9090:9090
    image: headscale/headscale:0.23.0-alpha12
    environment:
      - TZ=Europe/London
    command: serve
    restart: unless-stopped
    networks:
      traefik:
        ipv4_address: 172.19.0.28
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik"
      - "traefik.http.routers.headscale.rule=Host(`headscale.mydomain.com`) && PathPrefix(`/`)"
      - "traefik.http.routers.headscale.entrypoints=websecure"
      - "traefik.http.routers.headscale.service=headscale"
      - "traefik.http.services.headscale.loadbalancer.server.port=8080"
      - "traefik.http.services.headscale.loadbalancer.server.scheme=http"

  headscale-admin:
    image: goodieshq/headscale-admin:latest
    container_name: headscale-admin
    restart: unless-stopped
    environment:
      - TZ=Europe/London
    volumes:
        - ./config:/etc/headscale/
        - ./data:/var/lib/headscale/
        - ./run:/var/run/headscale/
    ports:
      - 9999:80
    networks:
      traefik:
        ipv4_address: 172.19.0.29
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik"
      - "traefik.http.routers.headscale-admin.rule=Host(`headscale.mydomain.com`) && PathPrefix(`/admin`)"
      - "traefik.http.routers.headscale-admin.entrypoints=websecure"
      - "traefik.http.routers.headscale-admin.service=headscale-admin"
      - "traefik.http.routers.headscale-admin.middlewares=auth"
      - "traefik.http.services.headscale-admin.loadbalancer.server.port=80"
      - "traefik.http.services.headscale-admin.loadbalancer.server.scheme=http"
      - "traefik.http.middlewares.auth.basicauth.users=funkyusername:xxxxxxxxxxxxxxxxhashedxxxxpasswordxxxxxxxxxxxxxxx"

networks:
  traefik:
    external: true

Start up the containers, and you should see these lines in the docker logs ...

headscale        | 2024-05-31T10:53:13+01:00 INF Opening database database=sqlite3 path=/var/lib/headscale/db.sqlite
headscale        | 2024-05-31T10:53:13+01:00 INF Setting up a DERPMap update worker frequency=86400000
headscale        | 2024-05-31T10:53:13+01:00 INF listening and serving HTTP on: 0.0.0.0:8080
headscale-admin  | {"level":"info","ts":1717149193.3994539,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
headscale-admin  | {"level":"info","ts":1717149193.4059176,"msg":"serving initial configuration"}

Test the headscale server with curl and the docker image ...

curl 0.0.0.0:9090/metrics
docker exec headscale headscale --help
docker exec headscale headscale version
docker exec headscale headscale nodes list
docker exec headscale headscale apikeys list

Navigate to the Headscale Admin web address you provided in the config.yml file with /admin at the end - https://headscale.mydomain.com/admin) and then you will see an error about Authentication and missing API key.

Generate your server's API key. You only get one chance to see this ...

docker exec headscale headscale apikeys create

... copy it, then go the Headscale Admin Settings page and paste it there with your 'server_url' from the config file.

Then press the SAVE button.

Yay - you have successfuly set up your own self-hosted Tailscale server! :-)

Now you can add your first client device.

Client Devices

Windows

https://tailscale.com/download/windows

Prevent Auto-Connect on Restart/Login

Linux

Software Installation

Native

Install the software ...

curl -fsSL https://tailscale.com/install.sh | sh

Go to your Admin server and grab your pre-auth key.

Join the tailnet ...

tailscale up --login-server=https://headscale.mydomain.uk --authkey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --accept-dns=false

WEB

There is a built-in web interface with tailscale, which you can access by running this command ...

sudo tailscale set --webclient

... and then pointing your web browser at the address it tells you to - e.g. http://100.64.0.1:5252

To stop the web interface, run this command ...

sudo tailscale set --webclient=false

GUI

https://github.com/DeedleFake/trayscale

Docker

https://hub.docker.com/r/tailscale/tailscale

https://tailscale.com/kb/1282/docker

Create your pre-auth key on your Headscale server using Headscale Admin.

Pull the image ...

docker pull tailscale/tailscale:latest

Start the docker passing the login server and pre-auth key environment variables ...

docker run -d --name=tailscale -v /var/lib:/var/lib -v /dev/net/tun:/dev/net/tun --network=host --cap-add=NET_ADMIN --cap-add=NET_RAW --env TS_STATE_DIR=/var/lib/tailscale --env TS_AUTHKEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --env TS_EXTRA_ARGS=--login-server=https://headscale.domain.uk --advertise-exit-node --env TS_HOSTNAME=mynodehostname tailscale/tailscale

Test ...

docker exec tailscale tailscale --socket /tmp/tailscaled.sock status

Ping a node ...

docker exec tailscale tailscale --socket /tmp/tailscaled.sock ping nameofnode

Job, done.

Here is the Docker Compose for all that ...

services:
  tailscale:
    container_name: tailscale
      volumes:
        - /var/lib:/var/lib
        - /dev/net/tun:/dev/net/tun
      network_mode: host
      cap_add:
        - NET_ADMIN
        - NET_RAW
      environment:
        - TS_STATE_DIR=/var/lib/tailscale
        - TS_USERSPACE=false
        - TS_AUTHKEY=f85ff211b94078a1xxxxxxxxxxxxxxx079bae00769e51
        - TS_EXTRA_ARGS=--login-server=https://headscale.mydomain.uk --advertise-exit-node
        - TS_HOSTNAME=mynodehostname
      image: tailscale/tailscale
      restart: unless-stopped

Cloud Init

https://www.youtube.com/watch?v=e-X5FJwrkaA

Users

Generate a User on the Headscale server first, then register a Node linked to that User.

docker exec headscale headscale users create <USER_NAME>

Nodes

Registration

Method 1: Register a machine using normal login

On a client machine, run the tailscale login command, which will output a machine key (mkey) ...

sudo tailscale up --login-server <YOUR_HEADSCALE_URL>

On the server, run the headscale nodes command to register that client machine node using that mkey to a User ...

docker exec headscale headscale nodes register --key <mkey:YOUR_MACHINE_KEY> --user <USER_NAME>

Method 2: Register a machine using a pre authenticated key

Generate a key linked to a User ...

docker exec headscale headscale preauthkeys create --reusable --expiration 24h --user <USER_NAME>

This will return a pre-authenticated key that can be used to connect a node to headscale during the tailscale login command on the client ...

sudo tailscale up --login-server <YOUR_HEADSCALE_URL> --authkey <YOUR_AUTH_KEY>

Testing

On the server, run the command to list the connected nodes ...

docker exec headscale headscale nodes list

ID | Hostname      | Name          | MachineKey | NodeKey | User   | IP addresses                  | Ephemeral | Last seen           | Expiration          | Connected | Expired
1  | paully-laptop | paully-laptop | [v6BuV]    | [E5A+n] | paully | 100.64.0.1, fd7a:115c:a1e0::1 | false     | 2024-05-31 12:56:23 | 0001-01-01 00:00:00 | online    | no

Exit Node

Want to hide your real IP address or "be in a different country"?

Server

Spin up your virtual private server in France and when you join that node to your tailnet, just advertise it as an 'exit node' ...

sudo tailscale up --login-server=https://headscale.mydomain.uk --authkey=a8590d89ca494b27cxxxxxxxxxxx5e3e923cc2ad974ee1be --advertise-exit-node --hostname=exit-node-fr-1 --accept-dns=false

Then toggle the option in your client to use the exit node in France 'exit-node-fr-1' and check your IP address at https://ipinfo.io

Client

List exit nodes on your tailnet ...

sudo tailscale exit-node list

IP              HOSTNAME                                        COUNTRY     CITY      STATUS      
100.64.0.2      nodename.username.tailscale.tailnet.name        -           -         -           

Then set your traffic to go through that exit node ...

sudo tailscale set --exit-node=100.64.0.2

https://tailscale.com/kb/1103/exit-nodes

Subnet Routers

https://tailscale.com/kb/1019/subnets

Pi-Hole with Tailscale

https://shotor.com/blog/run-your-own-mesh-vpn-and-dns-with-tailscale-and-pihole/

HowTos

What's my tailnet name?

tailscale status --json | jq -j '.MagicDNSSuffix'

How do I list my tailnets?

sudo tailscale switch --list

How do I switch tailnets?

sudo tailscale switch --list
sudo tailscale switch <account> [flags]

Links

Tailscale CLI

Tailout - a command-line tool for quickly creating a cloud-based exit node in your tailnet.

Authentication

https://github.com/gmiles32/headscale-authelia

Remote Access

Remote Access using Tailscale

  • RustDesk > Settings > Security > Direct IP Access + IP Whitelisting (e.g. tailscale IP range = 100.64.0.x)
  • RustDesk > Settings > Security > Password > Use Permanent Password