Tailscale 실전 구성: 설치부터 ACL, Docker, Headscale 자체 호스팅까지
Tailscale 설치·CLI 명령어·Subnet Router·Exit Node·ACL·Docker 연동·Headscale 자체 호스팅까지 실무에서 바로 쓰는 구성 절차를 정리한다.
2026-08-12 · 최초 발행 2026-03-13
Tailscale을 실제로 운영에 넣으려면 개념보다 손에 익혀야 할 절차가 많다. 설치부터 초기 설정, CLI 명령어, Subnet Router·Exit Node 구성, ACL 정책, Docker/Kubernetes 연동, 자체 호스팅(Headscale)까지 순서대로 짚는다.
설치
Linux
원라인 설치 스크립트로 시작한다.
# 원라인 설치 스크립트
curl -fsSL https://tailscale.com/install.sh | sh
# 설치 후 Tailscale 시작
sudo tailscale up
# 서비스 자동 시작 등록
sudo systemctl enable --now tailscaled
배포판별 패키지 매니저로 수동 설치할 수도 있다.
# Ubuntu/Debian
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list
sudo apt-get update
sudo apt-get install tailscale
# RHEL/CentOS/Fedora
sudo dnf config-manager --add-repo https://pkgs.tailscale.com/stable/fedora/tailscale.repo
sudo dnf install tailscale
sudo systemctl enable --now tailscaled
macOS
Tailscale 패키지 서버에서 Standalone 버전을 받는 것이 권장 방식이다. Mac App Store에서 "Tailscale"을 검색해 설치할 수도 있고, CLI만 필요하면 GitHub 릴리스에서 오픈소스 바이너리를 받으면 된다. 최소 요구사항은 macOS 12.0(Monterey) 이상이다.
Windows
Tailscale 다운로드 페이지에서 MSI 설치 파일을 받는다. 설치가 끝나면 시스템 트레이의 Tailscale 아이콘을 눌러 Log in을 선택하고, Google·Microsoft·GitHub 같은 SSO 제공자로 인증한다.
초기 설정과 Tailnet 구성
계정 생성부터 Tailnet이 완성되기까지 흐름은 다음과 같다.
login.tailscale.com에서 Google·Microsoft·GitHub·Okta 같은 SSO 제공자로 계정을 만든다. 첫 번째 디바이스에서 tailscale up을 실행하면 브라우저로 SSO 인증 화면이 뜨고, 두 번째 디바이스에서 같은 계정으로 다시 tailscale up을 실행하면 두 디바이스가 자동으로 Tailnet(가상 사설 네트워크)을 형성하며 100.x.y.z 대역의 IP가 할당된다.
MagicDNS 켜기
Admin Console의 DNS 설정에서 MagicDNS를 활성화하면 디바이스명으로 접근할 수 있다.
# IP 대신 디바이스명으로 접속
ssh user@my-server # MagicDNS 활성화 시
ssh user@my-server.tailnet-name.ts.net # FQDN 형식
ping my-nas # 디바이스명으로 ping
CLI로 다루는 일상 작업
연결 관리
# Tailscale 연결 (기본)
sudo tailscale up
# 인증 키로 자동 연결 (서버/CI 환경)
sudo tailscale up --authkey=tskey-auth-xxxxx
# 호스트명 지정
sudo tailscale up --hostname=prod-web-01
# 연결 해제 (노드 유지)
sudo tailscale down
# 완전 로그아웃 (노드 제거)
sudo tailscale logout
상태 확인
# 연결 상태 확인
tailscale status
# 출력 예시:
# 100.64.0.1 my-laptop user@ linux idle
# 100.64.0.2 prod-server user@ linux active; direct 1.2.3.4:41641
# 100.64.0.3 home-nas user@ linux active; relay "tok"
# JSON 형식 상세 정보
tailscale status --json
# 현재 디바이스의 Tailscale IP 확인
tailscale ip
tailscale ip -4 # IPv4만
tailscale ip -6 # IPv6만
relay "tok"처럼 릴레이 경유 여부가 상태 출력에 그대로 드러나기 때문에, 연결 품질을 확인할 때 가장 먼저 보는 명령이다.
네트워크 진단
# 네트워크 상태 진단
tailscale netcheck
# 출력 예시:
# Report:
# * UDP: true
# * IPv4: yes, 1.2.3.4:12345
# * IPv6: yes, [2001:db8::1]:12345
# * MappingVariesByDestIP: false
# * HairPinning: true
# * PortMapping: UPnP, PMP, PCP
# * Nearest DERP: Tokyo
# * DERP latency:
# - tok: 3.2ms (Tokyo)
# - sin: 65.4ms (Singapore)
# - sfo: 120ms (San Francisco)
# 특정 피어와의 연결 상태 확인
tailscale ping my-server
# pong from my-server (100.64.0.2) via 1.2.3.4:41641 in 5ms
파일 전송 (Taildrop)
# 파일 전송
tailscale file cp ./report.pdf my-server:
# 파일 수신 (수신 대기)
tailscale file get ./downloads/
Subnet Router 구성
Tailscale 클라이언트를 설치할 수 없는 레거시 장비나 사내 네트워크에 접근해야 할 때 Subnet Router를 쓴다.
설정 절차
# (1) IP 포워딩 활성화 (Linux)
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf
# (2) Subnet Router로 라우트 광고
sudo tailscale up --advertise-routes=192.168.1.0/24,10.0.0.0/8
# (3) Admin Console에서 해당 노드의 라우트 승인
# 또는 ACL에 autoApprovers 설정으로 자동 승인
# (4) 클라이언트에서 서브넷 라우트 수락
sudo tailscale up --accept-routes
autoApprovers ACL 설정
Admin Console에서 매번 수동 승인하는 대신, ACL에 autoApprovers를 넣으면 지정한 태그·그룹의 라우트를 자동 승인한다.
{
"autoApprovers": {
"routes": {
"192.168.1.0/24": ["tag:server"],
"10.0.0.0/8": ["group:network-admins"]
}
}
}
Exit Node 구성
모든 인터넷 트래픽을 특정 노드로 몰아서 공용 Wi-Fi 환경을 보호하거나 특정 지역 IP로 접속하고 싶을 때 쓴다.
Exit Node 서버 설정
# Exit Node로 광고
sudo tailscale up --advertise-exit-node
# Admin Console에서 Exit Node 승인 필요
# 또는 ACL autoApprovers 설정:
# "exitNode": ["tag:exit-node"]
Exit Node 클라이언트 사용
# 특정 Exit Node 사용
sudo tailscale up --exit-node=prod-vpn-server
# Exit Node 해제
sudo tailscale up --exit-node=
ACL 정책 설정
ACL은 JSON(또는 HuJSON) 형식으로 Admin Console에서 관리하며, GitOps 방식으로도 다룰 수 있다.
기본 ACL 구조
{
"groups": {
"group:devs": ["user1@company.com", "user2@company.com"],
"group:ops": ["admin@company.com"]
},
"tagOwners": {
"tag:server": ["group:ops"],
"tag:db": ["group:ops"]
},
"acls": [
{
"action": "accept",
"src": ["group:devs"],
"dst": ["tag:server:80,443"]
},
{
"action": "accept",
"src": ["group:ops"],
"dst": ["*:*"]
},
{
"action": "accept",
"src": ["tag:server"],
"dst": ["tag:db:5432"]
}
],
"ssh": [
{
"action": "accept",
"src": ["group:ops"],
"dst": ["tag:server"],
"users": ["root", "ubuntu"]
}
]
}
자주 쓰는 ACL 패턴
| 패턴 | 설명 | 예시 |
|---|---|---|
| 사용자 → 서버 | 특정 그룹이 서버의 특정 포트 접근 | "src": ["group:devs"], "dst": ["tag:web:80,443"] |
| 서버 → DB | 서버 간 내부 통신 허용 | "src": ["tag:app"], "dst": ["tag:db:5432"] |
| 전체 허용 | 운영팀 전체 접근 | "src": ["group:ops"], "dst": ["*:*"] |
| SSH 제어 | SSH 접근 사용자 및 대상 제한 | "ssh" 섹션에서 별도 정의 |
| 자동 승인 | 라우트/Exit Node 자동 승인 | "autoApprovers" 섹션 |
Docker 환경 구성
전용 컨테이너로 실행
# docker-compose.yml
version: "3.8"
services:
tailscale:
image: tailscale/tailscale:latest
container_name: tailscale
hostname: docker-node
environment:
- TS_AUTHKEY=tskey-auth-xxxxx
- TS_STATE_DIR=/var/lib/tailscale
- TS_USERSPACE=false
volumes:
- tailscale-state:/var/lib/tailscale
- /dev/net/tun:/dev/net/tun
cap_add:
- NET_ADMIN
- SYS_MODULE
restart: unless-stopped
volumes:
tailscale-state:
사이드카 패턴 (다른 컨테이너에 네트워크 공유)
network_mode: "service:tailscale"로 지정하면 다른 컨테이너가 Tailscale 컨테이너의 네트워크 네임스페이스를 그대로 쓴다.
services:
tailscale:
image: tailscale/tailscale:latest
environment:
- TS_AUTHKEY=tskey-auth-xxxxx
- TS_SERVE_CONFIG=/config/serve.json
volumes:
- tailscale-state:/var/lib/tailscale
cap_add:
- NET_ADMIN
network_mode: host
my-app:
image: my-app:latest
network_mode: "service:tailscale"
depends_on:
- tailscale
인증 키 관리
서버, CI/CD 러너, 컨테이너처럼 브라우저로 로그인할 수 없는 환경에서는 인증 키(Auth Key)를 쓴다.
인증 키 유형
| 유형 | 설명 | 용도 |
|---|---|---|
| 일회용 키 | 한 번만 사용 가능 | 단일 서버 등록 |
| 재사용 키 | 여러 디바이스 등록 가능 | CI/CD 러너, 컨테이너 |
| 에피메럴 키 | 디바이스 종료 시 자동 제거 | 컨테이너, 임시 환경 |
| 태그 키 | ACL 태그 자동 적용 | 자동화된 인프라 프로비저닝 |
인증 키 생성과 사용
Admin Console의 Settings → Keys → Generate auth key에서 만들 수도 있고, API로 직접 만들 수도 있다.
# Admin Console → Settings → Keys → Generate auth key
# 또는 API로 생성
curl -X POST "https://api.tailscale.com/api/v2/tailnet/-/keys" \
-u "tskey-api-xxxxx:" \
-H "Content-Type: application/json" \
-d '{
"capabilities": {
"devices": {
"create": {
"reusable": true,
"ephemeral": true,
"tags": ["tag:ci-runner"]
}
}
},
"expirySeconds": 86400
}'
# 인증 키로 디바이스 등록
sudo tailscale up --authkey=tskey-auth-xxxxx
Tailscale SSH 설정
별도의 SSH 키를 배포하지 않고도 SSO 인증만으로 SSH 접속을 관리할 수 있다.
# SSH 서버 측 설정
sudo tailscale up --ssh
# SSH 접속 (일반 SSH와 동일)
ssh user@my-server # Tailscale SSH 경유
ACL SSH 정책
{
"ssh": [
{
"action": "check",
"src": ["group:devs"],
"dst": ["tag:server"],
"users": ["ubuntu"],
"checkPeriod": "12h"
}
]
}
accept는 즉시 허용, check는 주기적 재인증을 요구해 보안을 강화하는 동작이고, checkPeriod로 재인증 주기를 설정한다.
자체 호스팅: Headscale
컨트롤 서버까지 완전히 자체 호스팅하려면 오픈소스 프로젝트 Headscale을 쓴다.
Docker Compose로 배포
# docker-compose.yml
version: "3.8"
services:
headscale:
image: headscale/headscale:latest
container_name: headscale
volumes:
- ./config:/etc/headscale
- headscale-data:/var/lib/headscale
ports:
- "8080:8080" # gRPC
- "443:443" # HTTPS
- "3478:3478/udp" # STUN
command: serve
restart: unless-stopped
volumes:
headscale-data:
초기 설정
# 사용자(네임스페이스) 생성
docker exec headscale headscale users create my-user
# 인증 키 생성
docker exec headscale headscale preauthkeys create --user my-user --reusable --expiration 24h
# 클라이언트에서 Headscale 서버로 연결
tailscale up --login-server=https://headscale.example.com --authkey=xxxxx
내장 DERP 서버 활성화
Headscale은 내장 DERP 서버를 포함하고 있어, 릴레이 트래픽까지 자체 호스팅할 수 있다.
# config.yaml (Headscale 설정)
derp:
server:
enabled: true
region_id: 999
region_code: "self"
region_name: "Self-hosted DERP"
stun_listen_addr: "0.0.0.0:3478"
트러블슈팅 체크리스트
연결 문제 진단
# (1) Tailscale 서비스 상태 확인
sudo systemctl status tailscaled
# (2) 네트워크 진단
tailscale netcheck
# (3) 특정 피어 연결 테스트
tailscale ping target-device
# (4) 방화벽 확인 사항
# - UDP 41641 (WireGuard direct)
# - UDP 3478 (STUN)
# - TCP 443 (DERP fallback)
# (5) 로그 확인
sudo journalctl -u tailscaled -f
자주 발생하는 문제
| 증상 | 원인 | 해결 방법 |
|---|---|---|
relay "tok" 표시 |
NAT 통과 실패, DERP 릴레이 경유 | 방화벽에서 UDP 41641 허용 |
idle 상태 지속 |
키 만료 또는 인증 실패 | tailscale up 재인증 |
| Subnet 접근 불가 | 라우트 미승인 또는 accept-routes 미설정 | Admin Console에서 라우트 승인 + --accept-routes |
| DNS 해석 실패 | MagicDNS 미활성화 | Admin Console → DNS에서 MagicDNS 활성화 |
| 느린 전송 속도 | DERP 릴레이 경유 중 | tailscale netcheck으로 직접 연결 여부 확인 |