Headscale Setup¶
Official Site: https://headscale.net/
tl;dr: a self-host version of tailscale, providing more controls but less features
最近折腾组网,看了下 Tailscale 看起来不错,不过不确定 Tailscale 会不会被 GFW gank,于是研究起了 Headscale
Control Plane¶
Installation¶
$ wget *.deb
(in GitHub Release)# apt install ./*.deb
# vim /etc/headscale/config.yaml
# systemctl enable --now headscale
# systemctl status headscale
headscale-ui¶
Pure static site, so no access control is required (all actions are performed at the frontend, including api key storage)
Note
we'll deploy the static site at /web/
to avoid CORS messes, you could even deploy it to another site, say control.headscale.****.****
for example, but additional settings in rev proxy is needed, and I would just recommend you to deploy it at /web/
and use the same domain for simplicity
$ wget *.zip
(in GitHub Release)$ unzip *.zip -d /var/www/html-headscale-ui
$ vim /etc/caddy/Caddyfile
Caddy¶
Caddy would magically handle everything even with HTTPS, so yay!
/etc/caddy/Caddyfile | |
---|---|
Now go to headscale.****.****/web/
, but first create a API key with:
Paste it in the browser, and you're good to go! (Note how the API key is stored locally, try a Private Window if you're paranoid)
Client¶
Installation¶
Just install it as a normal tailscale setup:
Linux | |
---|---|
for macOS users, try Homebrew instead of App Store version, which provides you with CLI interface.
Warning
DO NOT install the non-cask version on homebrew alongside an App Store version, apparently they don't commmunicate, at all.
You could install a CLI only version with a tailscale
+ tailscaled
, but why?
Login¶
To connect to the control plane, use:
Create a preauth key on the aforementioned headscale-ui page
Features¶
Docker subnet¶
One great way to use the new intranet you just setup, is to assign a subnet to the docker network for each machine, so each container would have its own IP address, and would perform just as a regular system, without the need to perform port fowarding, rev proxy on host ... etc.
Here's a step-by-step to show you how to do it:
Note
With defaultd config, headscale will assign 10.60.0.1/24
for the client network, so I'm planning the following address:
10.60.0.1
would get a10.8.1.0/24
subnet10.60.0.2
would get a10.8.2.0/24
subnet- ...
Adjust the following steps according to your own network settings
Modifying default docker0
¶
Warning
I should really give you some heads up on this:
-
Assigning every docker container to the default bridge network would allow them to communicate with each other freely, leading to potential security risks.
-
With default bridge network, you CAN'T manually assign IP to container, you'll get the following message:
Note
You can modify docker compose to join the default network like this:
docker-compose.yml | |
---|---|
NOTE: This breaks discovery, so you'll need to use --link
or --network
to connect containers again.
Modify /etc/docker/daemon.json
and add:
Warning
See https://github.com/moby/moby/issues/22638#issuecomment-263932574
Use IP/netmask address, not subnet/netmask address. tl;dr use .1
not .0
You'll need to restart Docker after this, supposing with systemd
installation:
Warning
Docker now have a special live-restore
option, which would prevent containers from stopping when reloading daemon.
In this case this is NOT desired, you must stop all containers for it to assign new IP addresses.
Create a new subnet¶
docker-subnet.sh | |
---|---|
Attaching docker compose to this network is easy:
With docker run
, use:
Enable IP forwarding¶
https://tailscale.com/kb/1019/subnets#connect-to-tailscale-as-a-subnet-router
Broadcast Route to Headscale¶
Approve the route in the control plane¶
Again this could be done with the web page, or with the CLI:
ACL rules¶
ACL rules enables more detailed control over the network, allowing you to control who can access what, and who can't, with autoApprovers
you could automatically approve certain routes.
To use ACLs in headscale, you must edit your config.yaml file. In there you will find a
policy.path
parameter. This will need to point to your ACL file. More info on how these policies are written can be found here
My config as example: