Headscale: 구독료 없이 Tailscale의 모든 기능을 누리는 방법!

BBetter Stack
Internet TechnologyTelecommutingComputing/Software

Transcript

00:00:00이것은 모든 서버에 설치 가능한 Tailscale의 무료 오픈 소스 버전인 Headscale입니다.
00:00:06인터넷 연결이 끊기거나 Tailscale이 갑자기 가격을 올릴 경우를 대비해, 암호화된 네트워크를 완벽하게 제어할 수 있게 해주죠.
00:00:13그런데 흥미로운 점은 Headscale을 만든 사람이 바로 Tailscale의 직원이라는 사실입니다.
00:00:18왜 자기들의 경쟁 모델을 만드는 사람에게 월급을 주고 있는 걸까요?
00:00:22구독 버튼을 누르고 그 이유를 함께 알아봅시다.
00:00:25자세한 내용을 살펴보기 전에 Headscale이 실제로 어떻게 작동하는지 빠르게 확인해 보죠.
00:00:30현재 세 대의 Hetzner 서버가 있습니다. 하나는 메인 Headscale 컨트롤 플레인용이고, 나머지 두 노드를 서로 연결해 보려고 합니다.
00:00:40이 두 노드는 현재 제 암호화된 네트워크의 일부입니다.
00:00:44모든 것이 Docker에서 실행 중이므로, 이 명령어를 입력하면 현재 활성화된 노드인 Ubuntu Test와 Ubuntu Test 2를 확인할 수 있습니다.
00:00:53그리고 이 주소들이 노드에 접속할 때 사용할 수 있는 IP 주소입니다.
00:00:56이제 이 두 노드 사이를 서로 연결해 보겠습니다.
00:00:59먼저 이 IP 주소를 복사합니다.
00:01:02그리고 Ubuntu Test 2 서버에서 root 계정으로 SSH 접속을 시도해 보겠습니다.
00:01:07원래 root 접속은 지양해야 하지만, 테스트 목적이니까요.
00:01:09방금 복사한 Headscale의 IP 주소를 입력합니다.
00:01:11엔터를 치고 화면을 정리하면, 보시는 것처럼 Ubuntu Test 1에 접속되었습니다.
00:01:17Ubuntu Test 2에서 1로 들어갔고, 다시 exit를 입력해 2로 돌아올 수 있습니다.
00:01:24반대로 Ubuntu Test 1에서도 Ubuntu Test 2의 IP를 붙여넣어 SSH 접속을 할 수 있죠.
00:01:31화면을 보시면 Ubuntu Test 1에서 Ubuntu Test 2로 성공적으로 접속된 것을 볼 수 있습니다.
00:01:36하지만 테일넷(tailnet) 외부인 제 맥(Mac)에서 새 탭을 열어 Ubuntu Test 2의 IP로 접속을 시도하면 어떨까요?
00:01:48보시다시피 네트워크 바깥에 있기 때문에 연결되지 않고 멈춰버립니다.
00:01:52방금 보신 것처럼 Headscale은 네트워크에 대한 완전한 권한을 부여합니다.
00:01:56모든 세부 사항을 직접 제어할 수 있고, 특정 업체에 종속되지 않고 원하는 만큼 노드를 추가할 수 있습니다.
00:02:03구형 라즈베리 파이나 NAS에 연결하면 인터넷 없이도 작동 가능합니다.
00:02:08다만 설정 과정이 조금 복잡합니다.
00:02:11실제로 어떻게 구축하는지 보여드리겠습니다.
00:02:13지금 Ubuntu Test 3라는 새 서버를 만들었는데요, 두 노드를 연결할 새 사용자와 함께 새로운 테일넷, 즉 암호화된 서버를 생성할 겁니다.
00:02:24테스트를 위해 Ubuntu Test 3와 Ubuntu Test 1을 연결해 보죠.
00:02:29제 Headscale 컨트롤 플레인에는 이미 설치가 되어 있지만, 어떤 과정을 거쳤는지 훑어보겠습니다.
00:02:37현재 세 개의 Docker 컨테이너가 실행 중입니다.
00:02:40Headscale UI, Headscale 본체, 그리고 Caddy입니다.
00:02:45Docker Compose 파일을 보면 Headscale 공식 문서에 있는 예제와 매우 유사합니다.
00:02:56다만 Headscale 버전이나 디렉토리 경로 같은 몇 가지 사항만 수정했습니다.
00:03:03Headscale에서 사용할 수 있는 여러 오픈 소스 웹 UI 중 하나인 Headscale UI 컨테이너도 추가했습니다.
00:03:11이건 잠시 후에 보여드릴게요.
00:03:13그리고 리버스 프록시 역할을 할 Caddy가 있습니다.
00:03:16이 Docker Compose 파일 링크는 영상 설명란에 남겨두겠습니다.
00:03:21이 디렉토리에는 lib 폴더와 config 폴더가 있습니다.
00:03:26lib 폴더는 사용자, 노드, DNS 정보 등을 관리하는 SQLite 데이터베이스를 보관하는 곳입니다.
00:03:36원한다면 설정에서 SQLite 대신 Postgres 데이터베이스로 변경할 수도 있습니다.
00:03:43config 디렉토리에는 Tailscale 설정과 JSON 형식의 액세스 제어 목록(ACL) 정책 파일이 들어 있습니다.
00:03:52이건 나중에 더 설명하겠지만, Tailscale 문서에서 가져와 서버로 바로 내려받을 수 있는 파일입니다.
00:04:01GitHub의 예제 설정을 보면 서버 주소부터 접두사, 정책 파일 위치까지 모든 것을 변경할 수 있음을 알 수 있습니다.
00:04:11제 설정도 거의 비슷한데, 네트워크 내 노드들이 서로를 찾을 수 있도록 서버 URL을 Cloudflare 도메인으로 연결해 주었습니다.
00:04:23정책 파일 경로를 추가한 것 외에는 크게 건드린 게 없습니다.
00:04:28도메인은 일반적인 Cloudflare 설정이며, headscale 서브도메인의 A 레코드를 컨트롤 플레인의 IP 주소로 연결했습니다.
00:04:37이렇게 설정한 뒤 Caddy 파일을 열어보면, UI용 URL(/web)과 프록시용 URL 두 개가 사용 중인 것을 볼 수 있습니다.
00:04:49설정이 끝났다면 첫 번째로 할 일은 사용자를 만드는 것입니다. 이 명령어를 입력하면 됩니다.
00:04:56사용자 이름을 “Tom”으로 정해볼까요? 이름은 무엇이든 상관없습니다.
00:05:00사용자가 생성되었습니다. 리스트를 확인해 보면 ID 6번으로 새 사용자가 추가된 것을 볼 수 있습니다.
00:05:08하지만 아직 이 사용자에게 할당된 노드가 없습니다.
00:05:11이제 Tom에게 노드를 연결해 봅시다.
00:05:13새로 만든 Ubuntu Test 3 서버에서 가장 먼저 할 일은 이 명령어를 실행해 Tailscale 클라이언트를 추가하는 것입니다.
00:05:23이제 Tailscale 바이너리를 사용할 수 있게 되었습니다.
00:05:27root 사용자가 아니라면 명령어 앞에 sudo를 붙여야 할 수도 있습니다.
00:05:31하지만 서비스를 시작하거나 로그인하기 전에, Headscale과 연동되도록 특정 방식으로 실행해야 합니다.
00:05:38그러기 위해 사전 인증 키(pre-auth keys)를 생성해야 하는데, 관련 명령어는 Headscale 문서의 시작 가이드에서 찾을 수 있습니다.
00:05:46스크롤을 내려서 이 명령어를 복사하겠습니다.
00:05:49Headscale 컨트롤 플레인에서 'docker exec' 뒤에 방금 복사한 명령어를 붙여넣습니다.
00:05:54사용자 ID 부분에는 Tom의 ID인 6을 입력합니다.
00:05:59컨테이너 내부로 명령을 보내는 것이므로 'headscale'을 한 번 더 써줘야 합니다.
00:06:04이제 사전 인증 키가 생성되었습니다.
00:06:07이 명령어를 복사해서 Ubuntu Test 3 서버에 붙여넣습니다.
00:06:11그다음 방금 만든 사전 인증 키를 여기에 입력합니다.
00:06:15마지막으로 로그인 서버 주소를 우리가 설정한 headscale.pandor.css로 변경해 줍니다.
00:06:23Pandora 도메인은 이미 누가 쓰고 있더군요. 아니면 그걸 썼을 텐데요.
00:06:26엔터를 치면 Headscale 네트워크에 새 노드가 성공적으로 추가될 겁니다.
00:06:31다시 컨트롤 플레인으로 돌아와 노드 리스트를 확인하면, Tom 소속의 Ubuntu Test 3가 IP 주소와 함께 나타납니다.
00:06:44이제 Ubuntu Test 1도 Tom에게 할당해 보겠습니다.
00:06:47우선 ID 1번인 기존 노드를 삭제하겠습니다. 확인 절차를 생략하기 위해 강제 삭제 옵션을 사용합니다.
00:06:56이제 새 인증 키를 만들고 Ubuntu Test 서버에 등록합니다. SSH 기능을 사용 중이니 SSH 플래그도 잊지 말고 넣어줍니다.
00:07:06Ubuntu Test 3 서버에서도 SSH 접속이 가능하도록 설정을 마무리해 줍니다.
00:07:13노드 목록을 다시 보면 Ubuntu Test 1과 3 모두 Tom의 계정 아래에 있습니다.
00:07:20이제 두 서버를 서로 연결해 보겠습니다.
00:07:21Ubuntu Test 3의 IP를 복사해 Ubuntu Test 1로 가서 SSH 접속을 시도합니다.
00:07:30키를 승인하니 Ubuntu Test 1에서 Ubuntu Test 3로 접속이 잘 됩니다.
00:07:35반대로 Ubuntu Test 3에서 1로 접속하는 것도 가능합니다.
00:07:41제 단계를 그대로 따라 하셨더라도 작동하지 않을 확률이 매우 높은데, 그건 액세스 제어 정책(ACL)을 설정해야 하기 때문입니다.
00:07:49제가 사용하는 정책을 보여드릴게요.
00:07:51Headscale 디렉토리의 config 폴더를 보면 사람이 읽을 수 있는 JSON 형식의 ACL 파일이 있습니다.
00:08:01내용을 보면 네트워크 내 누구든 어떤 목적지나 포트로든 접속을 허용하는 매우 간단한 설정입니다.
00:08:11또한 테일넷 내부의 모든 노드가 별도의 승인 없이 root 계정으로 SSH 접속을 할 수 있게 되어 있죠.
00:08:24물론 실제 환경에서는 보안을 위해 특정 노드가 특정 포트로만 접속할 수 있게 훨씬 엄격하게 설정해야 합니다.
00:08:33하지만 이건 시작을 돕기 위한 아주 기초적인 구성입니다.
00:08:37마찬가지로 이 설정 파일의 링크도 설명란에 적어두겠습니다.
00:08:40그럼 “Headscale UI를 쓰면 이 모든 과정이 쉬워지나?”라는 의문이 드실 겁니다.
00:08:43제 대답은 “그럴 수도 있고 아닐 수도 있다”입니다.
00:08:45보여드리죠.
00:08:47이것이 제 Headscale UI 주소입니다. 현재 Tess와 Tom 두 사용자의 정보가 보입니다.
00:08:48연결된 키와 노드 정보 등을 확인할 수 있습니다.
00:08:57이걸 쓰려면 먼저 명령어를 실행해 생성한 Headscale API 키를 등록해야 합니다.
00:09:01그런데 제가 겪은 문제는 장치 목록(device view) 화면입니다.
00:09:06보시다시피 정보가 거의 표시되지 않는데, 콘솔을 보면 TypeScript 타입 오류가 납니다. 소스 코드를 건드리지 않았으니 제 잘못은 아닐 겁니다.
00:09:09이 지점에서 앱이 멈춰버려서 아무것도 할 수가 없습니다.
00:09:22원래는 여기서 새 장치를 추가하거나 설정을 변경할 수 있어야 하거든요.
00:09:26버그가 너무 많아서 아직은 큰 도움이 되지 않는 것 같습니다.
00:09:32액세스 정책 설정을 더 쉽게 해주는 다른 UI들도 시중에 많이 나와 있습니다.
00:09:35하지만 제 개인적인 경험상, 아직 Headscale UI가 아주 유용하다고 보긴 어렵네요.
00:09:42네, 설정 과정이 확실히 복잡합니다.
00:09:46정말 많이 복잡하죠.
00:09:49기술적 배경이 없거나 주니어 개발자라면 혼자 설정하는 데 꽤 애를 먹을 겁니다.
00:09:51아마 그래서 Tailscale 측에서도 직원이 이 프로젝트를 하도록 놔두는 것 같습니다. 당장은 회사 수익에 큰 위협이 되지 않으니까요.
00:09:57누군가 Claude Opus 같은 AI를 활용해 아주 깔끔한 UI를 입힌다면 멋진 서비스가 되겠지만, 라이선스 문제에 부딪힐 수도 있겠죠.
00:10:07하지만 일단 모든 설정을 마치고 나면, Headscale은 정말 놀라울 정도로 잘 작동합니다.
00:10:18물론 서버를 외부에 공개하는 Funnel이나 Serve 기능 같은 일부 미지원 기능이 있긴 합니다.
00:10:22다중 테일넷, 일시적 노드(ephemeral nodes), 네이티브 네트워크 로그 기능 등도 아직은 지원하지 않습니다.
00:10:32그럼에도 오픈 소스 도구치고는 굉장히 인상적입니다.
00:10:38나중에 제 개인 AI(OpenClaw)를 로컬 LLM을 통해 완전히 오프라인으로 돌리고 싶어지면, Headscale 도입을 진지하게 고려해 볼 것 같습니다.
00:10:42And if I ever get to the stage where I want my OpenClaw to run completely offline with a local LLM, then I may consider it.

Key Takeaway

Headscale은 Tailscale의 강력한 메시 VPN 기능을 유지하면서도 중앙 제어 서버를 직접 운영함으로써 완전한 독립성과 무료 이용 환경을 제공하는 오픈 소스 프로젝트입니다.

Highlights

Headscale은 Tailscale의 제어 서버를 오픈 소스로 구현하여 사용자가 네트워크를 완전히 제어할 수 있게 함

Tailscale 직원이 직접 개발에 참여하여 공식 서비스와 높은 호환성을 유지함

Docker와 Caddy를 활용한 자가 호스팅 설정 과정과 도메인 연결 방법 제시

사용자 생성, 사전 인증 키 발급 및 노드 등록을 통한 암호화된 테일넷 구축 시연

ACL(액세스 제어 목록) 설정을 통한 노드 간 권한 관리 및 SSH 접속 자동화

현재 Headscale UI의 버그와 기술적 복잡성 등 실질적인 사용 시 주의사항 언급

구독료 부담 없이 독립적인 프라이빗 네트워크를 구축하려는 고급 사용자에게 최적의 솔루션

Timeline

Headscale 개요 및 도입 배경

Headscale은 Tailscale의 무료 오픈 소스 버전으로, 사용자가 자신의 암호화된 네트워크를 완벽하게 제어할 수 있도록 돕는 도구입니다. 인터넷 연결이 끊기거나 서비스 가격이 인상되는 상황에 대비할 수 있는 훌륭한 대안으로 소개됩니다. 특히 이 프로젝트의 제작자가 Tailscale의 현직 직원이라는 흥미로운 사실을 밝히며 시청자의 호기심을 자극합니다. 기업이 경쟁 모델이 될 수 있는 프로젝트를 지원하는 이유를 탐구하며 본격적인 설명을 시작합니다. 전반적으로 중앙 집중식 서비스에서 벗어나 독립적인 네트워크 권한을 갖는 것의 중요성을 강조합니다.

네트워크 연결 및 작동 원리 시연

실제 Hetzner 서버 세 대를 사용하여 Headscale 컨트롤 플레인과 두 개의 노드를 연결하는 과정을 실습으로 보여줍니다. Docker 환경에서 실행되는 노드들의 IP 주소를 확인하고, 암호화된 테일넷 내부에서 SSH를 통해 서로 자유롭게 접속하는 모습을 시연합니다. 반면 네트워크 외부에 있는 기기에서는 해당 IP로 접근이 불가능함을 보여주며 보안성을 입증합니다. 사용자는 이를 통해 특정 업체에 종속되지 않고 라즈베리 파이나 NAS 등 다양한 하드웨어를 네트워크에 추가할 수 있습니다. 설정 과정이 다소 복잡할 수 있다는 점을 미리 고지하며 기술적 접근을 준비시킵니다.

Docker 기반 서버 설정 및 구성 요소

Ubuntu 서버를 활용해 새로운 테일넷을 구축하는 구체적인 기술 스택과 설정 파일을 분석합니다. Headscale 본체, 웹 UI, 그리고 리버스 프록시 역할을 하는 Caddy까지 총 세 개의 Docker 컨테이너 구성을 설명합니다. 데이터베이스 관리를 위한 SQLite 설정과 노드 간 통신을 제어하는 ACL(액세스 제어 목록) 정책 파일의 구조를 상세히 다룹니다. Cloudflare 도메인의 A 레코드를 컨트롤 플레인 IP에 연결하여 네트워크 가시성을 확보하는 과정을 포함합니다. 이 섹션은 실제 구축을 원하는 사용자들이 참고할 수 있는 아키텍처 가이드 역할을 합니다.

사용자 생성 및 노드 등록 실습

명령줄 인터페이스(CLI)를 통해 새로운 사용자 'Tom'을 생성하고 고유 ID를 부여하는 과정을 보여줍니다. 클라이언트 기기에 Tailscale 바이너리를 설치한 후, Headscale 서버와 통신하기 위해 전용 로그인 서버 주소를 지정하는 방법을 설명합니다. 특히 보안 승인을 위해 사전 인증 키(pre-auth keys)를 생성하고 이를 노드 등록 시 사용하는 절차가 핵심입니다. 여러 대의 노드를 동일한 사용자 계정에 할당하여 서로 원활하게 SSH 접속이 가능해지는 상태를 최종 확인합니다. 복잡한 명령어를 단계별로 풀어서 설명하여 기술적 진입 장벽을 낮추려고 노력합니다.

ACL 정책 설정 및 보안 관리

노드가 성공적으로 등록되었음에도 통신이 되지 않을 때 반드시 확인해야 할 ACL(액세스 제어 목록) 설정을 다룹니다. JSON 형식으로 작성된 정책 파일을 통해 특정 포트와 목적지에 대한 접속 권한을 어떻게 부여하는지 예시를 들어 설명합니다. 기본 설정에서는 모든 노드 간의 통신과 root 계정 SSH 접속을 허용하는 광범위한 정책을 사용하지만, 실제 환경에서의 위험성도 경고합니다. 보안 강화를 위해 특정 서비스와 노드에만 최소한의 권한을 주는 엄격한 설정의 필요성을 강조합니다. 이 섹션은 네트워크 운영의 핵심인 보안 제어 메커니즘을 이해하는 데 큰 도움을 줍니다.

Headscale UI의 한계와 결론

웹 기반으로 관리를 편리하게 해주는 Headscale UI를 소개하지만, 현재 버전에서 발생하는 다양한 버그와 타입 오류 등 한계점을 솔직하게 지적합니다. 장치 목록이 제대로 표시되지 않는 등 실무에서 사용하기에는 아직 미흡한 부분이 많아 CLI 방식이 더 안정적임을 시사합니다. Tailscale이 이 프로젝트를 방치하는 이유가 높은 기술적 난이도로 인해 일반 대중의 유입이 적기 때문이라는 분석을 내놓습니다. 그럼에도 불구하고 설정 완료 후의 성능은 매우 뛰어나며, 로컬 AI 서버 운영 등 오프라인 환경 구축에 강력한 도구가 될 것임을 확신합니다. 일부 고급 기능의 미지원에도 불구하고 오픈 소스로서의 가치가 충분하다는 결론으로 마무리합니다.

Community Posts

View all posts