배포 방식 선택: 서버는 코어, 데스크톱은 필요에 따라 클라이언트 사용

Linux에서 Clash를 실행할 때 그래픽 환경이 꼭 필요한 것은 아닙니다. mihomo는 Clash 설정 체계와 호환되며 프로토콜과 규칙 기능을 확장한 코어입니다. 이전에는 Clash Meta라는 이름으로도 널리 알려졌습니다. 설정을 읽고 프록시 포트를 열어 연결을 처리하는 역할을 합니다. 구독 관리 창, 트레이 아이콘, 제어 패널은 보통 그래픽 클라이언트가 제공합니다.

이 글에서는 독립형 mihomo 바이너리와 시스템 수준의 systemd 서비스를 함께 사용하는 방법을 다룹니다. SSH로 접속하는 서버, 개발 머신, 상시 프록시가 필요한 데스크톱 배포판에 적합합니다. 설정 파일은 /etc/mihomo/config.yaml에, 실행 데이터는 /var/lib/mihomo에 두며 로컬 HTTP/SOCKS 혼합 포트는 7890을 사용합니다.

  • 헤드리스 서버: 명령어와 로그로 관리할 수 있는 이 방법을 우선 사용하세요. 데스크톱 환경을 설치할 필요가 없습니다.
  • 일반 데스크톱: 노드를 자주 바꾸거나 규칙을 편집해야 한다면 그래픽 클라이언트를 사용할 수 있습니다. 클라이언트가 자체 코어를 관리합니다.
  • 이미 클라이언트를 사용 중인 경우: 먼저 클라이언트가 7890 포트를 사용 중인지 확인하세요. 두 코어가 같은 주소와 포트에 동시에 바인딩될 수 없습니다.

시스템 아키텍처 확인 및 mihomo 바이너리 설치

1. systemd와 CPU 아키텍처 확인

ps -p 1 -o comm=
uname -m
command -v curl
command -v gzip

첫 번째 명령의 출력은 systemd여야 합니다. 컨테이너나 최소 구성 시스템처럼 systemd가 없거나 아직 활성화되지 않은 환경에서는 아래의 systemctl 명령을 그대로 사용할 수 없습니다. 해당 환경의 프로세스 관리 방식을 사용하세요.

아키텍처 출력릴리스 파일 선택주의 사항
x86_64Linux amd64에서는 우선 v1 호환 수준을 선택하세요.v1, v2, v3는 CPU 명령어 세트의 호환 수준이며 클라이언트 버전이 아닙니다.
aarch64Linux arm64ARM 클라우드 서버와 64비트 운영체제를 실행하는 개발 보드에서 흔히 사용됩니다.
armv7l기기에 맞는 Linux armv7 파일을 선택하세요.하드웨어와 릴리스 안내를 확인해야 합니다. arm64 파일로 대체할 수 없습니다.

Debian 또는 Ubuntu에 필요한 도구가 없다면 sudo apt update && sudo apt install curl gzip ca-certificates를 실행하세요. Fedora에서는 sudo dnf install curl gzip ca-certificates를 실행합니다. 아래 다운로드 명령은 Bash용입니다.

2. 다운로드 및 설치

mihomo 공식 릴리스 페이지를 열고 안정 버전에서 아키텍처에 맞는 .gz 바이너리 파일을 선택한 다음, 해당 파일의 HTTPS 다운로드 링크 전체를 복사하세요. 릴리스 페이지 주소나 소스 코드 압축 파일을 바이너리 링크로 사용하면 안 됩니다. 아래 입력은 링크를 직접 받아 버전 번호를 고정하지 않습니다.

mkdir -p "$HOME/mihomo-install"
cd "$HOME/mihomo-install"

read -r -p '공식 Linux .gz 파일의 HTTPS 링크를 붙여 넣으세요: ' download_url
curl --fail --location --proto '=https' \
  --output mihomo.gz "$download_url"
unset download_url

gzip -t mihomo.gz
gzip -dc mihomo.gz > mihomo
chmod 0755 mihomo
./mihomo -v

sudo install -m 0755 mihomo /usr/local/bin/mihomo
/usr/local/bin/mihomo -v

각 명령을 차례로 실행하고 성공 여부를 확인한 뒤 다음 단계로 넘어가세요. -v 출력에서 코어 버전과 아키텍처를 확인할 수 있습니다. Exec format error가 표시되면 아키텍처를 잘못 선택했을 가능성이 큽니다. Illegal instruction이 표시되면 CPU 명령어 세트 요구 사항을 확인하세요. amd64 기기라면 호환 수준이 더 낮은 파일을 선택할 수 있습니다.

서버에서 릴리스 사이트에 접속할 수 없다면 작업용 컴퓨터에서 먼저 파일을 다운로드하고 mihomo.gz로 이름을 바꾼 뒤 SFTP로 서버의 설치 디렉터리에 업로드하세요. 그런 다음 gzip -t 단계부터 계속 진행하면 됩니다. 다운로드를 위해 TLS 인증서 검증을 임시로 비활성화하지 마세요.

전용 실행 계정을 만들고 최소 설정으로 리스닝 확인

일반적인 7890 프록시 포트를 실행할 때 코어를 root로 실행할 필요는 없습니다. 전용 시스템 계정을 만들고 설정 파일과 쓰기 가능한 데이터를 분리하면 실수로 인한 영향을 줄일 수 있습니다. 아래 예시는 useradd를 제공하는 일반적인 배포판을 기준으로 합니다. 계정이 이미 있다면 중복 생성하지 말고 먼저 id mihomo로 확인하세요.

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

sudo tee /etc/mihomo/config.yaml > /dev/null <<'YAML'
mixed-port: 7890
allow-lan: false
bind-address: 127.0.0.1
mode: rule
log-level: info
ipv6: false

rules:
  - MATCH,DIRECT
YAML

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는 코어의 실행 데이터 디렉터리를 지정합니다. 상대 경로를 사용하는 데이터 파일, 캐시, provider 파일은 해당 디렉터리를 기준으로 확인하세요. 코어가 항상 현재 터미널 디렉터리에서 설정을 읽는다고 가정하면 안 됩니다. 설정 테스트는 여러 문법 및 참조 오류를 찾을 수 있지만 실제 노드 연결 테스트를 대신하지는 않습니다.

systemd 서비스 작성 및 부팅 시 자동 시작 설정

서비스 파일에는 절대 경로를 사용하고 실행 계정을 고정하세요. 아래 보호 옵션은 로컬 명시적 프록시 구성에 적합합니다. 코어가 데이터 디렉터리에 쓰는 것은 허용하지만 시스템 디렉터리를 임의로 변경하지 못하게 합니다.

sudo tee /etc/systemd/system/mihomo.service > /dev/null <<'UNIT'
[Unit]
Description=mihomo local proxy service
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=mihomo
Group=mihomo
WorkingDirectory=/var/lib/mihomo
ExecStartPre=/usr/local/bin/mihomo -t -d /var/lib/mihomo -f /etc/mihomo/config.yaml
ExecStart=/usr/local/bin/mihomo -d /var/lib/mihomo -f /etc/mihomo/config.yaml
Restart=on-failure
RestartSec=5s
UMask=0027
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ReadWritePaths=/var/lib/mihomo

[Install]
WantedBy=multi-user.target
UNIT

sudo systemctl daemon-reload
sudo systemctl enable --now mihomo.service
systemctl status mihomo.service --no-pager
sudo journalctl -u mihomo.service -n 80 --no-pager
sudo ss -lntp 'sport = :7890'

정상이라면 서비스 상태가 active (running)으로 표시되고 7890 포트가 127.0.0.1에서 리스닝합니다. enable은 부팅 시 자동 시작을 설정하며 --now는 서비스를 즉시 시작합니다. network-online.target이 실제로 대기하는지는 배포판의 네트워크 관리자와 wait-online 서비스에 따라 다르며, 외부 사이트에 반드시 접속할 수 있다는 뜻은 아닙니다.

  • 설정 파일을 수정한 경우: 먼저 앞에서 안내한 mihomo -t를 실행하세요. 테스트를 통과하면 sudo systemctl restart mihomo를 실행합니다.
  • 서비스 파일을 수정한 경우: 먼저 sudo systemctl daemon-reload를 실행한 뒤 서비스를 다시 시작하세요.
  • 실시간 로그 확인: sudo journalctl -u mihomo -f를 실행하세요. Ctrl+C를 누르면 로그 확인만 종료되며 서비스는 계속 실행됩니다.
  • 서비스를 중지하고 부팅 시 자동 시작 해제: sudo systemctl disable --now mihomo를 실행하세요.

이 글에서는 ExecReload를 설정하지 않으므로 systemctl reload mihomo를 일반적인 업데이트 명령으로 사용하면 안 됩니다. 서비스를 재시작하면 해당 프로세스를 통과하는 기존 연결이 잠시 끊깁니다. 원격 작업 중이라면 업데이트 시간을 신중하게 정하세요.

구독 가져오기: 전체 설정과 노드 목록 구분하기

‘구독 주소’에서 항상 같은 형식의 데이터가 내려오는 것은 아닙니다. 전체 Clash/mihomo 설정에는 보통 proxies 또는 proxy-providers, proxy-groups, rules가 포함됩니다. 노드만 담긴 provider YAML, Base64 노드 목록, 단일 공유 링크는 이 글의 기본 설정 파일로 바로 사용할 수 없습니다.

전체 설정 안전하게 교체하기

서비스에서 전체 mihomo 설정을 제공한다면 먼저 임시 파일로 다운로드한 다음 내용을 확인하고 테스트하세요. 아래 명령은 대화형 Bash에서 구독 주소 입력을 숨겨 토큰이 포함된 URL이 명령 기록에 남지 않도록 합니다. 종료 시 임시 파일은 삭제됩니다. 서버 접근 로그와 로컬의 높은 권한을 가진 사용자는 관련 정보를 확인할 수 있으므로 구독 주소를 공개하지 마세요.

(
  umask 077
  tmp=$(mktemp) || exit 1
  trap 'rm -f "$tmp"' EXIT

  read -r -s -p '전체 설정 구독의 HTTPS 주소를 붙여 넣으세요: ' sub_url
  printf '\n'
  curl --fail --location --proto '=https' \
    --output "$tmp" "$sub_url" || exit 1
  unset sub_url

  sudo install -o root -g mihomo -m 0640 \
    "$tmp" /etc/mihomo/config.next.yaml || exit 1
  sudoedit /etc/mihomo/config.next.yaml

  sudo -u mihomo /usr/local/bin/mihomo -t \
    -d /var/lib/mihomo \
    -f /etc/mihomo/config.next.yaml || exit 1

  sudo cp -p /etc/mihomo/config.yaml /etc/mihomo/config.previous.yaml || exit 1
  sudo mv /etc/mihomo/config.next.yaml /etc/mihomo/config.yaml || exit 1
  sudo systemctl restart mihomo
)

편집기에서 mixed-port: 7890, allow-lan: false, bind-address: 127.0.0.1인지 확인하세요. 외부 제어 인터페이스, DNS 리스닝, TUN 활성화 여부와 로컬 파일 경로도 점검해야 합니다. 이 구성에는 외부 제어 인터페이스나 DNS 리스닝이 필요하지 않으며 TUN도 사용하지 않습니다. 불필요한 설정을 삭제하거나 비활성화한 뒤 테스트하세요.

규칙에서 참조하는 정책 그룹이 실제로 존재해야 하며 그룹에 포함된 노드도 모두 확인할 수 있어야 합니다. 규칙 데이터베이스나 provider 파일 다운로드에 실패하면 로그에 표시된 URL과 오류 내용을 확인하세요. YAML 구문 분석에 성공했다는 이유만으로 구독을 사용할 수 있다고 판단하면 안 됩니다. 설정에서 사용자 홈 디렉터리의 파일을 읽도록 되어 있으면 이 서비스의 ProtectHome=true가 접근을 차단합니다. 필요한 파일을 데이터 디렉터리로 옮기고 경로를 수정하세요.

노드 provider와 자동 업데이트 범위

proxy-providers는 자체 url, path, interval 설정으로 노드를 업데이트할 수 있습니다. 예를 들어 interval: 3600은 3600초 간격을 의미합니다. 업데이트되는 대상은 해당 provider이며 기본 설정의 모든 규칙과 정책 그룹이 자동으로 바뀌지는 않습니다. provider의 상대 저장 경로는 쓰기 가능한 데이터 디렉터리 안에 두세요.

전체 기본 설정을 주기적으로 업데이트하려면 다운로드, 구문 테스트, 백업, 교체, 실패 시 복구 절차를 별도로 설계하고 systemd timer로 예약해야 합니다. 예약 다운로드 명령 하나로 사용 중인 config.yaml을 바로 덮어쓰지 마세요. 구독을 가져오지 못했을 때는 빈 파일로 재시작하는 것보다 이전의 정상 설정을 보존하는 편이 안전합니다.

터미널 프록시 변수 설정 및 HTTP·SOCKS 연결 테스트

systemd 서비스가 정상적으로 시작되었다는 것은 코어가 실행 중이라는 뜻일 뿐, 모든 터미널 프로그램이 자동으로 프록시를 사용한다는 뜻은 아닙니다. 환경 변수의 영향을 배제할 수 있도록 먼저 명시적 옵션을 사용해 테스트하세요. 아래 요청은 연결 확인을 위한 공개 사이트 예시이며 실제로 테스트한 결과가 아닙니다. 응답 시간과 외부 IP는 네트워크, 규칙, 노드에 따라 달라집니다.

curl --noproxy "" --proxy http://127.0.0.1:7890 \
  --connect-timeout 10 --max-time 30 \
  -I https://www.kernel.org/

curl --noproxy "" --proxy socks5h://127.0.0.1:7890 \
  --connect-timeout 10 --max-time 30 \
  -I https://www.kernel.org/

socks5h를 사용하면 curl이 대상 도메인 조회를 SOCKS 프록시에 맡깁니다. socks5는 일반적으로 애플리케이션에서 먼저 도메인을 조회합니다. HTTP 프록시로 HTTPS 사이트에 접속할 때는 보통 CONNECT 터널을 사용하므로 프록시 주소는 http://127.0.0.1:7890으로 지정합니다. 프록시 주소를 HTTPS로 바꾸는 것이 아닙니다.

현재 터미널에서만 활성화

export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
export all_proxy=socks5h://127.0.0.1:7890
export no_proxy=localhost,127.0.0.1,::1

curl --connect-timeout 10 --max-time 30 -I https://www.kernel.org/

환경 변수는 현재 셸에서 이후 실행하는 하위 프로세스에만 전달됩니다. 이미 실행 중인 앱에는 영향을 주지 않으며 다른 systemd 서비스에 자동으로 적용되지도 않습니다. 프로그램마다 변수 이름의 대소문자와 우선순위 지원이 다릅니다. curl에서 HTTP 프록시를 사용하려면 소문자인 http_proxy를 지정하세요. 계속 적용하려면 현재 사용자의 ~/.bashrc나 해당 셸 설정 파일에 위 설정을 추가할 수 있습니다. 다만 프록시 서비스가 중지되면 관련 명령도 실패할 수 있습니다.

sudo는 기본 설정에서 프록시 변수를 자주 제거합니다. 일반 사용자로 테스트에 성공했다고 해서 모든 관리자 명령에도 프록시가 설정된 것은 아닙니다. 다른 systemd 서비스에서 프록시가 필요하면 해당 서비스의 drop-in 파일에 Environment=를 설정하고, 애플리케이션이 실제로 해당 변수를 지원하는지 확인하세요.

직접 연결 환경으로 되돌리기

unset http_proxy https_proxy all_proxy no_proxy
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY NO_PROXY

git config --global --get http.proxy

Git에는 별도의 전역 프록시 설정이 있을 수 있습니다. 마지막 명령은 설정 확인용입니다. 기존 설정이 더 이상 필요하지 않다는 점을 확인한 뒤 git config --global --unset http.proxy를 실행하세요. 환경 변수만 지워서는 애플리케이션 자체에 저장된 프록시 설정이 삭제되지 않습니다.

서비스는 실행되지만 인터넷에 연결되지 않을 때: 4단계 점검

  1. 프로세스: systemctl status mihomo를 실행하세요. 서비스가 계속 재시작된다면 마지막의 ‘재시작 횟수 초과’ 문구만 보지 말고 journalctl에서 처음 종료되기 직전의 오류를 확인하세요.
  2. 리스닝: sudo ss -lntp 'sport = :7890'을 실행하세요. 포트가 리스닝하지 않으면 시작 실패나 포트 설정 오류일 가능성이 큽니다. address already in use가 표시되면 다른 클라이언트나 수동으로 실행한 코어가 있는지 확인하세요.
  3. 프록시: --proxy를 지정한 curl 요청으로 테스트하세요. 연결이 거부되면 로컬 포트를 먼저 확인하고, 연결 핸드셰이크가 시간 초과되면 노드, 서버의 외부 연결 제한, 프로토콜 호환성을 점검하세요.
  4. 규칙: 로그에서 일치한 규칙과 선택된 정책을 확인하세요. HTTP 요청이 성공했다는 것은 요청이 완료되었다는 뜻일 뿐입니다. 규칙이 여전히 MATCH,DIRECT라면 프록시 노드가 작동한다는 증거가 아닙니다.

설정 테스트에서 permission denied가 발생하면 /etc/mihomo의 디렉터리 실행 권한과 파일 그룹, provider가 읽기 전용 경로에 저장되는지 확인하세요. systemd에서 start-limit-hit가 표시되면 먼저 근본 원인을 해결한 뒤 sudo systemctl reset-failed mihomo와 sudo systemctl start mihomo를 실행하세요.

원격 SSH 세션에서 127.0.0.1은 작업용 컴퓨터가 아니라 서버 자신을 가리킵니다. 이 구성에서는 클라우드 보안 그룹에서 7890 포트를 열 필요가 없습니다. 작업용 컴퓨터에서 서버 프록시를 잠시 사용하려면 컴퓨터에서 ssh -N -L 17890:127.0.0.1:7890 서버 로그인 대상을 실행하세요. 마지막 항목은 평소 사용하는 SSH 로그인 대상으로 바꾸면 됩니다. 그런 다음 컴퓨터의 애플리케이션 프록시를 127.0.0.1:17890으로 설정하세요.

데스크톱 배포판과 TUN: 두 가지 트래픽 처리 방식을 혼용하지 마세요

GNOME 데스크톱에서는 ‘설정’ → ‘네트워크’ → ‘네트워크 프록시’에서 수동 설정을 선택하고 HTTP 및 HTTPS 프록시 호스트를 127.0.0.1, 포트를 7890으로 설정할 수 있습니다. 메뉴 이름은 배포판에 따라 조금 다를 수 있습니다. 데스크톱 프록시 설정은 해당 설정을 따르는 앱에만 적용되므로 터미널, 게임, 백그라운드 서비스까지 모두 프록시를 사용한다고 보장할 수 없습니다.

구독과 노드를 그래픽 클라이언트에서 관리하려면 먼저 이 글의 독립 서비스를 중지한 다음 클라이언트가 자체 코어를 실행하도록 하세요. 포트, 설정 출처, 로그 확인 경로가 각각 하나로 정리되어 문제를 더 쉽게 찾을 수 있습니다. ‘그래픽 클라이언트의 시스템 프록시 스위치’와 ‘systemd 코어 서비스 실행’은 서로 다른 기능이며 대체할 수 없습니다.

TUN을 고려할 시점

  • 대상 애플리케이션이 명시적 프록시를 지원하지 않거나 더 많은 트래픽을 처리해야 할 때 TUN 사용을 검토하세요.
  • 먼저 /dev/net/tun이 있는지, 컨테이너나 호스트에서 가상 네트워크 인터페이스를 만들 수 있는지 확인하세요.
  • 이 글의 비특권 서비스에는 네트워크 인터페이스와 라우팅을 설정하는 데 필요한 권한이 부여되지 않았습니다. tun.enable만 추가해서는 충분하지 않습니다.
  • Linux capabilities를 사용하려면 CAP_NET_ADMIN 등의 권한이 실제 기능에 필요한지 검토하고 systemd 제한도 함께 확인하세요. 보호 설정을 모두 해제하지 마세요.
  • 자동 라우팅, 정책 라우팅, DNS 가로채기를 함께 검증하세요. 원격 서버의 네트워크를 변경하기 전에 SSH 세션을 하나 더 열어 두고 클라우드 콘솔에도 접속할 수 있는지 확인하세요.

배포가 완료되려면 설정 테스트 통과, 부팅 시 서비스 자동 시작, 7890의 로컬 바인딩, 명시적 프록시 요청 성공, 로그에서 예상한 정책을 통한 연결 확인까지 모두 충족해야 합니다. 이 흐름을 먼저 완성한 뒤 자동 업데이트나 TUN을 추가하면 문제를 더 쉽게 찾을 수 있습니다.