Rina VM deployment (Debian on QEMU/libvirt)
Deploy a Debian 13 minimal VM with cloud-init on a host running QEMU and libvirt (virsh). No interactive install: user, password, static IP, and swap are applied on first boot.
Why cloud-init (and not the netinst ISO)?
| Approach | Pros | Cons |
|---|---|---|
| Cloud image + cloud-init ✅ | Fully automated, minimal image, repeatable, set user/IP/swap in one go | Requires cloud image (no installer UI) |
| Netinst ISO | Familiar installer | Manual or preseed setup; slower; more steps |
Recommendation: Use the provided Debian generic cloud image + cloud-init for a one-shot, reproducible VM that matches your specs.
Specs (as requested)
- VM name:
CUBE(override withVM_NAME=...) - CPU: 2 cores
- Memory: 4 GB RAM + 4 GB swap
- Storage: 128 GB
- IP: 192.168.0.225 (set in
cloud-init/user-data; override there if needed) - User:
rina/ Password:rinapwd - OS: Latest Debian minimal (Debian 13 Trixie cloud image)
- Network: By default the VM is attached to bridge br1.40 (VLAN 40). See VLAN 40 / br1.40 setup on the host first.
Requirements on the remote host
- libvirt (virsh), QEMU, virt-install, qemu-img
- cloud-image-utils (for
cloud-localds) or genisoimage (for seed ISO) - Optional: curl (to download the cloud image)
Install on Debian/Ubuntu:
sudo apt install libvirt-daemon-system qemu-kvm virtinst libguestfs-tools cloud-image-utils
Quick start
-
Copy this directory to the remote machine (or clone there).
-
On the host: If using VLAN 40, configure br1.40 and eth1.40 first (see docs/vlan40-bridge-systemd-networkd.md).
-
Optional: Edit
cloud-init/user-dataandcloud-init/network-config:- Change IP (default
192.168.0.225/24), gateway (192.168.0.1), or DNS if your LAN differs. - Add your SSH public key under
ssh_authorized_keysfor key-based login. - Network is also embedded in
user-data;network-configis kept for reference.
- Change IP (default
-
Run the deploy script (on the remote host):
chmod +x deploy-rina-vm.sh ./deploy-rina-vm.shBy default the VM is named CUBE and attached to bridge br1.40. Override with
VM_NAME=...orBRIDGE=...if needed. -
Wait for first boot (~1–2 minutes). Then:
ssh rina@192.168.0.225 # password: rinapwdOr open the console:
virsh console CUBE.
What the script does
- Downloads the Debian 13 generic cloud image (qcow2) once to
/var/lib/libvirt/images/. - Creates a 128 GB disk for the VM backed by that image.
- Builds a cloud-init NoCloud seed ISO from
cloud-init/user-dataandcloud-init/meta-data. - Creates and starts the VM with virt-install (name CUBE, 2 vCPU, 4 GB RAM, 128 GB disk, bridge br1.40, seed ISO attached).
Customization
- VM name:
VM_NAME=myvm ./deploy-rina-vm.sh(default: CUBE) - Pool directory:
POOL_DIR=/path/to/images ./deploy-rina-vm.sh - Network: By default the VM is attached to bridge br1.40 (VLAN 40). To use another bridge:
BRIDGE=br0 ./deploy-rina-vm.sh. To use a libvirt network:BRIDGE= NETWORK=default ./deploy-rina-vm.sh - Resources:
CPU=4 MEMORY_GB=8 DISK_GB=256 ./deploy-rina-vm.sh
Firewall and SSH (same as “Rina PC”)
There is no firewall/SSH config in this repo. To apply the same rules as on the Rina PC:
- On the Rina PC, export current rules, for example:
- UFW:
sudo ufw status verbose > ufw-rina-pc.txt - iptables:
sudo iptables-save > iptables-rina-pc.txt
- UFW:
- Copy those rules to this VM (e.g. copy the files to
rina@192.168.0.225) and apply the same way (ufw or iptables). - Or document the desired rules and add them to
cloud-init/user-dataunderruncmdor a one-time script (e.g. enable ufw and allow SSH).
Example in user-data (if using UFW and you want SSH + same as Rina PC):
runcmd:
- apt-get install -y ufw
- ufw allow 22/tcp # SSH
# Add more rules to match Rina PC, then:
- ufw --force enable
Adjust rules to match your Rina PC before deploying.
Interface name (wrong IP or DHCP)
If the VM gets an IP via DHCP instead of 192.168.0.225, the interface name might not be enp1s0. On the VM run ip a and note the main interface (e.g. eth0). Then in cloud-init/user-data (and cloud-init/network-config if used), change the network.ethernets key from enp1s0 to that name, rebuild the seed ISO, and redeploy (or fix netplan inside the VM once).
Useful commands (on the host)
virsh list --all
virsh console CUBE
virsh shutdown CUBE
virsh start CUBE
(Use your VM_NAME if you overrode it.)
Files
deploy-rina-vm.sh– Deploy script (VM name CUBE, bridge br1.40 by default; download image, create disk, build seed ISO, virt-install).setup-vlan40-bridge.sh– Optional one-off script to create br1.40 and attach eth1.40; for persistent config use systemd-networkd (see docs).cloud-init/user-data– Userrina, password, sudo, SSH, packages, static IP (192.168.0.225), 4 GB swap.cloud-init/meta-data– Instance ID and hostname.cloud-init/network-config– Standalone netplan-style config (reference; main config is in user-data).docs/vlan40-bridge-systemd-networkd.md– Host setup for VLAN 40 and bridge br1.40 with systemd-networkd.
Reference
- Debian cloud images: https://cloud.debian.org/images/cloud/
- Debian 13 netinst (alternative): https://www.debian.org/CD/netinst/