quickchr
QEMU를 통해 MikroTik CHR 가상 머신을 다운로드, 실행 및 관리하는 CLI 및 라이브러리입니다.
빠른 시작 (Quick Start)
필수 조건 (Prerequisites)
- Bun 런타임, 1.4.3 이상 버전
- QEMU (https://www.qemu.org)와
qemu-system-x86_64 및/또는 qemu-system-aarch64
- 기본 qcow2 생성을 위한
qemu-img, 설정 마법사, 디스크 크기 조정, 추가 디스크 및 스냅샷 기능용
- arm64 CHR을 위한 UEFI 펌웨어 (edk2)
QEMU 설치:
# Windows — QEMU 설치 (qemu-img 포함)
winget install SoftwareFreedomConservancy.QEMU
...
KVM이 없는 Claude Code cloud 세션 또는 다른 프록시된 샌드박스에서 실행하는 경우, 네트워크 액세스와 필요한 설정 스크립트는 MANUAL.md → Claude Code cloud sessions를 참조하세요.
설치 (Install)
CLI:
bun install -g @tikoci/quickchr
quickchr doctor
라이브러리:
프리릴리즈 QA (Prerelease QA) (0.5.1)
0.5.1 버전은 먼저 npm next에 게시됩니다. 위의 비정규화된 설치는 latest를 사용하며, QA가 통과하면 0.5.1이 해당 위치로 승격됩니다. 재현 가능한 CLI 또는 라이브러리 QA를 위해 이 배포된 후보 버전을 고정하려면 다음을 사용하세요:
나중에 나올 후보 버전을 따라가려면 @0.5.1 대신 @next를 사용하세요. 0.5.0 이후의 변경 사항(스토리지 승인, 캐시 계정 및 디스크 보존 수정 포함)은 0.5.1 변경 로그에서 확인하십시오. 0.4.x에서의 마이그레이션 내용은 0.5.0 노트에 설명되어 있습니다.
CLI 사용법 (CLI Usage)
가장 쉽게 시작하는 방법은 대화형 마법사(interactive wizard)를 사용하는 것입니다. 이 마법사는 모든 옵션을 안내하고 CHR을 자동으로 시작해 줍니다. qemu-img가 필요하며, 누락된 도구를 보고한 후 프롬프트를 제공하거나 다운로드합니다:
quickchr setup wizard walkthrough
또는 TTY에서 인자 없이 quickchr를 실행하여 동일한 마법사(wizard)를 자동으로 얻을 수 있습니다. 모든 마법사 프롬프트에 대한 단계별 분석은 MANUAL.md §3 setup를 참조하십시오.
모든 마법사 옵션은 스크립팅을 위한 플래그로도 사용할 수 있습니다:
quickchr add --name my-chr --channel stable --arch arm64
...
quickchr stop <이름>은 QEMU를 종료(전원 차단)합니다. 명시적인 게스트 종료 요청을 하려면 quickchr shutdown <이름> [--timeout <초>]를 사용하십시오 (기본값 10초, 또는 QUICKCHR_SHUTDOWN_TIMEOUT). 이는 QEMU가 종료되기를 기다리며, 만약 게스트가 유예 시간 내에 중지되지 않으면 강제 전원 차단을 명확하게 보고합니다.
생성 / 시작 옵션
| 플래그 | 설명 | 기본값 |
|---|
--version <버전> | RouterOS 버전 (예: 7.22.1) | 최신 안정화 버전 |
| ... | | |
RouterOS 프로비저닝 지원 정책
quickchr는 부팅 전용(boot-only) 머신 관리와 **부팅 후 프로비저닝(post-boot provisioning)**을 분리합니다.
- 부팅 전용 / QEMU 로컬 기능은 구형 RouterOS 7.x 빌드에서 작동합니다: 이미지 다운로드, 부팅/시작, 디스크 크기 조정(disk resize), 추가 디스크, 네트워크 연결, 포트 매핑 등이 포함됩니다.
- 부팅 후 프로비저닝은 RouterOS 7.20.8 이상에서만 검증/테스트됩니다: 패키지 설치(package install), 관리 로그인 또는 사용자 지정 사용자 생성, admin 비활성화, CHR 라이선스 작업, 장치 모드 변경 등이 포함됩니다.
- 이것은 quickchr 지원 정책이며, 구형 버전이 절대 작동할 수 없다는 RouterOS의 주장이 아닙니다. 테스트에서 다루지 않는 버전별 프로비저닝 함정을 피하기 위해 의도적으로 첫 번째 장기 기준선(long-term baseline)에 멈춥니다.
- 프로비저닝을 계획하고 있다면,
--channel long-term 또는 명시적인 버전 **>= 7.20.8**를 선호하십시오.
| 기능 | 최소 RouterOS 버전 | 참고 사항 |
|---|
| 부팅 / 시작 / 중지 | 모든 RouterOS 7.x; x86의 경우 RouterOS 6 (최선 노력) | 부팅 전용 경로입니다. 부팅 후 RouterOS 변경은 없습니다. 6.x는 REST가 없으며, 준비 상태 확인(readiness)은 네이티브 API 로그인이 필요하고 프로비저닝은 거부됩니다 — 매뉴얼 "RouterOS 6 (boot-only)"를 참조하십시오. |
| ... | | |
백그라운드 모드 대 포그라운드 모드 (Background vs Foreground Mode)
기본적으로 quickchr start는 QEMU를 백그라운드에서 실행합니다: QEMU가 분리된 프로세스(detached process)로 생성되며, CHR이 부팅을 완료하면 명령은 반환됩니다. 관리하려면 quickchr list, quickchr status, 그리고 quickchr stop을 사용하십시오.
quickchr start --channel stable
...
포그라운드(foreground) 모드에서는 터미널 자체가 CHR의 시리얼 콘솔이 됩니다. 다음 키 시퀀스를 사용하십시오:
| 키 | 동작 |
|---|
Ctrl-A X | QEMU를 종료하고 셸로 돌아갑니다 |
| ... | |
참고: 백그라운드 QEMU 프로세스는 진정한 OS 레벨의 고아 프로세스입니다 — quickchr는 셸 작업 제어(&)를 사용하지 않습니다. 명령이 반환된 후 터미널을 닫아도 QEMU는 계속 실행됩니다. quickchr stop <name>은 전원 차단(power cut)으로 종료하며, quickchr shutdown <name>은 게스트에게 먼저 종료하도록 요청하고, 그래도 시간이 내에 종료되지 않으면 전원 차단을 사용합니다.
디스크 지원 (Disk Support)
- CLI 및 위자드 부팅 디스크는
qemu-img를 사용하여 원본(raw) MikroTik 이미지에서 변환된 qcow2 형식을 기본값으로 사용합니다. 라이브러리 호출자는 bootSize가 qcow2를 암시하는 경우가 아니면 raw 형식을 기본값으로 합니다.
--boot-size는 첫 부팅 전에 qcow2 크기를 조정합니다; raw 형식과 부팅 크기를 명시적으로 결합하는 것은 거부됩니다.
--add-disk로 추가된 디스크는 항상 빈 qcow2 이미지로 생성됩니다.
quickchr clean <name>은 모든 크기 조정된 부팅 디스크와 추가 디스크를 제거한 다음, 저장된 머신 구성으로부터 다시 생성합니다.
quickchr disk <name>은 저장된 디스크 레이아웃을 보여줍니다. qemu-img가 설치되어 있으면 가상 크기와 실제 크기도 함께 표시됩니다.
quickchr snapshot은 qcow2 내부 스냅샷(qcow2 부팅 디스크 필요)을 관리합니다.
다중 NIC 네트워킹 (Multi-NIC Networking)
기본적으로 각 CHR은 단일 사용자 모드 NIC(SLIRP)를 가집니다. --add-network 플래그를 사용하여 더 많은 NIC를 추가하거나 기본값을 대체할 수 있습니다:
quickchr start --name router1 --add-network user --add-network shared
quickchr start --name router2 --add-network user --add-network shared
...
트래픽(호스트→게스트 서비스, 호스트가 게스트에서 발생한 UDP를 수신하는 경우, L2 브로드캐스트, VM↔VM 링크, 실제 LAN)에 어떤 메커니즘이 적합한지 확신할 수 없다면 네트워킹 레시피 가이드를 참조하십시오. 이 문서는 '트래픽 형태 → 메커니즘' 결정표입니다. CLI 플래그는 라이브러리와 1:1로 매핑됩니다: --add-network ↔ StartOptions.networks, --forward ↔ StartOptions.extraPorts.
포트 레이아웃 (Port Layout)
각 인스턴스는 10개의 포트 블록을 할당받습니다. 기본 베이스가 9100인 경우, 첫 번째 인스턴스는 다음과 같이 매핑됩니다:
| 오프셋 | 서비스 | 기본 포트 |
|---|
| +0 | HTTP / REST / WebFig | 9100 |
| ... | | |
두 번째 인스턴스는 9110–9119를, 그 외의 인스턴스는 순차적으로 할당받습니다.
사용자 지정 포트 포워딩 및 고정 WinBox
add 또는 create-and-start 명령에서 --forward <spec>을 사용하여 추가적인 QEMU SLiRP hostfwd 매핑을 추가할 수 있습니다. 이 축약형 구문은 게스트 포트를 알고 있는 경우 내장 서비스 레지스트리를 사용합니다:
quickchr add lab --forward smb
quickchr add dude-lab --forward winbox:8291
quickchr add app-lab --forward myapp:9200:7777/udp
...
포트 범위(port range) (name:hostStart-hostEnd[:guestStart-guestEnd][/proto])는 포트당 하나의 hostfwd로 확장됩니다. 이는 동적 데이터 포트를 사용하는 L3 피어에게 유용합니다. 게스트가 전송하는 UDP를 수신만 하고(포워딩 없음), 이를 처리하려면 네트워킹 레시피 가이드의 게이트웨이 경로를 참조하십시오.
winbox와 같은 내장 서비스 이름을 재사용하면 해당 서비스의 호스트 포트를 해당 머신에 고정(pin)하거나 대체합니다. 기존 머신은 machine.json에 저장된 매핑을 유지하므로, 고정 서비스 포트를 깨끗하게 변경하려면 머신을 다시 생성하십시오.
머신 디스크립터 및 서브프로세스 환경
quickchr inspect <name> [--json]은 실행 중인 머신에 대한 안정적이고 버전이 지정된 (descriptorVersion: 1) JSON 디스크립터를 방출합니다. 이는 quickchr ↔ centrs 인터페이스 계약(issue #71, docs/centrs-interface.md)입니다. 이 디스크립터에는 상태, 머신 식별자 및 서비스별 services 맵(rest-api, native-api, ssh)이 포함되어 있으며, 각 서비스에 대한 호스트/포트/전송 방식/tls/가용성/인증 정보를 제공하고, 선택적으로 customForwards와 networks를 추가로 포함합니다. --json은 호환성을 위해 허용되며, inspect 출력은 항상 JSON입니다. 이 명령어는 env 필드를 가지고 있지 않으므로, 서브프로세스 환경 변수는 quickchr env를 사용해야 합니다.
quickchr env <name> [--json]은 ChrInstance.subprocessEnv()와 동일한 서브프로세스 환경을 출력합니다. 기본적으로 셸의 KEY=value 라인 형식으로, --json 플래그를 사용하면 JSON 맵 형태로 출력됩니다.
자격 증명 주의 사항: 디스크립터/환경 출력에는 연결 비밀 정보가 포함됩니다 — 즉, subprocessEnv()/quickchr env의 QUICKCHR_AUTH/BASICAUTH, 그리고 각 descriptor() 서비스 자체의 인증 필드(services["rest-api"].auth.password/.basic/.header; services["native-api"].auth.password, basic/header 없음; services.ssh.auth.privateKeyPath)가 포함됩니다. 따라서 자식 프로세스는 quickchr의 비밀 저장소에 접근하지 않고도 연결할 수 있습니다. 이를 비밀번호처럼 취급하십시오: 커밋하거나, 공개 이슈에 붙여넣거나, CI 로그에 남겨두지 마십시오. 중지된 머신은 MACHINE_STOPPED 오류를 발생시키므로, 디스크립터나 환경 맵을 요청하기 전에 머신을 시작해야 합니다.
라이브러리 사용법
import { QuickCHR } from "@tikoci/quickchr";
...
버전 및 채널 API
CLI 텍스트를 스크래핑하지 않고도 어떤 CHR을 부팅할 가치가 있는지 선택할 수 있습니다 (CI 매트릭스에 유용):
import { resolveActiveChannels, resolveAllVersions } from "@tikoci/quickchr";
await resolveAllVersions();
...
compareRouterOsVersion 함수는 프리릴리즈 접미사(pre-release suffixes)를 순서대로 정렬합니다. 즉, 7.24beta2 < 7.24rc1 < 7.24 < 7.24.1 순으로 비교됩니다. 이 매핑은 CLI에서 quickchr version --json을 통해 확인할 수 있습니다. MANUAL.md의 버전 및 채널 헬퍼(Version & channel helpers) 섹션을 참조하십시오.
캐시 API (Cache API)
CI는 QEMU를 부팅하지 않고도 캐시 식별자를 해결하고 이미지를 다운로드할 수 있습니다:
import { CACHE_VERSION_UNRESOLVED, cacheAdd, cacheKey } from "@tikoci/quickchr";
const identity = await cacheKey({ channel: "stable", arch: "x86" });
...
명시적인 버전(explicit version)은 채널 해결을 수행하지 않습니다. 오프라인 채널 조회는 cacheKey에서 version: "unresolved"를 반환하며, cacheAdd는 엄격하게 작동하여 요청된 이미지를 해결하거나 다운로드할 수 없을 경우 실패합니다.
테스트 사용 (Use in Tests)
import { describe, test, afterAll, expect } from "bun:test";
import { QuickCHR } from "@tikoci/quickchr";
...
환경 변수 (Environment Variables)
| 변수 (Variable) | 설명 (Description) |
|---|
MIKROTIK_WEB_ACCOUNT | MikroTik.com 계정 이메일 (라이선스 갱신용) |
| ... | |
전체 목록(여기에는 QUICKCHR_DATA_DIR, QUICKCHR_NO_PROMPT, QUICKCHR_DEBUG, NO_COLOR가 포함됨)은 MANUAL.md §11에서 확인할 수 있습니다.
문서 (Documentation)
- MANUAL.md — 전체 참고 자료: 모든 CLI 명령어, 모든 라이브러리 API, 프로비저닝(provisioning), 채널(channels), 네트워킹(networking), 스토리지(storage), 오류(errors). 소스 검증 완료.
- examples/ — 실행 가능한 스크립트 (
bun run): quickstart/ (부팅 + 쿼리), grounding/ (설정 적용 → 읽어오기 — 테스트용 bun:test), dude/ (패키지 설치), harness/ (외부 도구 구동), rollback/, service-forward/, file-transfer/, device-mode/, 그리고 mndp/udp-gateway/version-matrix. examples/COVERAGE.md를 참조하세요.
- docs/networking-recipes.md — 어떤 네트워킹 메커니즘이 어떤 트래픽 쉐이핑에 적합한지.
- DESIGN.md — 아키텍처, 레이어, 설계 원칙.
- CONTRIBUTING.md — 개발 환경 설정 및
bun run check 실행 방법.
- CHANGELOG.md — 릴리스 이력.
AI 에이전트와 함께 quickchr 사용하기? tikoci/routeros-skills에 있는 routeros-quickchr 스킬은 에이전트에게 그라운딩 워크플로우(grounding workflow) — CHR 부팅, 설정 적용, 읽어오기 — 와 네트워킹 레시피 및 하네스 패턴을 가르칩니다.
라이선스
MIT