This document covers security considerations for production deployments of Docker-VM-Runner.
Docker-VM-Runner ships with intentionally weak defaults for quick local testing. You must change them before exposing services to any network.
| Service | Default User | Default Password | Override Variable |
|---|---|---|---|
| Guest VM | user |
password |
GUEST_PASSWORD |
| Redfish API | admin |
password |
REDFISH_USERNAME / REDFISH_PASSWORD |
Recommendations:
- Set
GUEST_PASSWORDto a strong value or, better, disable password auth entirely by providing an SSH public key viaSSH_PUBKEY. - Set
REDFISH_USERNAMEandREDFISH_PASSWORDto non-default values whenREDFISH_ENABLE=1. - For production VMs, disable password-based SSH in your cloud-init user-data and rely on key-based authentication.
Docker-VM-Runner auto-generates a self-signed TLS certificate for:
- The Redfish (sushy-emulator) HTTPS endpoint
- The noVNC WebSocket proxy
Self-signed certificates are not suitable for production. To use your own certificates:
docker run \
-v /path/to/my.crt:/var/lib/docker-vm-runner/state/certs/sushy.crt:ro \
-v /path/to/my.key:/var/lib/docker-vm-runner/state/certs/sushy.key:ro \
...When PERSIST=1 is set, generated certificates are retained across container restarts under the state directory.
Docker-VM-Runner requires elevated container privileges because it manages a full virtualization stack (libvirt + QEMU) inside the container.
| Setting | Why |
|---|---|
--privileged (or --device /dev/kvm --cgroupns=host) |
KVM access for hardware-accelerated virtualization |
--cap-add SYS_ADMIN |
Required only when using virtiofs filesystem sharing |
The bundled qemu.conf uses these settings for container compatibility:
security_driver = "none"— Disables SELinux/AppArmor confinement for QEMU processes. This is necessary because container-internal libvirt cannot manage host security labels.clear_emulator_capabilities = 0— Retains full capabilities for the QEMU emulator process. Required for device access within containers.user = "root"/group = "root"— QEMU runs as root inside the container.
These settings are standard for containerized libvirt deployments but mean the VM processes are not sandboxed within the container.
By default, all services bind to 0.0.0.0 (all interfaces):
| Service | Default Port | Env Variable |
|---|---|---|
| SSH (forwarded to guest) | 2222 | SSH_PORT |
| VNC | 5900 | VNC_PORT |
| noVNC (HTTPS) | 6080 | NOVNC_PORT |
| Redfish (HTTPS) | 8443 | REDFISH_PORT |
Recommendations:
- Only publish the ports you need:
-p 127.0.0.1:2222:2222instead of-p 2222:2222. - Use a reverse proxy with authentication for noVNC and Redfish in production.
- When using bridge or direct (macvtap) networking, the guest VM is directly exposed to the network — apply appropriate firewall rules on the host.
When NETWORK_MODE=direct, the guest NIC uses macvtap in bridge mode. This:
- Gives the guest a real IP address on the host network
- Requires promiscuous mode on the parent interface
- Bypasses Docker's network isolation entirely
Only use direct mode on trusted networks.
Before deploying Docker-VM-Runner in production:
- Changed
GUEST_PASSWORDto a strong value (or using SSH key auth only) - Changed
REDFISH_USERNAMEandREDFISH_PASSWORD(if Redfish is enabled) - Replaced self-signed TLS certificates with proper ones
- Published only necessary ports with host-binding (
127.0.0.1:port:port) - Set
PERSIST=1(or mounted a data volume at/data) for data persistence - Reviewed network mode — prefer NAT for isolated setups, bridge/direct only on trusted networks
- Reviewed cloud-init user-data for any hardcoded secrets