みかんせい
本家様 https://headscale.net/stable/
github https://github.com/juanfont/headscale
外部からのアクセスで WireGuard を使うのですが、いつ、だれが接続したのかがつかめずらい。
接続認証はそもそも秘密鍵なので、それを持っているのが認証になるのかなと思うのだが、「いつ」「だれ」かをログに取りたい。
っで調べていて見つけたのが「tailscale」. こちらは有償で、個人ユースには無償版もある。っでオープンソースなものを調べて見つけたのが「Headscale」
でも「Headscale」が提供するのは「tailscale」のコントロールサーバー部分. windowsやmacOSに入れるクライアントトールは「公式Tailscaleアプリ」を使うみたい
OSはrockylinux9を使ってます
プログラムの置き場所は「/usr/local/bin」です
[root@headscale ~]# cat /etc/redhat-release
Rocky Linux release 9.7 (Blue Onyx)
[root@headscale ~]#
[root@headscale ~]# dnf install curl wget git nginx
[root@headscale ~]# cd /usr/local/bin/
[root@headscale bin]# wget https://github.com/juanfont/headscale/releases/download/v0.28.0/headscale_0.28.0_linux_amd64
[root@headscale bin]# mv headscale_0.28.0_linux_amd64 headscale
[root@headscale bin]# chmod +x headscale
[root@headscale bin]# ls -lh
total 51M
-rwxr-xr-x. 1 root root 51M Feb 5 05:36 headscale
[root@headscale bin]#
[root@headscale bin]# headscale version
headscale version v0.28.0
commit: 97fa117c48a58bee3941e5e8b4393873501afe14
build time: 2026-02-04T20:26:22Z
built with: go1.25.5 linux/amd64
[root@headscale bin]#プログラムはこれでOkで次にこの headscale を稼働するユーザを作ります
[root@headscale ~]# useradd \
--create-home \
--home-dir /var/lib/headscale/ \
--system \
--user-group \
--shell /usr/sbin/nologin \
headscale
[root@headscale ~]# id headscale
uid=995(headscale) gid=994(headscale) groups=994(headscale)
[root@headscale ~]#ユーザは「system」アカウントにしてまして、1000以下のUID/GIDとなってます
設定ファイルを取得します
[root@headscale ~]# mkdir -p /etc/headscale
[root@headscale ~]# cd /etc/headscale/
[root@headscale headscale]# wget -O config.yaml https://raw.githubusercontent.com/juanfont/headscale/v0.28.0-beta.2/config-example.yaml一応このファイルの中身は
[root@headscale ~]# sed -e '/^[[:space:]]*#/d' -e '/^[[:space:]]*$/d' /etc/headscale/config.yaml
---
server_url: http://127.0.0.1:8080
listen_addr: 127.0.0.1:8080
metrics_listen_addr: 127.0.0.1:9090
grpc_listen_addr: 127.0.0.1:50443
grpc_allow_insecure: false
noise:
private_key_path: /var/lib/headscale/noise_private.key
prefixes:
v4: 100.64.0.0/10
v6: fd7a:115c:a1e0::/48
allocation: sequential
derp:
server:
enabled: false
region_id: 999
region_code: "headscale"
region_name: "Headscale Embedded DERP"
verify_clients: true
stun_listen_addr: "0.0.0.0:3478"
private_key_path: /var/lib/headscale/derp_server_private.key
automatically_add_embedded_derp_region: true
ipv4: 198.51.100.1
ipv6: 2001:db8::1
urls:
- https://controlplane.tailscale.com/derpmap/default
paths: []
auto_update_enabled: true
update_frequency: 3h
disable_check_updates: false
ephemeral_node_inactivity_timeout: 30m
database:
type: sqlite
debug: false
gorm:
prepare_stmt: true
parameterized_queries: true
skip_err_record_not_found: true
slow_threshold: 1000
sqlite:
path: /var/lib/headscale/db.sqlite
write_ahead_log: true
wal_autocheckpoint: 1000
acme_url: https://acme-v02.api.letsencrypt.org/directory
acme_email: ""
tls_letsencrypt_hostname: ""
tls_letsencrypt_cache_dir: /var/lib/headscale/cache
tls_letsencrypt_challenge_type: HTTP-01
tls_letsencrypt_listen: ":http"
tls_cert_path: ""
tls_key_path: ""
log:
level: info
format: text
policy:
mode: file
path: ""
dns:
magic_dns: true
base_domain: example.com
override_local_dns: true
nameservers:
global:
- 1.1.1.1
- 1.0.0.1
- 2606:4700:4700::1111
- 2606:4700:4700::1001
split: {}
search_domains: []
extra_records: []
unix_socket: /run/headscale/headscale.sock <-- 「/var/run/headscale/headscale.sock」から「/run/headscale/headscale.sock 」へ
unix_socket_permission: "0770"
logtail:
enabled: false
randomize_client_port: false
taildrop:
enabled: true
[root@headscale ~]#「/run/headscale/」がユーザheadscaleになるように
[root@headscale ~]# echo "D /run/headscale 0755 headscale headscale -" > /usr/lib/tmpfiles.d/headscale.conf
[root@headscale ~]# /usr/bin/systemd-tmpfiles --create /usr/lib/tmpfiles.d/headscale.conf設定ファイルの次は service ファイル
[root@headscale ~]# wget -O /etc/systemd/system/headscale.service https://raw.githubusercontent.com/juanfont/headscale/refs/heads/main/packaging/systemd/headscale.service
[root@headscale ~]# vi /etc/systemd/system/headscale.service
[Unit]
After=network.target
Description=headscale coordination server for Tailscale
X-Restart-Triggers=/etc/headscale/config.yaml
[Service]
Type=simple
User=headscale
Group=headscale
ExecStart=/usr/local/bin/headscale serve <-- headscale の保存場所に合わせて修正
ExecReload=/usr/bin/kill -HUP $MAINPID
Restart=always
RestartSec=5
WorkingDirectory=/var/lib/headscale <-- ユーザ headscale のホームディレクトリとかで
ReadWritePaths=/var/lib/headscale <-- ユーザ headscale のホームディレクトリとかで
AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_CHOWN
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_CHOWN
LockPersonality=true
NoNewPrivileges=true
PrivateDevices=true
PrivateMounts=true
PrivateTmp=true
ProcSubset=pid
ProtectClock=true
ProtectControlGroups=true
ProtectHome=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectProc=invisible
ProtectSystem=strict
RemoveIPC=true
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
RuntimeDirectory=headscale
RuntimeDirectoryMode=0750
StateDirectory=headscale
StateDirectoryMode=0750
SystemCallArchitectures=native
SystemCallFilter=@chown
SystemCallFilter=@system-service
SystemCallFilter=~@privileged
UMask=0077
[Install]
WantedBy=multi-user.target
[root@headscale ~]#っで headscaleを試しに動かす
[root@headscale ~]# systemctl daemon-reload
[root@headscale ~]# systemctl enable headscale --now
[root@headscale ~]# journalctl -f -u headscale
Mar 22 02:16:08 headscale systemd[1]: Started headscale coordination server for Tailscale.
Mar 22 02:16:08 headscale headscale[12631]: 2026-03-22T02:16:08+09:00 INF No private key file at path, creating... path=/var/lib/headscale/noise_private.key
Mar 22 02:16:08 headscale headscale[12631]: 2026-03-22T02:16:08+09:00 INF Opening database database=sqlite3 path=/var/lib/headscale/db.sqlite
Mar 22 02:16:08 headscale headscale[12631]: 2026-03-22T02:16:08+09:00 INF Starting Headscale commit=97fa117c48a58bee3941e5e8b4393873501afe14 version=v0.28.0
Mar 22 02:16:08 headscale headscale[12631]: 2026-03-22T02:16:08+09:00 INF Clients with a lower minimum version will be rejected minimum_version=v1.74
Mar 22 02:16:09 headscale headscale[12631]: 2026-03-22T02:16:09+09:00 INF listening and serving HTTP on: 127.0.0.1:8080
Mar 22 02:16:09 headscale headscale[12631]: 2026-03-22T02:16:09+09:00 INF listening and serving debug and metrics on: 127.0.0.1:9090
:
:[root@headscale ~]# dnf install httpd certbot python3-certbot-apache
[root@headscale ~]# echo "ok" >> /var/www/html/index.html
[root@headscale ~]# cat<<_EOF_> /etc/httpd/conf.d/vpn.conf
<VirtualHost *:80>
ServerName vpn.chaperone.jp
DocumentRoot "/var/www/html"
</VirtualHost>
<VirtualHost *:443>
ServerName vpn.chaperone.jp
DocumentRoot "/var/www/html"
</VirtualHost>
_EOF_
[root@headscale ~]# systemctl enable httpd --now
[root@headscale ~]# firewall-cmd --add-service=http --add-service=https --permanent
[root@headscale ~]# firewall-cmd --reload
(vpn.chaperone.jpに対して httpアクセスとhttpsアクセスを試みる)
[root@headscale ~]# certbot --apache -d vpn.chaperone.jp
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel): XXXXXXXX@YYYYYYYYYYY.jp <-- 受け取れるメールアドレスを記載
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.6-August-18-2025.pdf. You must agree
in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y <-- 加入者契約書に同意ならY
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N <-- 米国のデジタル権利擁護団体 電子フロンティア財団(EFF)が発行するニュースを受け取るならY
Account registered.
Requesting a certificate for vpn.chaperone.jp
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/vpn.chaperone.jp/fullchain.pem
Key is saved at: /etc/letsencrypt/live/vpn.chaperone.jp/privkey.pem
This certificate expires on 2026-06-23.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Deploying certificate
Successfully deployed certificate for vpn.chaperone.jp to /etc/httpd/conf.d/vpn.conf <-- 「/etc/httpd/conf.d/vpn.conf」を書き換えてます
Congratulations! You have successfully enabled HTTPS on https://vpn.chaperone.jp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[root@headscale conf.d]#[root@headscale ~]# vi /etc/headscale/config.yaml
server_url: http://127.0.0.1:8080
↓
server_url: https://vpn.chaperone.jp
[root@headscale ~]# vi /etc/httpd/conf.d/vpn.conf
<VirtualHost *:80>
ServerName vpn.chaperone.jp
DocumentRoot "/var/www/html"
RewriteEngine on <-+
RewriteCond %{SERVER_NAME} =vpn.chaperone.jp | letsencryptのcertbot で追加された行
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] +----
</VirtualHost>
<VirtualHost *:443>
ServerName vpn.chaperone.jp
DocumentRoot "/var/www/html"
SSLCertificateFile /etc/letsencrypt/live/vpn.chaperone.jp/fullchain.pem <-+
SSLCertificateKeyFile /etc/letsencrypt/live/vpn.chaperone.jp/privkey.pem <-+ letsencryptのcertbot で追加された行
Include /etc/letsencrypt/options-ssl-apache.conf <-+
ProxyPass / http://127.0.0.1:8080/ <-- 追加
ProxyPassReverse / http://127.0.0.1:8080/ <-- 追加
</VirtualHost>
[root@headscale ~]#[root@headscale ~]# systemctl restart headscale
[root@headscale ~]# systemctl reload httpd
[root@headscale ~]# setsebool -P httpd_can_network_connect 1これで「https://vpn.chaperone.jp」が空白のページならok。
クライアントアプリは tailscale のアプリを使います。結構タダ乗りしてない?
https://tailscale.com/download
からクライアントプラットホームにあうパッケージをダウンロードして入れます。