· 플랫폼 배포 · 예상 읽는 시간 13분
Ubuntu mihomo 설치 및 설정: 데스크톱 클라이언트와 systemd 서버 배포
Ubuntu 데스크톱 클라이언트 설치부터 서버의 mihomo systemd 배포까지 안내합니다. 바이너리 설치, config.yaml 경로, 서비스 파일, TUN 권한 설정을 다룹니다.
Ubuntu 배포 방식 선택: 데스크톱 클라이언트 또는 독립 커널
mihomo는 YAML 설정을 읽고 프록시 규칙을 적용해 연결을 처리하는 커널로, Clash Meta라고도 불립니다. 데스크톱 클라이언트는 커널에 구독 관리, 정책 그룹 전환, 시스템 프록시 및 로그 화면을 더해 제공합니다. mihomo 바이너리만 설치하면 그래픽 창이 나타나지 않으며 Ubuntu 데스크톱의 네트워크 프록시도 자동으로 변경되지 않습니다.
아래 명령은 Ubuntu 22.04 LTS 및 24.04 LTS에서 흔히 사용하는 systemd 환경을 기준으로 작성했습니다. 컨테이너, WSL, 권한이 제한된 VPS에서는 장치 권한이 다를 수 있으므로 특히 TUN 지원 여부를 별도로 확인해야 합니다. 이 문서에서는 커널 버전을 특정하지 않습니다. 배포 시 mihomo -v로 실제 버전을 기록하고, 설정 호환성 문제를 확인할 수 있도록 업그레이드 후에도 버전 정보를 보관하세요.
| 사용 환경 | 권장 방식 | 관리할 항목 |
|---|---|---|
| GNOME 데스크톱에서 일상적으로 사용 | 그래픽 클라이언트 | 구독, 시스템 프록시, 클라이언트 서비스 모드 |
| 데스크톱 환경이 없는 Ubuntu 서버 | mihomo와 systemd | 설정 파일, 서비스 계정, 로그, 시작 순서 |
| 일회성 터미널 작업 | 로컬 프록시 포트 | 명령별로 프록시를 지정하면 TUN을 켤 필요가 없습니다 |
한 대의 컴퓨터에서는 한 번에 한 가지 방식만 실행하세요. 데스크톱 클라이언트에 내장된 커널과 별도의 systemd 서비스를 함께 시작하면
7890포트를 두고 충돌하거나 TUN 경로가 중복으로 생성될 수 있습니다.
Ubuntu 데스크톱 클라이언트 설치 및 설정 가져오기
아키텍처와 설치 패키지 형식 확인
먼저 터미널에서 다음 명령을 실행하세요. x86_64는 일반적으로 amd64 패키지, aarch64는 arm64 패키지에 해당합니다. 기기 브랜드만 보고 아키텍처를 판단하지 마세요.
uname -m
dpkg --print-architecture
lsb_release -ds
클라이언트 다운로드 페이지에서 Linux 빌드를 제공하는 클라이언트(예: Clash Verge Rev)를 선택하고 현재 Ubuntu 버전의 의존성을 확인하세요. Ubuntu에서는 해당 아키텍처용 .deb 패키지를 우선 고려하세요. 다운로드 디렉터리에서 실제 파일명을 붙여 sudo apt install ./을 실행하면 됩니다. Tab 키로 파일명을 자동 완성할 수 있으며, apt가 필요한 소프트웨어 의존성을 처리합니다. AppImage는 별도의 배포 형식입니다. FUSE 호환 패키지가 필요한지는 해당 클라이언트의 릴리스 안내를 확인하고, Ubuntu 버전이 다른 환경에 같은 의존성 설치 명령을 그대로 적용하지 마세요.
구독, 시스템 프록시 및 브라우저 연결 확인
- 클라이언트의 설정 또는 구독 화면에서 신뢰할 수 있는 구독 URL이나 로컬 YAML 파일을 가져오세요. 구독 링크에는 로그인 정보가 포함되는 경우가 많으므로 공개 스크린샷, 지원 티켓 또는 Git 저장소에 올리지 마세요.
- 가져온 설정을 선택하고 프록시 그룹에서 사용할 노드를 고른 다음 Rule(규칙) 모드로 시작하세요. 규칙 모드는 규칙 순서에 따라 트래픽의 출구를 선택하며, 모든 트래픽을 프록시로 보내는 방식은 아닙니다.
- 클라이언트 설정에서 실제 HTTP 또는 mixed-port 포트를 확인한 뒤 시스템 프록시를 켜세요. 포트는 클라이언트 설정에 따라 달라질 수 있으므로 구독 파일에 적힌 값만 확인해서는 안 됩니다.
- 브라우저에서 대상 사이트에 접속한 다음 클라이언트 연결 기록에서 적용된 규칙, 정책 그룹 및 출구를 확인하세요.
GNOME 프록시를 직접 설정하려면 Ubuntu의 「설정」→「네트워크」→「네트워크 프록시」에서 수동 방식을 선택하세요. 로컬 mixed-port가 7890이라고 가정하면 HTTP와 HTTPS 프록시 호스트에 모두 127.0.0.1, 포트에 모두 7890을 입력합니다. 여기서 HTTPS 프록시 항목은 HTTPS 요청이 사용할 프록시 주소를 뜻하며, 로컬 포트 자체가 TLS를 제공해야 한다는 의미는 아닙니다.
데스크톱 시스템 프록시는 해당 설정을 따르는 프로그램에만 적용됩니다. 터미널 도구, 컨테이너 및 일부 앱은 GNOME 프록시 설정을 자동으로 사용하지 않습니다. 클라이언트의 설정 디렉터리가 반드시 ~/.config/mihomo인 것도 아닙니다. 클라이언트의 「설정 디렉터리 열기」 기능을 먼저 사용하고 원본 구독, 병합 템플릿, 실행 중인 설정을 구분하세요. 다음 구독 업데이트 때 덮어써질 파일을 수정하지 않도록 주의해야 합니다.
명령줄 배포: 바이너리 및 디렉터리 권한
서버에서는 실행 파일을 /usr/local/bin/mihomo에, 설정을 /etc/mihomo/config.yaml에, 실행 데이터를 /var/lib/mihomo에 둡니다. 이렇게 분리하면 쓰기 권한을 제한하기 쉽고, 로그인한 사용자에 따라 서비스의 작업 디렉터리가 바뀌는 문제도 방지할 수 있습니다.
커널 설치 및 서비스 계정 생성
CPU 아키텍처에 맞는 공식 릴리스 바이너리를 준비하세요. gzip 압축 파일을 받았다면 먼저 압축을 풀어야 합니다. 아래 절차에서는 압축을 푼 파일을 /tmp/mihomo에 두었다고 가정합니다. 이 파일은 실행 가능한 바이너리여야 하며, 압축 파일이나 다운로드 실패 후 저장된 HTML 페이지여서는 안 됩니다. 오래된 CPU에서 호환되지 않는 명령어 세트용 빌드를 강제로 사용하지 마세요.
file /tmp/mihomo
sudo install -m 0755 /tmp/mihomo /usr/local/bin/mihomo
/usr/local/bin/mihomo -v
sudo useradd --system --user-group \
--home-dir /var/lib/mihomo \
--shell /usr/sbin/nologin mihomo
sudo install -d -o root -g mihomo -m 0750 /etc/mihomo
sudo install -d -o mihomo -g mihomo -m 0750 /var/lib/mihomo
계정 생성 명령은 한 번만 실행하면 됩니다. 같은 이름의 계정이 이미 있다면 기존 서비스의 실행 계정을 임의로 변경하지 말고 먼저 id mihomo로 용도를 확인하세요. 설정 파일은 root 소유로 두고 mihomo 그룹에 읽기 권한을 부여합니다. 실행 데이터 디렉터리는 캐시와 규칙, 데이터베이스 등 필요한 파일을 저장할 수 있도록 서비스 계정에 쓰기 권한을 허용합니다.
실행 가능한 최소 설정 작성
sudoedit /etc/mihomo/config.yaml을 실행해 아래 내용을 입력하세요. 이 설정은 로컬 리스닝과 규칙 처리를 확인하기 위한 것으로, 모든 연결이 DIRECT로 직접 연결되며 원격 프록시 기능은 제공하지 않습니다. 실제 사용 시에는 신뢰할 수 있는 완전한 설정으로 교체하고 실제 노드, 정책 그룹 및 규칙을 포함하세요. 구독 URL만 붙여 넣어서는 안 됩니다.
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
ipv6: false
rules:
- MATCH,DIRECT
sudo chown root:mihomo /etc/mihomo/config.yaml
sudo chmod 0640 /etc/mihomo/config.yaml
sudo -u mihomo /usr/local/bin/mihomo \
-t -d /var/lib/mihomo -f /etc/mihomo/config.yaml
-f는 설정 파일을 명시하고, -d는 실행 데이터 디렉터리를 지정하며, -t는 설정을 검사합니다. 검사를 통과하면 현재 커널이 설정을 읽을 수 있다는 뜻이지, 노드에 연결할 수 있거나 규칙이 예상대로 작동한다는 뜻은 아닙니다. 외부 규칙 세트, Geo 데이터 또는 로컬 파일을 참조하는 설정이라면 경로와 다운로드 조건, 서비스 계정의 읽기 권한도 확인해야 합니다.
systemd 서비스 파일 및 부팅 시 자동 시작
sudoedit /etc/systemd/system/mihomo.service를 실행해 서비스를 생성하세요. 아래 설정은 네트워크 장치 생성 권한을 부여하지 않는 일반 로컬 프록시 모드입니다. 별도의 계정으로 실행하면 7890과 같은 비특권 포트를 열기 위해 root를 사용할 필요가 없습니다.
[Unit]
Description=mihomo proxy core
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=mihomo
Group=mihomo
WorkingDirectory=/var/lib/mihomo
ExecStart=/usr/local/bin/mihomo -d /var/lib/mihomo -f /etc/mihomo/config.yaml
Restart=on-failure
RestartSec=5s
UMask=0027
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/mihomo
[Install]
WantedBy=multi-user.target
ProtectSystem=strict는 서비스의 파일 시스템 쓰기를 제한하며, 선언한 실행 데이터 디렉터리에만 쓰기 권한을 남깁니다. 계속 업데이트해야 하는 provider 파일을 /etc/mihomo에 두지 마세요. 설정에서 /var/lib/mihomo 아래의 경로를 사용할 수 있습니다. network-online.target이 실제로 얼마나 기다리는지는 시스템의 네트워크 관리 서비스에 따라 다르며, 외부 구독 서버에 연결할 수 있다는 보장은 없습니다.
sudo systemctl daemon-reload
sudo systemctl enable --now mihomo
systemctl status mihomo --no-pager
sudo journalctl -u mihomo -b -n 80 --no-pager
sudo ss -lntp 'sport = :7890'
정상적으로 실행되면 서비스 상태는 active (running)이어야 하며 로컬 프록시가 리스닝 중이어야 합니다. 로그에 address already in use가 표시되면 먼저 해당 포트를 사용 중인 데스크톱 클라이언트나 이전 프로세스를 찾으세요. 강제 종료 명령을 먼저 실행하거나 모든 네트워크 인터페이스에서 리스닝하도록 설정을 바꿔 문제를 해결하려 하지 마세요.
터미널에서 연결 확인 및 설정 업데이트
curl --proxy http://127.0.0.1:7890 \
--connect-timeout 10 --max-time 20 \
-I https://example.com/
이 명령은 프록시 주소를 직접 지정해 프로그램이 프록시를 사용하지 않는 문제와 프록시 커널의 처리 오류를 구분하는 데 유용합니다. 이 문서의 최소 설정을 사용하면 요청은 여전히 로컬에서 대상 사이트로 직접 연결됩니다. 실제 설정으로 바꾼 뒤에는 로그에서 출구를 확인하고, HTTP 응답 코드만으로 노드가 적용되었는지 판단하지 마세요.
YAML을 수정한 뒤 먼저 -t를 포함한 검사 명령을 다시 실행하고, 이어서 sudo systemctl restart mihomo를 실행하세요. 이 서비스에는 ExecReload가 설정되어 있지 않으므로 systemctl reload가 동작한다고 가정하면 안 됩니다. unit 또는 drop-in을 수정한 경우에만 daemon-reload도 실행해야 합니다. 재시작하면 기존 연결이 끊길 수 있으므로 서버에서는 적절한 시간을 선택하세요.
TUN 모드: 장치, 권한 및 DNS 처리
TUN은 가상 네트워크 인터페이스를 사용하며 시스템 프록시를 따르지 않는 앱의 트래픽을 처리하는 데 적합합니다. 일반 HTTP 프록시 포트를 다른 이름으로 부르는 것이 아니며, Ubuntu 서버를 자동으로 로컬 네트워크 게이트웨이로 만들지도 않습니다. 게이트웨이로 트래픽을 전달하려면 IP 포워딩, 방화벽 및 다른 장치의 라우팅 설정도 필요합니다. 이는 이 서버 자체의 트래픽을 처리하는 설정과는 별개입니다.
TUN 장치 사용 가능 여부 확인
ls -l /dev/net/tun
sudo modprobe tun
장치가 없고 모듈 로드에도 실패한다면 호스트가 TUN을 지원하는지 확인하세요. 컨테이너에서는 호스트가 장치를 전달하고 네트워크 관리 권한을 부여해야 하는 경우가 많습니다. 서비스 권한을 올리는 대신 /dev/net/tun을 모든 사용자가 쓸 수 있도록 변경하지 마세요.
root가 아닌 서비스에 네트워크 권한 부여
sudo systemctl edit mihomo를 실행하고 아래 drop-in 내용을 입력하세요. CAP_NET_ADMIN은 네트워크 인터페이스와 라우팅을 관리하고, CAP_NET_RAW는 관련 raw 소켓 작업을 지원합니다. 이 권한은 TUN이 실제로 필요한 서비스에만 부여하세요.
[Service]
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW
여기서는 systemd가 프로세스 시작 시 권한을 부여하므로 바이너리에 setcap을 실행할 필요가 없습니다. 이 문서의 기본 unit은 PrivateDevices=true를 활성화하지 않습니다. 직접 장치 격리나 장치 접근 허용 목록을 추가하는 경우 서비스가 계속 /dev/net/tun에 접근할 수 있는지 확인하세요.
TUN 및 DNS 설정 병합
기존 YAML의 최상위 수준에 다음 항목을 추가하세요. 이미 dns 또는 tun 항목이 있다면 기존 섹션에 병합해야 하며 같은 최상위 키를 중복 정의하면 안 됩니다. 이 DNS 설정은 로컬 1053 포트에서 리스닝해 Ubuntu에서 흔히 사용하는 systemd-resolved 로컬 DNS 주소를 직접 점유하지 않습니다.
dns:
enable: true
listen: 127.0.0.1:1053
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
nameserver:
- 1.1.1.1
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
auto-route는 경로 자동 설정을 요청하고, auto-detect-interface는 출구 인터페이스를 자동으로 찾습니다. DNS 예시에는 공용 DNS 주소를 사용했으므로 실제 네트워크에서 연결 가능한지 확인해 조정하세요. 모든 네트워크에서 그대로 쓸 수 있는 고정값은 아닙니다. fake-ip는 커널이 매핑에 사용하는 가상 주소를 반환하며 대상 사이트의 실제 주소가 아닙니다.
dns-hijack는 해당 TUN 경로로 들어오는 53번 포트 DNS 요청을 처리하지만, 앱에 내장된 DoH 암호화 DNS를 자동으로 감지해 가로채지는 않습니다. dns.enable만 활성화해도 시스템의 모든 DNS 요청이 커널을 거치는 것은 아닙니다. 문제 해결을 위해 /etc/resolv.conf를 삭제하거나 시스템 DNS 서비스를 중지하지 마세요. 먼저 실제 DNS 및 라우팅 경로를 확인해야 합니다.
sudo -u mihomo /usr/local/bin/mihomo \
-t -d /var/lib/mihomo -f /etc/mihomo/config.yaml
sudo systemctl daemon-reload
sudo systemctl restart mihomo
sudo journalctl -u mihomo -b -n 100 --no-pager
ip link show
ip rule show
resolvectl status
SSH로 원격 서버를 관리하는 중에는 자동 라우팅이 관리 연결에 영향을 줄 수 있습니다. TUN을 켜기 전에 클라우드 콘솔이나 다른 대역 외 접속 경로를 확보하고, 기존 설정을 백업한 뒤 서비스를 중지하는 방법을 확인하세요. 데스크톱 클라이언트 TUN, 독립 커널 TUN 및 다른 VPN의 기본 경로를 동시에 설정하지 마세요.
자주 발생하는 문제와 유지 관리 순서
시작 실패: 파일 문제와 네트워크 문제 구분
- Exec format error: 아키텍처가 맞지 않거나 압축 파일을 바이너리처럼 실행한 경우가 많습니다.
file출력과uname -m을 다시 확인하세요. - Permission denied: 설정 파일과 상위 디렉터리의 접근 권한을 확인하세요. 로그인한 사용자로 실행에 성공해도
mihomo서비스 계정이 파일을 읽을 수 있다는 뜻은 아닙니다. - 설정은 읽히지만 규칙 세트 로드 실패: provider 경로와 네트워크 연결, 데이터 디렉터리의 쓰기 권한을 확인하세요.
ProtectHome=true를 사용하는 경우 개인 홈 디렉터리에 있는 구독 파일을 참조하면 안 됩니다. - TUN operation not permitted: 장치가 존재하는지, drop-in이 적용되었는지, 실행 환경에서 네트워크 관리 권한을 허용하는지 순서대로 확인하세요.
systemctl cat mihomo로 병합된 unit 내용을 볼 수 있습니다.
브라우저는 되지만 터미널이나 컨테이너에서는 연결되지 않음
대부분 커널 시작 문제가 아니라 앱마다 프록시를 가져오는 방식이 달라서 발생합니다. 해당 도구가 환경 변수를 지원한다면 터미널에서 한 번의 명령에 HTTPS_PROXY=http://127.0.0.1:7890을 지정할 수 있습니다. 명시적으로 확인하려면 curl --proxy를 사용하세요. 컨테이너 안의 127.0.0.1은 Ubuntu 호스트가 아니라 컨테이너 자체를 가리키므로 접근 가능한 주소와 접근 제어를 별도로 설계해야 합니다.
기본값은 allow-lan: false로 유지하고, 그래픽 패널을 위해 제어 API를 인터넷에 직접 노출하지 마세요. 원격 관리가 꼭 필요하다면 인증된 접근 방식과 제한된 네트워크 경로를 사용하고 방화벽 설정을 확인하세요. HTTP 프록시 포트와 제어 API 포트는 용도가 다르므로 서로 대체할 수 없습니다.
서비스 업그레이드 및 중지
업그레이드 전에 현재 바이너리와 설정을 복구할 수 있도록 백업하세요. 서비스를 중지한 다음 실행 파일을 교체하고 새 버전 정보를 확인한 뒤 설정 검사와 실행 검증을 진행합니다. 로그에는 대상 도메인과 연결 정보가 포함될 수 있으므로 공유 전에 구독 정보와 민감한 내용을 삭제하세요.
sudo systemctl stop mihomo
sudo systemctl disable mihomo
systemctl is-enabled mihomo
마지막 명령이 disabled를 반환하면 부팅 시 자동 시작이 해제된 것이며 설정 파일이 삭제된 것은 아닙니다. GNOME 수동 프록시나 터미널 프록시 환경 변수를 설정했다면 함께 해제해야 합니다. 그렇지 않으면 앱이 중지된 127.0.0.1:7890에 계속 연결을 시도합니다. 데스크톱에서는 클라이언트가 시스템 연동을 관리하도록 하고, 서버에서는 프록시 모드를 반복해서 바꾸기보다 파일 경로와 서비스 계정, 라우팅 범위를 명확히 해야 문제를 찾기 쉽습니다.