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)

  • CPU: 2 cores
  • Memory: 4 GB RAM + 4 GB swap
  • Storage: 128 GB
  • IP: 192.168.0.225
  • User: rina / Password: rinapwd
  • OS: Latest Debian minimal (Debian 13 Trixie cloud image)

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

  1. Copy this directory to the remote machine (or clone there).

  2. Optional: Edit cloud-init/user-data and cloud-init/network-config:

    • Change gateway (default 192.168.0.1) or DNS if your LAN differs.
    • Add your SSH public key under ssh_authorized_keys for key-based login.
    • Network is also embedded in user-data; network-config is kept for reference.
  3. Run the deploy script (on the remote host):

    chmod +x deploy-rina-vm.sh
    ./deploy-rina-vm.sh
    
  4. Wait for first boot (~12 minutes). Then:

    ssh rina@192.168.0.225
    # password: rinapwd
    

What the script does

  1. Downloads the Debian 13 generic cloud image (qcow2) once to /var/lib/libvirt/images/.
  2. Creates a 128 GB disk for the VM backed by that image.
  3. Builds a cloud-init NoCloud seed ISO from cloud-init/user-data and cloud-init/meta-data.
  4. Creates and starts the VM with virt-install (2 vCPU, 4 GB RAM, 128 GB disk, seed ISO attached).

Customization

  • Pool directory: POOL_DIR=/path/to/images ./deploy-rina-vm.sh
  • Network: By default the script uses the libvirt network default. For a bridge (e.g. br0):
    NETWORK=br0 ./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:

  1. 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
  2. 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).
  3. Or document the desired rules and add them to cloud-init/user-data under runcmd or 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 (192.168.0.225 not working)

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, 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 rina
virsh shutdown rina
virsh start rina

Files

  • deploy-rina-vm.sh Deploy script (download image, create disk, build seed ISO, virt-install).
  • cloud-init/user-data User rina, password, sudo, SSH, packages, static IP, 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).

Reference

Description
Rina VM deployment (VLAN 40, br1.40, cloud-init)
Readme 43 KiB
Languages
Shell 100%