왜 Ubuntu에서 Clash Meta 설치가 따로 필요할까요
많은 사용자에게 Clash는 GUI 클라이언트(Windows의 Verge 계열, macOS용 앱, Android의 FlClash, iOS의 Stash 등)로 먼저 익숙해집니다. 그러나 개발용 데스크톱·홈 서버·원격 워크스테이션처럼 Linux가 기본 OS인 환경에서는 GUI 없이 단일 바이너리로 돌리거나, 반대로 배포판 패키지 관리자 밖에서 최신 코어를 직접 올려야 하는 경우가 흔합니다. Ubuntu는 문서와 커뮤니티 예제가 많아 첫 Linux 타깃으로 자주 고르지만, 정작 「설치는 끝났는데 재부팅 후 안 뜬다」「TUN만 켜면 권한 오류」「브라우저는 되는데 터미널은 직통」 같은 운영 단계 문제에서 시간을 씁니다.
이 글의 목표는 세 가지입니다. 첫째, Ubuntu Clash Meta 설치를 재부팅 후에도 동일하게 재현할 수 있게 디렉터리·권한·실행 인자를 고정합니다. 둘째, Linux systemd 자동 시작을 유저 유닛과 시스템 유닛 관점에서 나누어 설명하고, 로그를 보는 위치까지 포함합니다. 셋째, Clash TUN Linux를 한 번에 켜지 않고 단계적으로 켜며, mixed 포트·환경 변수·데스크톱 프록시와의 관계를 정리합니다. 코어 이름은 생태계에서 Clash Meta와 Mihomo가 혼용되므로, 이하에서는 바이너리 파일명을 mihomo로 가정하고 설명합니다. 실제 파일명이 다르면 그에 맞춰 바꿔 읽으면 됩니다.
사전 준비: 배포판 확인과 최소 패키지
Ubuntu 22.04 LTS나 24.04 LTS처럼 장기 지원 버전을 기준으로 설명합니다. 아키텍처는 대부분 amd64이지만 ARM 소형 기기라면 릴리스 아티팩트를 맞춰야 합니다. 우선 커널이 TUN 모듈을 제공하는지, 그리고 사용자 네임스페이스나 AppArmor 정책이 특이하지 않은지 확인합니다. 서버 이미지를 최소 설치로 깔았다면 curl, ca-certificates, iproute2, dnsutils 정도는 미리 깔아 두면 DNS·라우팅 점검이 수월합니다.
바이너리를 가져오는 경로는 팀 정책에 따라 갈립니다. 엔터프라이즈 환경이라면 내부 아티팩트 저장소를 쓰고, 개인 장비라면 공식 다운로드 페이지에서 제공하는 패키지 정책을 우선 확인하는 편이 안전합니다. 오픈소스 릴리스 노트·체크섬·이슈 트래커는 신뢰와 투명성을 위해 별도로 열람할 수 있지만, 설치 패키지의 주 진입점은 독자에게 혼선을 주지 않도록 사이트 다운로드 흐름에 맞추는 것이 좋습니다. 버전을 올릴 때는 Mihomo 업그레이드 가이드의 백업·검증 순서를 함께 적용하면 YAML 호환성 이슈를 줄일 수 있습니다.
디렉터리 레이아웃과 실행 사용자
흔한 선택지는 두 가지입니다. 개인 계정으로만 쓸 때는 홈 디렉터리 아래 ~/.config/mihomo 같은 위치에 config.yaml과 규칙 캐시를 두고, systemd 유저 유닛으로 띄웁니다. 여러 사용자나 시스템 서비스와 함께 관리하려면 /etc/mihomo에 구성을 두고 시스템 유닛으로 띄우는 편이 명확합니다. 전자는 권한 분쟁이 적고 후자는 운영 표준화에 유리합니다. TUN을 켤 때는 어느 쪽이든 CAP_NET_ADMIN 같은 능력(capability) 이슈가 생길 수 있으므로, 처음에는 TUN 없이 mixed 포트만 열어 두고 동작을 확인한 뒤 단계적으로 넘어가는 것을 권합니다.
바이너리는 /usr/local/bin/mihomo에 두면 PATH 문제를 줄일 수 있습니다. 배포판이 /usr/bin을 패키지 관리자 전용으로 취급한다면 로컬 관리자 경로를 쓰는 편이 업그레이드 충돌을 피합니다. 파일 소유자는 실행 사용자와 맞추고, 설정 파일에는 민감한 키가 들어가므로 퍼미션을 600 또는 640 수준으로 제한합니다. 팀 저장소에 예제 YAML을 올릴 때는 반드시 익명화한 스텁만 공유하세요.
최소 구성으로 먼저 기동 확인하기
systemd에 넣기 전에 포그라운드에서 한 번 실행해 로그를 직접 보는 습관이 오류를 빠르게 줄여 줍니다. config.yaml에 mixed-port나 port·socks-port 조합을 명시하고, DNS 섹션은 초기에 단순하게 유지합니다. tun.enable은 당분간 false로 둡니다. 이렇게 하면 권한 문제와 무관하게 HTTP/SOCKS 레이어에서 노드 핸드셰이크와 규칙 매칭을 먼저 검증할 수 있습니다.
프로필에 구독 URL이 있다면 갱신 주기와 실패 시 동작을 확인합니다. 회사망에서는 직접 다운로드가 막혀 초기 구동만 실패하는 경우도 있으니, curl로 동일 URL에 접근해 보는 등 네트워크 전제를 분리해 점검하세요. 규칙이 길다면 MATCH 폴백이 의도한 그룹을 가리키는지, DIRECT가 너무 앞에 있어 오매칭하지 않는지 로그의 rule hit를 함께 봅니다. 이 단계가 안정화되어야 TUN을 켰을 때의 증상 분리가 쉬워집니다.
systemd 유저 유닛으로 자동 시작 구성
개인 데스크톱이라면 유저 유닛이 간단합니다. ~/.config/systemd/user/mihomo.service를 만들고, ExecStart에 바이너리와 구성 디렉터리 인자를 넣습니다. 네트워크가 준비된 뒤에 올리고 싶다면 After=network-online.target와 Wants=network-online.target를 함께 쓰는 패턴이 많습니다. 유닛 파일을 저장한 뒤 systemctl --user daemon-reload로 다시 읽고, systemctl --user enable --now mihomo.service로 즉시 기동과 자동 시작을 한 번에 걸 수 있습니다.
로그인 세션 전용이 아니라 백그라운드에서도 항상 돌리고 싶다면 loginctl enable-linger 같은 설정이 필요할 수 있습니다. 이는 배포판·보안 정책에 민감하므로 서버에서는 시스템 유닛을 검토하는 편이 낫습니다. 재부팅 후 상태를 확인할 때는 systemctl --user status mihomo.service와 journalctl --user -u mihomo.service -b를 병행하세요. 실패가 반복되면 Restart=on-failure와 짧은 RestartSec로 재시도 폭주를 막는 것도 운영 팁입니다.
예시 유닛은 아래와 같습니다. 경로와 사용자 환경에 맞게 수정해야 합니다.
[Unit]
Description=Clash Meta (Mihomo) user service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory=%h/.config/mihomo
ExecStart=/usr/local/bin/mihomo -d %h/.config/mihomo
Restart=on-failure
RestartSec=3
[Install]
WantedBy=default.target
시스템 유닛과 보안 경계
공용 서버나 게이트웨이 역할을 한다면 /etc/systemd/system/mihomo.service에 두고 User·Group을 전용 계정으로 고정합니다. 전용 계정은 로그인 셸이 필요 없고, 홈 디렉터리는 최소 권한만 부여합니다. CapabilityBoundingSet·AmbientCapabilities·NoNewPrivileges 같은 지시어는 보안 팀 가이드에 맞춰 조정하세요. TUN을 시스템 서비스로 켤 때는 capability 설계가 핵심이며, 불필요한 권한을 넓히지 않는 방향으로 리뷰받는 것이 안전합니다.
방화벽(nftables·ufw)과의 관계도 미리 문서화합니다. TUN이 올라오면 로컬 정책 라우팅과 마크가 바뀌어 관리자가 의도하지 않은 홉으로 트래픽이 새는 것처럼 보일 수 있습니다. 운영 체크리스트에 「재부팅 후 ip rule·ip route show table 스냅샷」을 넣어 두면 장애 대응이 빨라집니다.
Linux에서 TUN이 의미하는 것
TUN은 사용자 공간 프록시가 아니라 커널 라우팅 경로에 가깝게 붙는 모드입니다. 애플리케이션이 시스템 프록시를 무시하더라도, 올바르게 구성되면 패킷이 가상 인터페이스 쪽으로 끌려 와 규칙 엔진을 통과합니다. 다만 그만큼 CAP_NET_ADMIN·라우팅 테이블·DNS 루프 같은 이슈가 표면화됩니다. 개념적 비교는 TUN 모드 가이드를 함께 보면 Windows·macOS와의 차이를 빠르게 정렬할 수 있습니다.
Mihomo에서는 tun.enable: true와 스택(system·gvisor 등) 선택, DNS와의 연계 옵션이 상호 의존합니다. 한 번에 모든 옵션을 켜기보다, 「가상 인터페이스 생성 성공 여부 → 기본 라우트 충돌 여부 → DNS 루프 여부 → 애플리케이션별 예외」 순으로 좁히는 편이 디버깅 비용이 적습니다.
TUN 켜기: capability와 실행 방식
가장 흔한 오류는 권한입니다. 바이너리에 capability를 부여하는 방법은 배포판에 따라 문법이 조금씩 다르지만, 관리자는 setcap으로 cap_net_admin을 선택적으로 열어 줄 수 있습니다. 대안으로 특정 환경에서는 서비스 관리자가 소규모 래퍼를 두기도 합니다. 어떤 방법이든 최소 권한 원칙을 지키고, 왜 그 권한이 필요한지 운영 문서에 한 줄이라도 남깁니다.
데스크톱에서 Polkit·pkexec 흐름을 쓰는 GUI 클라이언트와 달리, 서버용 단일 바이너리는 대개 이 부분을 직접 책임집니다. capability를 주기 어렵다면 초기에는 TUN 대신 mixed 포트와 터미널 환경 변수 조합으로 업무를 나누고, 이후 변경 요청을 정리하는 현실적인 타협도 있습니다.
DNS와 fake-ip 정책 정렬
TUN을 켜면 DNS가 루프에 빠지거나, 로컬 리졸버와 충돌해 「사이트는 뜨는데 특정 CDN만 실패」 같은 증상이 납니다. systemd-resolved를 쓰는 Ubuntu에서는 스텁 리스너와의 관계를 먼저 이해하고, Mihomo의 DNS 모드(redir-host·fake-ip 등)와 매칭시킵니다. 규칙에서 도메인 기반 분기를 쓰는 경우 fake-ip 범위가 넓으면 예상과 다른 경로를 탈 수 있으니, 초기에는 범위를 보수적으로 두고 로그로 확인합니다.
사내 DNS나 분할 DNS를 쓰는 환경에서는 nameserver-policy 류 옵션으로 도메인별 업스트림을 고정하는 편이 안정적입니다. 테스트는 dig·resolvectl 등으로 분리해, 애플리케이션이 실제로 어떤 응답을 보는지 확인하세요.
터미널 프록시 환경 변수와 mixed 포트
TUN이 모든 트래픽을 완벽히 가로채지 못하는 특수 애플리케이션이 있거나, 일부러 프록시 체인을 명시하고 싶다면 http_proxy·HTTPS_PROXY·ALL_PROXY·no_proxy를 셸 프로필에 넣습니다. 값은 Mihomo가 실제로 듣는 mixed 포트와 스킴이 일치해야 합니다. HTTP 프록시로 열어둔 포트를 SOCKS URL로 적어 두는 실수가 잦습니다.
컨테이너·CI·언어별 패키지 매니저는 각자 프록시 설정을 따로 두는 경우가 많습니다. 전역 변수만으로 끝나지 않을 때가 있으므로, 팀 단위로 최소 예제를 문서화해 두면 Linux 온보딩이 빨라집니다. macOS에서의 셸 초기화 이슈는 별도 글에서 다루었지만, Linux에서도 로그인·비로그인 셸 차이는 존재하니 동일한 원칙으로 점검하세요.
GNOME 등 데스크톱 프록시 UI와의 관계
Ubuntu 데스크톱은 GUI에서 시스템 프록시를 설정할 수 있습니다. TUN을 켠 상태에서는 일부 앱이 이미 터널 경로를 타므로 UI 설정이 중복되거나 충돌해 보일 수 있습니다. 일반적으로는 한 가지 방식을 주 경로로 정하고 나머지는 끄는 편이 덜 혼란스럽습니다. 브라우저 확장 프록시와의 이중 적용도 같은 범주의 문제입니다.
원격 데스크톱이나 Wayland·Xorg 차이는 입력 장치와는 별개지만, 네트워크 네임스페이스를 쓰는 개발 도구는 예외적으로 루프백 경로를 탈 수 있습니다. 증상이 특정 IDE 터미널에서만 재현된다면 해당 프로세스 트리를 분리해 보세요.
점검 순서와 흔한 함정
첫째, 재부팅 후 서비스가 inactive면 유닛 의존성과 linger, 혹은 시스템 유닛의 사용자 권한을 의심합니다. 둘째, 포트 충돌로 기동 실패가 나면 ss -lntp로 리스너를 확인합니다. 셋째, TUN 전환 직후 전체 단절이면 라우팅 테이블과 DNS 루프를 우선 봅니다. 넷째, 규칙은 정상인데 속도만 이상하면 노드 품질 이전에 MTU·ECN·BBR 같은 네트워크 스택 옵션을 의심합니다. 다섯째, 스냅 샌드박스나 커스텀 보안 모듈이 가상 인터페이스 생성을 막는 경우가 있어 dmesg/journal을 함께 봅니다.
문제를 좁힌 뒤에는 운영 문서에 「정상 시 스냅샷」을 남겨 다음 장애 때 비교할 수 있게 합니다. 작은 스크립트로 현재 라우팅·DNS 응답·리스너 목록을 수집해 비공개 위키에 붙여 두는 방법이 실무적으로 좋습니다.
정리
Ubuntu에서 Clash Meta(Mihomo)를 안정적으로 쓰려면 「바이너리·구성 디렉터리·실행 사용자」를 먼저 고정하고, systemd로 재부팅 이후에도 같은 커맨드 라인이 재현되게 만드는 것이 첫 관문입니다. 그다음 TUN은 권한·DNS·라우팅이라는 운영 축을 동시에 건드리므로, mixed 포트로 규칙과 노드를 검증한 뒤 단계적으로 켜는 순서가 안전합니다. 마지막으로 터미널 환경 변수와 데스크톱 프록시 UI를 정리해 애플리케이션별 예외를 줄이면, Linux 데스크톱에서도 Windows·macOS와 유사한 체감으로 일일 업무를 맞출 수 있습니다.
장기적으로는 코어 버전과 프로필 스키마를 팀 표준으로 묶어 두면 장애 재현과 업그레이드 비용이 줄어듭니다. 고급 규칙·프로바이더 설계는 문서 허브의 관련 챕터를 함께 참고하세요. GUI 클라이언트가 익숙한 사용자에게도 Linux 서버는 운영 디테일이 다르므로, 이 체크리스트를 그대로 온보딩 자료로 써도 좋습니다.