Running MikroTik CHR on Proxmox: A Step-by-Step Virtualization Guide
CHR runs on almost any hypervisor, but Proxmox is where most self-hosted labs and small ISPs actually put it — free, KVM-based, and scriptable through the qm command line. Get two specific settings wrong, though, and you end up with a VM that boots to a black screen or a disk that silently never writes. This guide covers both the GUI and scripted paths, the settings that actually matter, and the Proxmox-specific gotchas that generic CHR guides skip.
Table of Contents
- Why Run CHR on Proxmox
- Prerequisites
- Method 1: GUI-Based VM Creation
- Method 2: Scripted VM Creation with qm (Recommended)
- Critical Settings Explained
- Networking: Bridges, VLANs, and the Proxmox Firewall Gotcha
- Multiple NICs for a Real Router Topology
- Sizing CPU, RAM, and Disk
- First Boot and Initial Configuration
- Licensing CHR on Proxmox
- Turning It Into a Reusable Template
- Performance Tuning for Higher Throughput
- Troubleshooting Common Problems
- Quick-Reference Command Cheat Sheet
- Conclusion
Why Run CHR on Proxmox
- Proxmox is free, KVM-based, and widely deployed in home labs, small ISPs, and self-hosted infrastructure — a natural fit for CHR, which is itself built for exactly this kind of virtualized deployment.
- The
qmCLI makes CHR deployment fully scriptable — spin up a lab topology of several CHR routers with a shell script instead of clicking through the GUI repeatedly. - Common use cases: a virtual core router or BGP edge router, a lab environment for testing configurations before pushing to physical hardware, a VPN concentrator, or a route reflector sitting alongside other virtualized infrastructure.
Prerequisites
- A working Proxmox VE node with root or sufficient administrative access, either via the web GUI or SSH.
- Outbound internet access from the Proxmox host, to download the CHR image directly.
- At least one configured Proxmox bridge (
vmbr0by default) to attach the VM’s network interface to. - A general understanding of Proxmox storage backends (
local-lvm,local-zfs, or a directory-basedlocalstore) — the exact commands below adjust slightly depending on which one you use.
Method 1: GUI-Based VM Creation
- In the Proxmox web interface, click Create VM.
- On the OS tab, select Do not use any media — the CHR disk gets attached manually after creation, not installed from boot media.
- On the System tab, the default BIOS setting works fine; CHR does not need OVMF/UEFI.
- On the CPU/Memory tabs, a minimal allocation is enough to start (1 core, 512 MB RAM works for a lab VM) — resize later once you know the real workload.
- On the Network tab, select the VirtIO (paravirtualized) network adapter, bridged to
vmbr0or whichever bridge fits your topology. - Finish the wizard, but do not start the VM yet — the disk still needs to be replaced with the actual CHR image.
- SSH into the Proxmox host, download and extract the CHR image, then import it as that VM’s disk (see the CLI commands in Method 2 for the exact import step — the GUI does not have a native “import CHR image” button, so this part always drops into the shell).
Method 2: Scripted VM Creation with qm (Recommended)
This is the faster, repeatable path — especially useful if you are standing up more than one CHR instance.
# Set these variables for your environment
CHR_VERSION="7.x" # use the current version from mikrotik.com/download
VM_ID=905
STORAGE=local-lvm # or local-zfs, or your storage ID
VM_NAME="chr-router"
# Download and extract the image
wget -c "https://download.mikrotik.com/routeros/$CHR_VERSION/chr-$CHR_VERSION.img.zip"
unzip "chr-$CHR_VERSION.img.zip"
# Create the VM shell
qm create $VM_ID --name $VM_NAME --ostype l26
# Network: VirtIO adapter on the default bridge
qm set $VM_ID --net0 virtio,bridge=vmbr0
# Serial console instead of VGA — see the next section for why this matters
qm set $VM_ID --serial0 socket --vga serial0
# CPU and memory
qm set $VM_ID --memory 256 --cores 2 --cpu host
# Import and attach the disk in one step
qm set $VM_ID --scsi0 ${STORAGE}:0,import-from="$(pwd)/chr-$CHR_VERSION.img",discard=on
qm set $VM_ID --boot order=scsi0 --scsihw virtio-scsi-single
# Optional: grow the disk beyond the default small image size
qm disk resize $VM_ID scsi0 8G
# Start it
qm start $VM_ID
On older Proxmox versions without the inline import-from syntax, use the two-step equivalent instead: qm importdisk $VM_ID chr-$CHR_VERSION.img $STORAGE, followed by qm set $VM_ID --scsi0 $STORAGE:vm-$VM_ID-disk-0.
Critical Settings Explained
--serial0 socket --vga serial0is not optional. CHR outputs its console over a serial port, not a VGA framebuffer. Skip this setting and Proxmox’s console shows a black screen with no boot output at all — the wrong console type being displayed.--scsihw virtio-scsi-single, not the default multi-queuevirtio-scsicontroller. Using the wrong SCSI controller type here has caused documented cases of the VM showing as running while never actually writing to disk. The disk activity counter stays at zero. The VM appears fine until you realize nothing is persisting.--ostype l26tells Proxmox to apply Linux-appropriate defaults — accurate enough for CHR’s underlying kernel, even though RouterOS isn’t a general-purpose Linux distribution.discard=onpasses TRIM through to the underlying storage, useful on thin-provisioned backends like ZFS or LVM-thin so deleted blocks actually free up space on the host.--cpu hostexposes the host’s real CPU features to the VM rather than a generic emulated CPU type, which matters for RouterOS’s own performance and feature detection.
Networking: Bridges, VLANs, and the Proxmox Firewall Gotcha
- Attach each NIC to the correct bridge for your topology —
vmbr0for a WAN-facing interface, a separate bridge or VLAN-tagged interface for LAN segments. - VLAN tagging happens at the bridge level in Proxmox’s network config, using
tag=on thenetparameter if your bridge is VLAN-aware:qm set $VM_ID --net1 virtio,bridge=vmbr0,tag=100 - The
firewall=1flag enables Proxmox’s own per-NIC firewall, layered on top of whatever firewall rules you configure inside RouterOS itself. For a router VM specifically, this is worth understanding clearly: Proxmox’s firewall can silently interfere with traffic the VM is supposed to be routing or forwarding between segments, since it applies its own MAC/IP-level filtering independent of RouterOS’s firewall logic. - For most CHR router deployments, leave
firewall=0(the default when the flag is omitted) and let RouterOS’s own firewall do the actual filtering — enabling the Proxmox-level firewall on a router VM’s interfaces is a common source of confusing, hard-to-diagnose traffic problems that have nothing to do with the RouterOS configuration itself.
Multiple NICs for a Real Router Topology
A lab VM with one NIC is fine for basic testing, but a CHR instance acting as an actual router needs at least two — WAN and LAN, at minimum.
qm set $VM_ID --net0 virtio,bridge=vmbr0
qm set $VM_ID --net1 virtio,bridge=vmbr1
- Each
--netNparameter becomes a separate interface inside RouterOS (ether1,ether2, and so on) in the order they were added. - Add as many as your topology needs — a lab simulating multiple WAN links, a DMZ segment, or several internal VLANs each map cleanly to one additional NIC.
Sizing CPU, RAM, and Disk
- RAM: CHR genuinely needs very little — 256 MB is a commonly cited working baseline for a lab instance. For production sizing based on interface count, use the RAM formula covered in our RouterOS download and installation guide.
- CPU: 1–2 cores is enough for light routing and lab work. Scale up specifically for high-throughput scenarios — heavy firewall rule evaluation, IPsec encryption, or NAT at real ISP-level traffic volumes.
- Disk: the default CHR image is tiny. Resizing to 8 GB (as in the script above) gives comfortable headroom for logs, backups, and scripts, though RouterOS itself uses very little of that by default.
First Boot and Initial Configuration
- Open the VM’s console in Proxmox — with
--vga serial0set correctly, this now shows RouterOS’s actual boot output instead of a black screen. - Log in with the default
adminaccount (RouterOS increasingly prompts to set a password on first login rather than shipping fully blank). - Confirm the VirtIO network interfaces are visible:
/interface print
- Run the same post-install checks covered in our RouterOS installation guide — confirm the package, set the identity, and set a strong password immediately:
/system identity set name=chr-proxmox-01
/user set admin password=YOUR-STRONG-PASSWORD
Licensing CHR on Proxmox
- CHR licensing works identically regardless of the hypervisor — Proxmox does not change anything about how CHR’s Free/P1/P10/Perpetual-Unlimited tiers apply. See our RouterOS installation guide for the full breakdown of that licensing model.
- Outbound connectivity from the VM to mikrotik.com matters here too — the same license renewal check-in requirement applies whether CHR runs on Proxmox, bare-metal KVM, or a public cloud provider.
Turning It Into a Reusable Template
Once a CHR VM is configured the way you want a baseline to look, convert it into a Proxmox template so you can clone it repeatedly instead of repeating the full import process:
qm template $VM_ID
- Clone from the template whenever you need a fresh CHR instance — useful for lab environments where you frequently need several identical starting points.
- Templates are read-only once created — clone them into new VM IDs rather than trying to start and modify the template VM directly.
Performance Tuning for Higher Throughput
- Enable multiqueue on the network interface when the CHR instance needs to handle real throughput — set it to match the VM’s vCPU count, under the NIC’s Advanced options (or via
qm setwith thequeues=parameter):qm set $VM_ID --net0 virtio,bridge=vmbr0,queues=4This lets network interrupt handling spread across multiple vCPUs instead of bottlenecking on one.
- Keep
--cpu hostset rather than a generic CPU type, for both performance and feature availability. - Avoid oversubscribing the Proxmox host’s physical cores for a router VM specifically — a router under real load is latency-sensitive in a way many other VM workloads are not, and CPU contention from other VMs shows up directly as jitter and packet delay.
Troubleshooting Common Problems
Console shows a black screen, VM appears to be running
- Cause: Missing or incorrect
--serial0 socket --vga serial0setting — Proxmox is displaying a VGA console CHR never outputs to. - Fix: Apply the serial console settings from the CLI commands above and restart the VM.
VM runs, but nothing ever writes to disk
- Cause: A SCSI controller mismatch — using the default multi-queue
virtio-scsicontroller instead ofvirtio-scsi-single. - Fix: Confirm
--scsihw virtio-scsi-singleis set, and recreate the disk attachment if it was set up under the wrong controller type.
Router VM cannot pass traffic between two segments correctly
- Cause: Proxmox’s own per-NIC firewall (
firewall=1) is filtering traffic independently of RouterOS’s firewall configuration. - Fix: Disable the Proxmox-level firewall flag on the router VM’s interfaces and rely on RouterOS’s own firewall for actual traffic policy.
Image import fails with an unrecognized command
- Cause: An older Proxmox VE version that does not support the inline
import-fromsyntax onqm set. - Fix: Use the older two-step
qm importdiskfollowed byqm set --scsi0pattern instead.
Quick-Reference Command Cheat Sheet
# Download and extract
wget -c "https://download.mikrotik.com/routeros/$CHR_VERSION/chr-$CHR_VERSION.img.zip"
unzip "chr-$CHR_VERSION.img.zip"
# Create the VM
qm create $VM_ID --name $VM_NAME --ostype l26
qm set $VM_ID --net0 virtio,bridge=vmbr0
qm set $VM_ID --serial0 socket --vga serial0
qm set $VM_ID --memory 256 --cores 2 --cpu host
# Import and attach the disk
qm set $VM_ID --scsi0 ${STORAGE}:0,import-from="$(pwd)/chr-$CHR_VERSION.img",discard=on
qm set $VM_ID --boot order=scsi0 --scsihw virtio-scsi-single
qm disk resize $VM_ID scsi0 8G
# Start
qm start $VM_ID
# Add a second NIC for a WAN/LAN split
qm set $VM_ID --net1 virtio,bridge=vmbr1
# Enable multiqueue for higher throughput
qm set $VM_ID --net0 virtio,bridge=vmbr0,queues=4
# Convert to a reusable template
qm template $VM_ID
Conclusion
CHR on Proxmox is genuinely simple once two settings are right.
First, enable the serial console so you can see what is happening. Second, use the correct SCSI controller so the disk persists reliably.
Script the VM creation with `qm` instead of clicking through the GUI each time. Keep Proxmox’s own firewall off the router VM’s interfaces. Let RouterOS handle the traffic policy it was built for.
Get the foundation right, and the next CHR instance is quick to deploy. Whether it is for a lab, a route reflector, or a production edge router, one script run is all it takes. No more hour-long troubleshooting sessions with a black screen.
Check our list of MikroTik guides