Hướng dẫn self-hosting VPN kiểu Tailscale: Dùng Tailscale Client + Headscale
Bạn đang tìm cách xây dựng một mạng VPN mesh siêu dễ dùng, giống hệt Tailscale, nhưng hoàn toàn tự host, không phụ thuộc cloud của Tailscale Inc.?
Giải pháp hoàn hảo chính là combo Tailscale Client (chính thức) + Headscale – phiên bản open-source của Tailscale Control Server.
Bạn vẫn dùng đúng app Tailscale trên Windows, macOS, Linux, iOS, Android… nhưng toàn bộ traffic coordination và key exchange diễn ra trên server riêng của bạn.
Lợi ích lớn nhất:
- 100% private (không ai biết thiết bị nào kết nối với ai).
- Miễn phí (không giới hạn thiết bị).
- Giống hệt trải nghiệm Tailscale: auto NAT traversal, MagicDNS, ACL, Exit Node, Subnet Router…
- Dễ scale cho homelab, công ty nhỏ, team remote.
Bài viết này sẽ hướng dẫn ae từng bước để setup combo này, dùng cách hiện đại và ổn định nhất: Docker Compose + Caddy (auto HTTPS).
1. Yêu cầu trước khi bắt đầu
- Server: VPS Ubuntu 22.04/24.04 (khuyến nghị DigitalOcean, Vultr). Ít nhất 1 CPU – 2GB RAM (dùng thoải mái).
- Domain/Subdomain: Ví dụ
headscale.vnrom.nettrỏ A record về IP public của VPS. - Port mở: 80 (cho Let’s Encrypt) và 443 (HTTPS). Nếu dùng firewall ufw:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable- Docker & Docker Compose đã cài (nếu chưa:
sudo apt install docker.io docker-compose-plugin -y). - Kiến thức cơ bản về terminal.
2. Cài đặt Headscale cực nhanh với Auto-Install Script (Khuyên dùng)
Thay vì phải tạo thủ công từng file cấu hình như cách truyền thống, mình đã viết sẵn một script cài đặt tự động (hỗ trợ cả tiếng Việt và tiếng Anh) giúp bạn triển khai Headscale kèm theo giao diện quản lý Web UI siêu đẹp mà không sợ lỗi vặt.
Script này tự động nhận diện hệ điều hành (chạy ngon nghẻ trên VPS, Apple Silicon Mac, hay Raspberry Pi), tự sinh cấu hình an toàn, tự nạp module DNS để fix lỗi khởi động phiên bản mới nhất, và tạo sẵn một helper script để dễ dàng thao tác sau này.
Thực hiện siêu tốc qua 1 câu lệnh duy nhất:
# Tạo thư mục và tải script
mkdir -p ~/headscale && cd ~/headscale
curl -O https://raw.githubusercontent.com/duynghien/auto/main/headscale/setup.sh
# Chạy lệnh cài đặt
chmod +x setup.sh
./setup.shQuá trình cài đặt trên màn hình sẽ hỏi bạn:
- Chọn ngôn ngữ (1: Tiếng Anh, 2: Tiếng Việt).
- Tùy chọn chạy qua Domain (khuyến nghị có public HTTPS), LAN IP, hoặc Localhost.
- Nhập Public Domain (VD:
https://vpn.vnrom.net). - Bật giao diện Headscale Web UI (điền
y).
Sau vài giây Docker tải image, toàn bộ máy chủ Headscale và Web UI sẽ sẵn sàng cất cánh.
Cách dùng qua Helper Script tiện dụng
Thay vì phải gõ lệnh Docker Compose dài dòng, mình đã trang bị sẵn script headscale.sh trong thư mục cài đặt.
Để tạo người dùng (User) mới có tên là vnrom:
./headscale.sh cmd users create vnromĐể sinh mã đăng nhập Auth Key cho tải thiện bị của vnrom:
./headscale.sh cmd preauthkeys create -u vnromTrường hợp bạn dùng Dashboard Web UI (mặc định tại <IP>:9090 hoặc http://localhost:9090), ban đầu bảng điều khiển sẽ cần nhập API Key kết nối với Headscale. Chỉ cần tạo mã bằng lệnh này rồi paste vào giao diện Web UI (Mục Settings):
./headscale.sh apikey3. Cài đặt Headscale với Docker Compose (thủ công)
Tạo thư mục dự án:
mkdir ~/headscale && cd ~/headscale
mkdir config libTạo file docker-compose.yml
services:
headscale:
image: headscale/headscale:stable
container_name: headscale
volumes:
- ./config:/etc/headscale
- ./lib:/var/lib/headscale
restart: unless-stopped
command: serve
healthcheck:
test: ["CMD", "headscale", "health"]
interval: 30s
timeout: 5s
retries: 3
caddy:
image: caddy:latest
container_name: caddy
ports:
- "80:80"
- "443:443"
- "443:443/udp" # QUIC cho Tailscale
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
restart: unless-stopped
depends_on:
- headscale
volumes:
caddy_data:
caddy_config:Tạo file Caddyfile
https://headscale.vnrom.net {
reverse_proxy * http://headscale:8080
}Tải và chỉnh config.yaml
cd ~/headscale/config
curl -o config.yaml https://raw.githubusercontent.com/juanfont/headscale/main/config-example.yaml
nano config.yamlCác thay đổi quan trọng nhất (chỉ sửa những dòng mình đánh dấu):
server_url: https://headscale.vnrom.net # ← Quan trọng nhất
listen_addr: 0.0.0.0:8080
grpc_listen_addr: 0.0.0.0:50443
# TLS tự động bằng Let's Encrypt
tls_letsencrypt_hostname: headscale.vnrom.net # ← Đổi thành tên miền của bạn
tls_letsencrypt_cache_dir: /var/lib/headscale/cache
tls_letsencrypt_challenge_type: HTTP-01
# Database (sqlite đủ mạnh cho hầu hết trường hợp)
database:
type: sqlite
sqlite:
path: /var/lib/headscale/db.sqlite
write_ahead_log: true
# MagicDNS (rất hay dùng)
dns:
magic_dns: true
base_domain: ts.vnrom.net # ← Khác với server_url
nameservers:
global:
- 1.1.1.1
- 1.0.0.1
# ACL (bắt buộc nếu muốn kiểm soát quyền)
policy:
mode: file
path: /etc/headscale/acl.hujsonLưu lại và khởi động:
cd ~/headscale
docker compose up -dKiểm tra:
docker compose ps
docker compose logs -f headscale # xem log
curl -I https://headscale.vnrom.net/health # phải trả về 200 OK3. Tạo User & Pre-auth Key
Vào container:
docker exec -it headscale shTạo user (ví dụ tên bạn):
headscale users create duyTạo pre-auth key (dùng 1 lần, hết hạn 1 giờ):
headscale preauthkeys create --user duy --expiration 24h # có thể 24hCopy key (dạng hskey-auth-xxx...) ra ngoài.
Thoát container bằng exit.
4. Kết nối các thiết bị (Tailscale Client chính thức)
Linux (Ubuntu/Debian):
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up \
--login-server https://headscale.vnrom.net \
--authkey hskey-auth-xxx... \
--advertise-exit-node # nếu muốn làm Exit NodeWindows:
- Tải Tailscale từ tailscale.com/download
- Mở CMD/PowerShell với quyền Admin:
tailscale login --login-server https://headscale.vnrom.netHoặc dùng --authkey như trên.
macOS / iOS / Android:
- Cài app Tailscale từ App Store / Play Store / tailscale.com
- Vào Settings → Use custom control server → nhập
https://headscale.vnrom.net
Sau khi connect thành công, kiểm tra trên server:
docker exec headscale headscale nodes listBạn sẽ thấy thiết bị hiện xanh, có IP 100.64.x.x.
5. ACL (Access Control List) – Kiểm soát quyền
Tạo file ~/headscale/config/acl.hujson:
{
"acls": [
{ "action": "accept", "src": ["*"], "dst": ["*:*"] } // allow all (test)
],
"ssh": [
{
"action": "accept",
"src": ["autogroup:member"],
"dst": ["autogroup:member"],
"users": ["root", "duy"]
}
]
}Sau khi lưu, Headscale tự reload. Muốn chặt chẽ hơn thì thay * bằng group cụ thể (ví dụ group:admin).
6. Tính năng nâng cao (giống Tailscale 100%)
- Exit Node: Trên máy muốn làm exit node:
tailscale up --advertise-exit-node→ trên máy khác:tailscale set --exit-node=ten-may - Subnet Router:
tailscale up --advertise-routes=192.168.1.0/24→ approve trên Headscale:headscale nodes approve-routes --id <node-id> - MagicDNS: Truy cập máy khác bằng tên:
duy-macbook.ts.vnrom.net - Tailscale SSH: Bật trong app hoặc
--advertise-tags=tag:sshvà dùng ACL ssh.
7. Web UI (tùy chọn nhưng cực tiện)
Thêm vào docker-compose.yml service headscale-ui:
headscale-ui:
image: ghcr.io/gurucomputing/headscale-ui:latest
container_name: headscale-ui
restart: unless-stoppedSửa Caddyfile thêm dòng:
reverse_proxy /web* http://headscale-ui:8080Truy cập: https://headscale.vnrom.net/web
8. Một vài lỗi thường gặp
- Không connect được: Kiểm tra
server_urlcó đúng HTTPS không? Port 443 mở? DNS A record đúng? - Key hết hạn: Tạo key mới.
- Node không online:
tailscale statustrên client, kiểm tra firewall client. - MagicDNS không hoạt động: Đảm bảo
base_domainkhácserver_url. - Cập nhật Headscale:
docker compose pull && docker compose up -d
Với Tailscale Client + Headscale, bạn đã có một hệ thống VPN mesh mạnh mẽ, riêng tư và miễn phí hoàn toàn. Không còn lo lắng về giới hạn thiết bị hay privacy của Tailscale cloud nữa.
Một vài tài liệu chính chủ cho anh em tham khảo thêm:
- Headscale docs: https://headscale.net
- GitHub: https://github.com/juanfont/headscale
- Tailscale clients: https://tailscale.com/download








