BCVK-EPHEMERAL-RUN(8)
π¦ bcvk-ephemeral-run(8) π¦
okay bestie, sit down, hydrate, and let me tell you about the most unhinged little VM launcher you've ever met π
this is bcvk-ephemeral-run, and it is literally the moment.
β¨ NAME β¨
bcvk-ephemeral-run β run bootc containers as stateless VMs
πΈ SYNOPSIS πΈ
bcvk ephemeral run [OPTIONS] IMAGE
π DESCRIPTION π
Run bootc containers as stateless VMs managed by podman. The VM boots directly from the container image's filesystem via virtiofs, with no disk image creation required. That's the whole tea β β startup is fast, and the VM is stateless by default. Iconic behaviour, no notes.
π How It Works π
This command creates an ephemeral virtual machine by launching a podman container that contains and runs QEMU. The process works like this, step by step, no skips:
- Container Setup: A privileged podman container is launched with access to the host's virtualization infrastructure
- Host Virtualization Access: The container gains access to:
/dev/kvmfor hardware virtualization- Host's
virtiofsddaemon for filesystem sharing - QEMU binaries and virtualization stack
- VM Creation: Inside the container, QEMU is executed to create a virtual machine
- Root Filesystem: The bootc container image's root filesystem becomes the VM's root filesystem, mounted via virtiofs
- Kernel Boot: The VM boots using the kernel and initramfs from the bootc container image
This architecture provides several advantages:
- Isolation: The VM runs in a contained environment separate from the host
- Fast I/O: virtiofs provides efficient filesystem access between container and VM
- Resource Efficiency: Leverages existing container infrastructure while providing full VM capabilities
π§ Container-VM Relationship π§
The relationship between the podman container and the VM inside it, spelled out because it is a little bit of a situationship:
- Podman Container: Acts as the virtualization environment, providing QEMU and system services
- QEMU Process: Runs inside the podman container, creating the actual virtual machine
- VM Guest: The bootc container image runs as a complete operating system inside the VM
- Filesystem Sharing: The container's root filesystem is shared with the VM via virtiofs at runtime
This design allows bcvk to provide VM-like isolation and boot behavior while leveraging container tooling. it's giving "have your cake and virtualize it too" π
π OPTIONS π
IMAGEβ Container image to run as ephemeral VM. This argument is required. (yes bestie, required required, not "required" like your ex was "busy" π)--itype=ITYPEβ Instance type (e.g.,u1.nano,u1.small,u1.medium). Overridesvcpus/memoryif specified.--memory=MEMORYβ Memory size (e.g.4G,2048M, or plain number for MB). Default:4G--vcpus=VCPUSβ Number of vCPUs (overridden by--itypeif specified)--consoleβ Connect the QEMU console to the container's stdio (visible viapodman logs/attach)--debugβ Enable debug mode (drop to shell instead of running QEMU)--virtio-serial-out=NAME:FILEβ Add virtio-serial device with output to file (format:name:/path/to/file)--execute=EXECUTEβ Execute command inside VM via systemd and capture output-K,--ssh-keygenβ Generate SSH keypair and inject via systemd credentials--virtiofsd=VIRTIOFSD_BINARYβ Path to virtiofsd binary (overrides auto-detection)--output=OUTPUTβ Select how VM output is presented
Possible values:
consolejournal
Default: console
--log-dir=STREAMS=DIRβ Write VM log streams to files in DIR-t,--ttyβ Allocate a pseudo-TTY for container-i,--interactiveβ Keep STDIN open for container-d,--detachβ Run container in background--rmβ Automatically remove container when it exits--name=NAMEβ Assign a name to the container--network=NETWORKβ Configure the network for the container--label=LABELβ Add metadata to the container inkey=valueform-e,--env=ENVβ Set environment variables in the container (key=value)--debug-entrypoint=DEBUG_ENTRYPOINTβ Do not run the default entrypoint directly, but instead invoke the provided command (e.g.bash)--bind=HOST_PATH[:NAME]β Bind mount host directory (RW) at/run/virtiofs-mnt-<name>--ro-bind=HOST_PATH[:NAME]β Bind mount host directory (RO) at/run/virtiofs-mnt-<name>--systemd-units=SYSTEMD_UNITS_DIRβ Directory with systemd units to inject (expectssystem/subdirectory)--bind-storage-roβ Mount host container storage (RO) at/run/virtiofs-mnt-hoststorage--add-swap=ADD_SWAPβ Allocate a swap device of the provided size--mount-disk-file=FILE[:NAME]β Mount disk file as virtio-blk device at/dev/disk/by-id/virtio-<name>--karg=KERNEL_ARGSβ Additional kernel command line arguments--ignition=IGNITION_CONFIGβ Path to Ignition config file (JSON format) to inject via fw_cfg
π EXAMPLES π
π Build and Test Workflow π
The most common use case is testing container images you're building. this is the daily routine, the main character arc:
# Build your bootc container image
podman build -t localhost/mybootc .
# Run it as an ephemeral VM (background, auto-cleanup, SSH keys)
bcvk ephemeral run -d --rm -K --name test localhost/mybootc
# SSH in to verify it works
bcvk ephemeral ssh test
# Stop when done (container auto-removed due to --rm)
podman stop test
For a faster iteration loop, use bcvk-ephemeral-run-ssh(8) which combines run and SSH into one command with automatic cleanup. obsessed with her honestly π«Ά
β Common Flag Combinations β
Testing a public image:
bcvk ephemeral run -d --rm -K --name testvm quay.io/fedora/fedora-bootc:42
bcvk ephemeral ssh testvm
Development with mounted source code:
bcvk ephemeral run -d --rm -K \
--bind /home/user/project:src \
--name devvm localhost/mybootc
bcvk ephemeral ssh devvm
# Files available at /run/virtiofs-mnt-src inside VM
Resource-intensive workloads:
bcvk ephemeral run -d --rm -K \
--memory 8G --vcpus 4 \
--name bigvm localhost/mybootc
Debugging boot issues:
bcvk ephemeral run --console -it --name debugvm localhost/mybootc
π Understanding the Flags π
-d,--detach: Run in background. Without this, the container runs in foreground and you see QEMU output directly.--rm: Auto-remove the container when it stops. Highly recommended for ephemeral testing to avoid accumulating stopped containers. (bestie, your disk will thank you, no cap)-K,--ssh-keygen: Generate SSH keypair and inject into the VM via systemd credentials. Required forbcvk ephemeral sshto work.--name: Assign a name for easy reference with other commands likebcvk ephemeral ssh.
π¦ Bind Mounts π¦
Share host directories with the VM using --bind or --ro-bind:
# Read-write mount
bcvk ephemeral run -d --rm -K --bind /host/path:name --name vm image
# Inside VM, access at:
/run/virtiofs-mnt-name
# Read-only mount (safer for sensitive data)
bcvk ephemeral run -d --rm -K --ro-bind /etc/myconfig:config --name vm image
πΈ Disk File Mounts πΈ
Mount raw disk images as block devices:
# Create a test disk
truncate -s 10G /tmp/testdisk.raw
# Mount into VM
bcvk ephemeral run -d --rm -K \
--mount-disk-file /tmp/testdisk.raw:testdisk \
--name vm localhost/mybootc
# Inside VM: /dev/disk/by-id/virtio-testdisk
π Port Forwarding π
For SSH port forwarding (recommended), use bcvk ephemeral ssh with -L or -R:
# Forward VM port 80 to localhost:8080
bcvk ephemeral ssh myvm -L 8080:localhost:80
For network-level port forwarding via podman, configure slirp4netns:
bcvk ephemeral run -d --rm -K \
--network slirp4netns:port_handler=slirp4netns,allow_host_loopback=true \
--name webvm localhost/mybootc
π₯ Instance Types π₯
Use predefined instance types for consistent resource allocation:
bcvk ephemeral run -d --rm -K --itype u1.small --name vm localhost/mybootc
bcvk ephemeral run -d --rm -K --itype u1.medium --name vm localhost/mybootc
bcvk ephemeral run -d --rm -K --itype u1.large --name vm localhost/mybootc
π§ Ignition Configuration π§
Inject Ignition (https://coreos.github.io/ignition/) configuration files for first-boot provisioning on CoreOS-based images:
# Create an Ignition config file (v3.3.0 format)
cat > config.ign <<EOF
{
"ignition": {
"version": "3.3.0"
},
"passwd": {
"users": [
{
"name": "core",
"sshAuthorizedKeys": [
"ssh-ed25519 AAAAC3... user@example.com"
]
}
]
},
"storage": {
"files": [
{
"path": "/etc/hostname",
"contents": {
"source": "data:,my-coreos-vm"
},
"mode": 420
}
]
}
}
EOF
# Run Fedora CoreOS with Ignition config
bcvk ephemeral run -d --rm \
--ignition config.ign \
--name fcos-vm \
quay.io/fedora/fedora-coreos:stable
Important notes:
- Only works with Ignition-capable images (Fedora CoreOS, RHEL CoreOS, or custom bootc images with Ignition support)
- Config is injected via
fw_cfgon x86_64/aarch64,virtio-blkon s390x/ppc64le (following FCOS conventions) - The
ignition.platform.id=qemukernel argument is automatically added - For ephemeral VMs, Ignition typically only runs on the first boot of a newly provisioned system
See the Ignition documentation (https://coreos.github.io/ignition/) and bootc initramfs documentation (https://docs.fedoraproject.org/en-US/bootc/initramfs/) for creating custom bootc images with Ignition support.
π DEBUGGING π
When troubleshooting ephemeral VM issues, bcvk provides several debugging logs that can be accessed from within the container. it's giving "she left receipts" and honestly we love that for us
π Guest Journal Log π
The systemd journal from the guest VM is automatically streamed to /run/journal.log inside the container. This log captures all boot messages, service startup events, and system errors from the VM's perspective.
To view the journal log:
# For a running detached VM
podman exec <container-id> tail -f /run/journal.log
# View specific systemd service messages
podman exec <container-id> grep "dbus-broker" /run/journal.log
# Save journal for offline analysis
podman exec <container-id> cat /run/journal.log > guest-journal.log
The journal log is particularly useful for:
- Diagnosing boot failures and systemd service issues
- Investigating permission denied errors
- Understanding VM initialization problems
- Debugging network and device configuration
β¨ Virtiofsd Logs β¨
The virtiofsd daemon logs are written to /run/virtiofsd.log and /run/virtiofsd-<mount-name>.log for each filesystem mount. These logs show filesystem sharing operations between the container and VM.
To view virtiofsd logs:
# Main virtiofsd log
podman exec <container-id> cat /run/virtiofsd.log
# Logs for additional bind mounts
podman exec <container-id> cat /run/virtiofsd-workspace.log
Virtiofsd logs are helpful for:
- Debugging filesystem access issues
- Understanding file handle support warnings
- Investigating mount-related errors
π Podman Can't See bcvk's Filesystem π
okay bestie this one is a whole saga so buckle up π«Ά To boot a VM, bcvk asks podman to bind-mount paths straight out of its own filesystem β including its own binary. That only works if podman can literally see the same filesystem bcvk does. When it can't, you get an error that looks like this:
Podman command failed: Error: statfs /usr/bin/bcvk: no such file or directory
and you're just standing there like π§ no cap.
When does this happen tho? It hits when bcvk is running inside a toolbox or distrobox container and podman is forwarded to the host instead of actually running inside the container. Think a flatpak-spawn --host podman wrapper, or the podman socket β that kind of setup. It also happens when podman is a remote client. In all those cases, the paths bcvk hands to podman get resolved on podman's side, so a bcvk binary that only exists inside your toolbox simply isn't findable over there. The good news: bcvk notices this and slaps a hint onto the error explaining it. Iconic behaviour honestly π
The fix: install bcvk on the host, right alongside podman and QEMU, and just run it there. Coming from a toolbox? Call the host's copy with:
flatpak-spawn --host bcvk ...
Coming from a distrobox? Then it's:
distrobox-host-exec bcvk ...
and you're so back πΈ
β οΈ okay now the scary part, bestie: beware of version skew. If bcvk binaries exist at the same path on both the host and in the toolbox β say, both installed from packages β this error won't even show up. Instead, podman mounts the host's copy into the VM's container, which can be a totally different version from the one you actually ran. That's giving chaos energy π Keep them in sync, or better yet, install bcvk only on the host. periodt.
β¨ SEE ALSO β¨
bcvk(8)β yeah bestie, the main character herself π
π VERSION π
v0.21.0
and that's a wrap on the whole page, babe π«Ά you just read the bcvk(8) man page, v0.21.0, straight from the source. go forth and virtualize responsibly, mwah π β¨π
π¦ where this page comes from
- fedora 43: bcvk 0.21.0-1.fc43 Β· Apache-2.0 OR MIT
- fedora 44: bcvk 0.21.0-1.fc44 Β· Apache-2.0 OR MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms