SSD Nodes Learn RAM 8GB — $66/tahun
Panduan Matt ConnorOleh Matt Connor · Dikemas kini 2026-08-01

Headscale: Hos Sendiri Pelayan Kawalan Tailscale

Jalankan pelayan kawalan Tailscale sendiri pada VPS. Pasang headscale daripada fail .deb rasmi, tetapkan server_url sebelum memulakannya dan sambungkan nod pertama.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, July 30, 2026.

Apakah headscale

Headscale ialah pelaksanaan kawalan Tailscale yang dihoskan sendiri. Oleh itu, mesin yang menyelaraskan rangkaian peribadi anda ialah VPS milik anda. Ia ialah projek komuniti dan tidak dikendalikan oleh Tailscale Inc. Setiap mesin masih menjalankan klien rasmi tailscale, yang diarahkan ke pelayan anda menggunakan satu flag, --login-server.

Pelayan kawalan ialah komponen yang mengetahui pihak yang tergolong dalam rangkaian. Pelayan ini memberikan setiap nod alamat daripada 100.64.0.0/10, mengedarkan kunci awam dan memberitahu nod lokasi nod lain. Terowong kekal menggunakan WireGuard dan dibina dari nod ke nod. Traffic antara dua mesin anda tidak melalui mesin headscale, kecuali laluan terus tidak dapat dibina lalu nod beralih kepada relay.

Headscale menyediakan satu tailnet (satu rangkaian Tailscale) bagi setiap instance. Projek ini menyatakan bahawa model tersebut sesuai untuk kegunaan peribadi atau organisasi kecil. Dengan tiga atau empat mesin, VPN WireGuard biasa pada VPS milik anda memerlukan kurang perisian untuk dikendalikan dan kurang kemungkinan mengalami kerosakan. Headscale berbaloi apabila anda tidak lagi mahu menulis blok [Peer] secara manual untuk setiap komputer riba baharu. Untuk perbandingan yang lebih menyeluruh antara kedua-dua model, lihat perbezaan antara WireGuard dan Tailscale.

Keperluan sebelum pemasangan

  • VPS yang menjalankan Ubuntu 24.04 dengan alamat IPv4 awam dan akses sudo. Jika pelayan masih baharu, ikuti sepuluh minit pertama pada VPS baharu terlebih dahulu.
  • Rekod DNS A yang menunjuk kepada alamat tersebut. Panduan ini menggunakan headscale.example.com.
  • Domain atau subdomain kedua untuk MagicDNS. Panduan ini menggunakan tailnet.example.net. Domain ini mestilah berbeza daripada domain dalam server_url.
  • Satu mesin klien untuk disertakan, yang menjalankan Linux, macOS, Windows, Android atau iOS.

Pasang headscale daripada .deb rasmi

Projek ini menerbitkan pakej .deb pada halaman keluaran GitHub. Setakat Julai 2026, keluaran semasa ialah 0.29.3. Semak seni bina anda terlebih dahulu kerana nama fail menyertakannya.

sudo apt update
sudo apt install -y wget
dpkg --print-architecture

Perintah itu mencetak amd64 pada VPS x86 biasa dan arm64 pada pelan berasaskan Ampere atau Graviton. Masukkan jawapan itu ke dalam pemboleh ubah di bawah.

HEADSCALE_VERSION="0.29.3"
HEADSCALE_ARCH="amd64"
wget --output-document=headscale.deb \\
  "https://github.com/juanfont/headscale/releases/download/v${HEADSCALE_VERSION}/headscale_${HEADSCALE_VERSION}_linux_${HEADSCALE_ARCH}.deb"
sudo apt install -y ./headscale.deb
headscale version

./ di hadapan nama fail diperlukan. Tanpanya, apt mencari pakej bernama headscale.deb dalam repositori anda lalu gagal.

Pakej ini mencipta pengguna sistem headscale, menulis fail konfigurasi lalai /etc/headscale/config.yaml, dan memasang unit systemd. Pakej ini tidak memulakan perkhidmatan, dan itulah urutan yang betul. Konfigurasi yang disertakan mengarahkan server_url ke http://127.0.0.1:8080, yang bukan alamat yang boleh dicapai oleh mana-mana klien anda. Oleh itu, perkhidmatan yang dimulakan sekarang akan dikonfigurasikan dengan salah walaupun berjaya dimulakan. Menjalankan sudo systemctl is-active headscale pada ketika ini mencetak inactive. Itu dijangka dan bukan ralat.

Konfigurasikan server_url sebelum anda memulakan perkhidmatan

Edit /etc/headscale/config.yaml dengan sudo nano /etc/headscale/config.yaml, atau gunakan sed untuk menggunakan tiga perubahan yang sama. Simpan salinan asal kerana fail ini panjang dan mempunyai banyak komen. Fail ini ialah rujukan terbaik untuk tetapan yang selebihnya.

sudo cp /etc/headscale/config.yaml /etc/headscale/config.yaml.orig
sudo sed -i 's|^server_url:.*|server_url: https://headscale.example.com|' /etc/headscale/config.yaml
sudo sed -i 's|^listen_addr:.*|listen_addr: 127.0.0.1:8080|' /etc/headscale/config.yaml
sudo sed -i 's|^  base_domain:.*|  base_domain: tailnet.example.net|' /etc/headscale/config.yaml
sudo grep -E '^(server_url|listen_addr):|^  base_domain:' /etc/headscale/config.yaml

server_url ialah alamat yang ditulis oleh headscale ke dalam setiap pendaftaran klien. Selepas itu, klien akan membuat sambungan ke rentetan tepat tersebut untuk selama-lamanya. Oleh itu, alamat ini mestilah nama awam dengan https:// di hadapan, dan bukan 127.0.0.1.

listen_addr ialah alamat tempat proses membuat binding. Kekalkan alamat ini pada gelung balik. Proksi songsang pada pelayan yang sama menamatkan TLS (keselamatan lapisan pengangkutan) dan memajukan sambungan kepadanya. Oleh itu, tiada apa-apa dari luar pelayan perlu mencapai port 8080.

base_domain ialah sufiks MagicDNS, iaitu domain yang digunakan untuk memberikan nama kepada nod anda. Sufiks ini mestilah nama domain yang layak sepenuhnya tanpa noktah di hujung, dan mestilah berbeza daripada domain dalam server_url. Jika tidak, kedua-dua ruang nama akan bertindih.

Biarkan bahagian pangkalan data tanpa perubahan. Nilai lalai ialah SQLite pada /var/lib/headscale/db.sqlite, dalam direktori yang dicipta dan dimiliki oleh pakej. SQLite mencukupi untuk tailnet sebesar ini.

Mulakan headscale dan buktikan bahawa ia sedang berjalan

sudo systemctl enable --now headscale
sudo systemctl is-active headscale
curl -sS -o /dev/null -w '%{http_code}\\n' http://127.0.0.1:8080/health

is-active mencetak active dan curl mencetak 200. enable --now melaksanakan kedua-dua bahagian tugas: ia memulakan perkhidmatan dan menetapkannya supaya bermula selepas but semula.

Jika is-active mencetak failed, baca jurnal menggunakan sudo journalctl -u headscale -n 50 --no-pager. Kegagalan pada peringkat ini hampir selalu berpunca daripada fail konfigurasi, kerana headscale menghuraikan seluruh fail sebelum membuka soket. Oleh itu, lekukan yang salah atau kunci yang tidak dikenali menghentikan proses sebelum apa-apa mendengar pada soket. Betulkan fail itu, kemudian jalankan sudo systemctl restart headscale. Setiap perubahan konfigurasi selepas ini memerlukan mula semula yang sama. Klien akan bersambung semula secara automatik selepas itu. Jika unit systemd masih baharu bagi anda, menjalankan perkhidmatan dan pemasa sendiri dengan systemd menerangkan perintah yang digunakan di sini.

Semak fail keadaan semasa anda berada dalam shell:

stat -c '%U %n' /var/lib/headscale/db.sqlite /var/lib/headscale/noise_private.key

Kedua-dua baris bermula dengan headscale, iaitu pengguna tanpa keistimewaan yang dicipta oleh pakej tersebut. noise_private.key ialah identiti pelayan kepada kliennya. Kekalkan fail itu. Jika anda memadamkannya, headscale akan menjana identiti baharu dan setiap nod perlu didaftarkan semula.

Letakkan TLS di hadapan headscale

Klien mesti mengakses server_url melalui HTTPS. Caddy ialah kaedah paling ringkas kerana ia meminta dan memperbaharui sijil secara automatik.

sudo apt install -y caddy

Gantikan /etc/caddy/Caddyfile dengan blok daripada dokumentasi headscale:

headscale.example.com {
    reverse_proxy 127.0.0.1:8080 {
        header_up True-Client-IP {remote_host}
        header_up X-Real-IP {remote_host}
    }
}
sudo caddy validate --adapter caddyfile --config /etc/caddy/Caddyfile
sudo systemctl restart caddy
sudo systemctl is-active caddy

validate memaparkan adapted config to JSON apabila fail berjaya dihuraikan. Amaran bahawa fail belum diformatkan hanyalah isu kosmetik. Dari komputer riba anda, curl -sS -o /dev/null -w '%{http_code}\\n' https://headscale.example.com/health juga sepatutnya memaparkan 200. Semakan tunggal itu membuktikan bahawa DNS, firewall, sijil dan proksi berfungsi bersama.

Berikut ialah perincian proksi yang sering menyebabkan masalah. Sambungan kawalan Tailscale ialah peningkatan HTTP. Sambungan ini dimulakan dengan POST, bukan GET, dan nilai pengepala Upgrade ialah tailscale-control-protocol. Caddy meneruskannya tanpa konfigurasi tambahan. nginx tidak berbuat demikian. Oleh itu, bahagian hadapan nginx memerlukan peta peningkatan:

map $http_upgrade $connection_upgrade {
    default keep-alive;
    ''      close;
}

server {
    listen 443 ssl;
    server_name headscale.example.com;
    location / {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_buffering off;
        proxy_pass http://127.0.0.1:8080;
    }
}

Jika baris tersebut ditinggalkan, permintaan biasa masih berjaya. Oleh itu, /health mengembalikan 200 dan semuanya kelihatan baik. Namun, sambungan kawalan jangka panjang tidak pernah terbentuk. Nod anda akan mendaftar, kemudian kekal luar talian. Jika anda memilih nginx, Certbot pada Ubuntu 24.04 dengan nginx menerangkan bahagian sijil.

Port yang perlu dibuka dalam UFW

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

Port 443 membawa semua komunikasi klien. Port 80 hanya digunakan untuk cabaran HTTP ACME (persekitaran pengurusan sijil automatik) dan pengalihan ke HTTPS. Caddy memerlukannya untuk mendapatkan sijil.

Port 8080 kekal tertutup. listen_addr ialah 127.0.0.1:8080, jadi proksi menghubungi headscale melalui antara muka loopback dan tiada peraturan firewall diperlukan. Membuka port 8080 kepada Internet memberikan klien saluran kawalan teks jelas dan tidak memberikan sebarang manfaat. Ingat bahawa kebanyakan penyedia menjalankan firewall kedua dalam panel kawalan mereka, berasingan daripada UFW. Oleh itu, port boleh terbuka pada pelayan tetapi masih tertutup di rangkaian tepi. Asas firewall UFW pada VPS menerangkan sintaks peraturan dengan lebih terperinci.

Cipta pengguna dan kunci preauth

sudo headscale users create alice
sudo headscale users list

Perintah headscale ialah klien. Perintah ini berkomunikasi dengan daemon yang sedang berjalan melalui soket unix di /var/run/headscale/headscale.sock, yang mempunyai mod 0770 dan dimiliki oleh kumpulan headscale. Oleh itu, terdapat dua perkara. Perintah ini gagal apabila perkhidmatan dihentikan. Ini ialah sebab lain susunan dalam panduan ini penting. Perintah ini juga memerlukan sudo, kecuali anda menambahkan akaun sendiri kepada kumpulan headscale.

users list mencetak ID di sebelah setiap nama. Anda memerlukan nombor itu kerana perintah key menerima ID pengguna berangka, bukan nama.

sudo headscale preauthkeys create --user 1 --expiration 24h

Kunci ini dicetak sekali sahaja. Salin kunci itu sekarang. Kunci preauth hanya boleh digunakan sekali dan sah selama satu jam melainkan anda menetapkan sebaliknya. Oleh itu, --expiration 24h wajar ditetapkan semasa anda masih menjalankan ujian. Tambahkan --reusable untuk kunci yang mendaftarkan beberapa mesin, dan lindungi kunci itu seperti kata laluan kerana sesiapa yang memilikinya boleh menyertai rangkaian anda.

Sambungkan klien pertama anda dengan --login-server

Pada mesin yang ingin disertakan:

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --login-server https://headscale.example.com --auth-key 'hskey-auth-PASTE-YOUR-KEY-HERE'
tailscale status
tailscale ip -4

tailscale ip -4 mencetak alamat yang diberikan oleh headscale, seperti 100.64.0.1. Kembali ke pelayan, sudo headscale nodes list memaparkan nod bersama ID, pengguna dan status dalam taliannya.

Nilai --login-server mesti sepadan tepat dengan server_url, termasuk skema dan tanpa garis condong di hujung. Nilai tersebut dibandingkan sebagai rentetan. Ketidakpadanan menyebabkan klien mendaftar menggunakan satu alamat, kemudian diarahkan untuk berhubung dengan alamat lain.

Mesin yang sebelum ini dilog masuk ke perkhidmatan hos Tailscale akan mengekalkan log masuk tersebut. Jalankan sudo tailscale logout padanya terlebih dahulu, kemudian jalankan tailscale up dengan --login-server.

Jika anda tidak menyertakan --auth-key, klien akan mencetak URL. Buka URL tersebut. Halaman itu memaparkan pengecam untuk percubaan pendaftaran tersebut, yang anda luluskan pada pelayan:

sudo headscale auth register --user alice --auth-id PASTE-THE-ID-FROM-THE-PAGE

Borang itu lebih mudah untuk komputer riba anda sendiri. Kunci prapengesahan lebih sesuai untuk apa-apa yang dijalankan melalui skrip kerana tiada manusia perlu memantaunya.

DERP dan perkara yang menyampaikan trafik apabila laluan terus gagal

DERP (relay terenkripsi yang ditetapkan untuk paket) ialah laluan sandaran. Apabila dua nod tidak dapat membuka sambungan WireGuard secara terus, biasanya kerana kedua-duanya berada di belakang NAT (terjemahan alamat rangkaian) yang ketat, nod tersebut menghantar paket melalui relay. Relay tidak menyimpan sebarang kunci, jadi relay tidak dapat membaca trafik anda. Relay boleh melihat nod yang berkomunikasi dan jumlah data yang dipindahkan.

Fahami perkara yang dilakukan oleh konfigurasi lalai. Headscale dihantar dengan penudingan ke https://controlplane.tailscale.com/derpmap/default bersama auto_update_enabled: true dan update_frequency: 3h. Oleh itu, satah kawalan anda berada di bawah kawalan anda, manakala relay anda berada di bawah kawalan Tailscale. Bagi kebanyakan pengguna, ini ialah pertukaran yang munasabah. Jika tidak, jalankan relay anda sendiri.

Untuk menjalankan relay sendiri, tetapkan enabled: true di bawah derp.server dalam config.yaml, mulakan semula headscale, dan buka port STUN (utiliti traversal sesi untuk NAT) dengan sudo ufw allow 3478/udp. Fail konfigurasi menyatakan keperluan ini dengan jelas: server_url mesti menggunakan https kerana DERP memerlukan TLS. Mengosongkan senarai derp.urls akan mengeluarkan relay Tailscale daripada peta. Jika anda berbuat demikian tanpa relay terbenam yang berfungsi, mana-mana pasangan nod yang tidak dapat bersambung secara terus tidak akan dapat bersambung sama sekali.

Daripada klien, tailscale netcheck memaparkan kependaman ke setiap rantau relay yang diketahuinya, manakala tailscale status menandakan setiap rakan setara sebagai sama ada direct dengan alamat atau relay dengan kod rantau. Rakan setara yang kekal pada relay menunjukkan masalah NAT, bukan masalah headscale.

Mengapakah nod dipaparkan sebagai luar talian?

Proksi menggugurkan proses upgrade. Ini punca yang paling biasa. Tandanya ialah semua yang lain kelihatan normal: /health mengembalikan 200, headscale nodes list memaparkan nod, tetapi nod tidak pernah berada dalam talian. Sambungan kawalan ialah POST yang membawa Upgrade: tailscale-control-protocol. Proksi yang tidak memajukannya akan memutuskan satu-satunya saluran yang melaporkan keadaan nod. Bandingkan konfigurasi nginx anda dengan blok map di atas, atau tukar kepada Caddy untuk menyingkirkan proksi sebagai punca.

server_url berubah selepas nod didaftarkan. Nod terus menggunakan nilai yang diberikan semasa pendaftaran. Jika anda mengeditnya, jalankan sudo tailscale up --login-server https://headscale.example.com --force-reauth pada setiap nod.

Klien tidak berjalan. Pada nod, sudo systemctl is-active tailscaled dan sudo journalctl -u tailscaled -n 50 --no-pager. Klien yang tidak dapat menyelesaikan atau mencapai domain anda akan merekodkan percubaannya di situ.

Kunci telah tamat tempoh. Perkara ini dibincangkan dalam bahagian seterusnya.

Untuk memantau bahagian pelayan semasa ujian, jalankan sudo journalctl -u headscale -f pada VPS dan mulakan semula tailscaled pada klien. Nod yang berjaya mencapai headscale akan menghasilkan baris log dengan serta-merta. Jika tiada output, ini bermakna permintaan tidak sampai. Oleh itu, periksa DNS, firewall dan proksi sebelum memeriksa headscale.

Tempoh luput kunci dan nod yang berhenti berfungsi beberapa minggu kemudian

Terdapat dua tempoh luput yang berasingan. Jika kedua-duanya tersalah anggap, masa akan terbuang.

Kunci prapengesahan luput dengan cepat mengikut reka bentuk. Nilai lalai ialah satu jam dan satu penggunaan. Jika tailscale up menolak kunci itu, jana kunci baharu pada pelayan dan bukannya mengedit apa-apa pada klien.

Kunci nod ialah komponen yang mempunyai tempoh sah lebih panjang. Bahagian node dalam config.yaml menetapkan expiry: 0, manakala 0 bermaksud tiada tempoh luput lalai: nod berdaftar kekal sah sehingga anda meluputkannya. Nod bertanda tidak akan luput walau apa pun. Tetapkan expiry: 180d jika anda mahu pendaftaran luput secara automatik, dan fahami kesannya: setiap nod yang tidak bertanda kemudiannya memerlukan sudo tailscale up --login-server https://headscale.example.com --force-reauth mengikut jadual tersebut, manakala pelayan tanpa kepala yang tidak disahkan semula akan terputus daripada rangkaian dengan sendiri.

Lakukan secara manual apabila seseorang kehilangan komputer riba. sudo headscale nodes list memberikan ID tersebut, kemudian sudo headscale nodes expire -i 3 mengeluarkan nod itu daripada sesi log masuk, dan sudo headscale nodes delete -i 3 mengalih keluarnya sepenuhnya daripada rangkaian.

Sandaran dan peningkatan

/var/lib/headscale dan /etc/headscale bersama-sama merangkumi keseluruhan pelayan. Hentikan perkhidmatan sebelum menyalinnya kerana SQLite mungkin sedang menjalankan operasi tulis, dan pangkalan data yang disalin semasa beban kerja aktif mungkin tidak konsisten.

sudo systemctl stop headscale
sudo tar czf /root/headscale-state.tgz -C /var/lib headscale
sudo tar czf /root/headscale-config.tgz -C /etc headscale
sudo systemctl start headscale
sudo chmod 600 /root/headscale-*.tgz

Pindahkan kedua-dua fail keluar dari pelayan. Fail tersebut mengandungi kunci peribadi dan semua pendaftaran, jadi kendalikannya dengan tahap perlindungan yang sama seperti pelayan itu sendiri. sandaran restic daripada VPS menerangkan cara menjadualkan proses ini dan menyulitkan sandaran.

Peningkatan mengulangi proses pemasangan: muat turun .deb, sudo apt install ./headscale.deb yang baharu, kemudian mulakan semula dan jalankan semula pemeriksaan is-active dan /health. Sejak 0.29, laluan peningkatan adalah ketat. Melangkau versi kecil disekat, begitu juga menurunkan taraf kepada versi kecil yang lebih lama. Tingkatkan satu versi kecil pada satu masa, buat sandaran sebelum setiap langkah, dan baca nota keluaran versi tersebut terlebih dahulu kerana keluaran yang sama mengubah tingkah laku dasar ACL serta memindahkan beberapa kunci konfigurasi.

FAQ

Mengapakah headscale gagal dimulakan sejurus selepas saya memasang .deb?

Pakej memasang unit tetapi membiarkan perkhidmatan dihentikan, dan /etc/headscale/config.yaml lalai ialah templat, bukannya konfigurasi yang boleh digunakan. Edit server_url, listen_addr dan base_domain terlebih dahulu, kemudian jalankan sudo systemctl enable --now headscale dan sahkan dengan sudo systemctl is-active headscale. Jika masih gagal, sudo journalctl -u headscale -n 50 --no-pager menunjukkan masalahnya. Pada peringkat ini, masalah tersebut hampir selalu merupakan ralat YAML kerana headscale menghuraikan keseluruhan fail sebelum mengikat port.

Adakah saya masih perlu memasang klien Tailscale biasa pada mesin saya?

Ya. Headscale hanya menggantikan pelayan kawalan. Setiap nod menjalankan klien rasmi daripada Tailscale, dan anda mengarahkannya ke pelayan dengan sudo tailscale up --login-server https://headscale.example.com. Flag tersebut wujud dalam klien standard, jadi tiada apa-apa perlu ditampal atau dibina semula.

Adakah trafik saya melalui pelayan headscale?

Biasanya tidak. Headscale menyelaraskan rangkaian serta mengagihkan kunci dan alamat, manakala laluan data menggunakan WireGuard secara terus antara nod anda. Trafik hanya melalui laluan alternatif apabila dua nod tidak dapat berhubung secara terus lalu menggunakan relay DERP. Dengan konfigurasi yang dibekalkan, relay tersebut ialah relay awam Tailscale. Jalankan tailscale status pada nod untuk melihat sama ada peer tertentu ialah direct atau berada pada relay.

Mengapakah nod saya kekal di luar talian selepas didaftarkan?

Nod yang muncul dalam headscale nodes list tetapi tidak pernah berada dalam talian biasanya telah kehilangan sambungan kawalannya pada proksi songsang. Sambungan tersebut ialah peningkatan HTTP yang dihantar sebagai POST dengan pengepala Upgrade: tailscale-control-protocol. nginx menggugurkannya melainkan anda menambah blok map $http_upgrade $connection_upgrade dan baris proxy_set_header yang sepadan. Caddy memajukannya tanpa konfigurasi tambahan, jadi Caddy ialah cara pantas untuk menguji sama ada proksi tersebut menjadi punca masalah.

Adakah saya memerlukan nama domain dan TLS untuk headscale?

Dalam amalan, ya. Klien bersambung kepada rentetan yang anda letakkan dalam server_url, sijil dikeluarkan untuk nama dan bukan untuk alamat IP mentah, dan fail konfigurasi menyatakan bahawa DERP memerlukan TLS. Domain bersama Caddy boleh disediakan dalam kira-kira lima minit dan memberikan anda titik akhir HTTPS yang memperbaharui sijilnya sendiri. Menjalankan pelayan kawalan melalui HTTP biasa bermakna setiap komunikasi klien dengannya merentasi internet tanpa penyulitan.