Skip to content
Private Cloud Deployment

VoipNow KVM/QEMU Deployment Guide

This page contains instructions on how to deploy the VoipNow QCOW2 image on KVM/QEMU.

Requirements

To meet VoipNow's performance and computing requirements, the virtual machine must have the following configuration:

  • Memory: 16GB (or more)
  • CPUs: 4 cores (or more)
  • Network: virtio (1GbE or more)
  • HDD: 50GB virtual disk (or more)
  • Hypervisor: KVM/QEMU

Important Notes

"⚠️ DHCP Recommended"

  • VoipNow IP settings are configured during first boot. If you use a static IP or if the IP address changes after first boot, you must manually update the IP in the VoipNow web interface (Cloud Management section).
  • For simplicity, this guide does not configure services to start automatically on boot. You will need to enable them manually for a production KVM system.

"Firewall / security group ports"

Make sure the VM firewall (and any upstream firewall/security group) allows:

  • TCP 22 (SSH)
  • TCP 25 (SMTP)
  • TCP 80, 443 (Web)
  • UDP 5060 (SIP)
  • TCP 5061 (SIP TLS)
  • UDP 10000-20000 (RTP media)
  • UDP 4000-4999 (T.38 fax media)

QCOW2 Deployment (QEMU)

  1. Prepare the QCOW2 disk

    Download the VoipNow QCOW2 image from https://repo.4psa.com/download/ and place it on the host (example: voipnow-*.generic.qcow2).

  2. Configure cloud-init for user authentication

    On AlmaLinux 8–10, install the required tools:

bash
sudo dnf install -y qemu-kvm xorriso

Create user-data file with your authentication settings:

yaml
#cloud-config
users:
  - default
  - name: root
    lock_passwd: false

# SSH public key for key-based authentication (recommended)
ssh_authorized_keys:
  - ssh-ed25519 AAS.............gUGg13A myssh_key

system_info:
  default_user:
    name: 4psa
    lock_passwd: false
    gecos: 4PSA Administrator
    groups: [adm, systemd-journal, wheel]
    sudo: ["ALL=(ALL) NOPASSWD:ALL"]
    shell: /bin/bash

disable_root: true
ssh_pwauth: false  # Set to 'true' to enable SSH password authentication
ssh_deletekeys: true

# Set password for console and/or SSH access
chpasswd:
  expire: false
  users:
    - name: 4psa
      password: your_secure_pass  # Change this to your desired password
      type: text

"Authentication Configuration Options"

SSH Key Authentication (recommended):

  • Add your SSH public key to ssh_authorized_keys
  • Keep ssh_pwauth: false for key-only authentication

Enable SSH Password Authentication:

  • Set ssh_pwauth: true to allow password-based SSH login
  • The password set in chpasswd will be used for SSH access

Console Password:

  • Change password: your_secure_pass in the chpasswd section
  • This password works for VNC/serial console access regardless of SSH settings
  • If ssh_pwauth: true, this password also works for SSH

Create meta-data:

yaml
instance-id: voipnow-001
local-hostname: voipnow

Create the cloud-init ISO:

bash
xorriso -as mkisofs -output cloud-init.iso -volid cidata -joliet -rock user-data meta-data
  1. Boot the VM with QEMU

    Create and start a VM using QEMU, ensuring:

    • The voipnow-*.qcow2 disk is attached
    • The cloud-init.iso is attached (CD-ROM)
    • Network uses virtio with host port forwarding

    Install OVMF firmware (required for EFI boot):

bash
sudo dnf install -y edk2-ovmf

Start the VM (user networking with host port forwarding):

bash
# Set variables for image paths
QCOW2_IMAGE="voipnow-*.qcow2"
CLOUD_INIT_ISO="cloud-init.iso"
WORK_IMAGE="/tmp/voipnow-vm.qcow2"

# Create working copy (preserves original image)
if [ -f "$WORK_IMAGE" ]; then
    echo "WARNING: Reusing existing VM image - NOT a fresh boot!"
    echo "To force a fresh boot: rm -f $WORK_IMAGE"
else
    echo "Creating fresh working copy..."
    cp "$QCOW2_IMAGE" "$WORK_IMAGE"
fi

qemu-system-x86_64 \
  -name voipnow-vm \
  -machine type=q35,accel=kvm \
  -cpu host \
  -smp 4,sockets=1,cores=4,threads=1 \
  -m 16384 \
  -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE.secboot.fd \
  -drive if=pflash,format=raw,file=/usr/share/OVMF/OVMF_VARS.secboot.fd \
  -drive file="${WORK_IMAGE}",format=qcow2,if=none,id=hd0,cache=writeback,discard=unmap,detect-zeroes=unmap \
  -device virtio-scsi-pci,id=scsi0 \
  -device scsi-hd,drive=hd0,bus=scsi0.0 \
  -drive file="${CLOUD_INIT_ISO}",format=raw,if=none,id=cd0,readonly=on \
  -device virtio-scsi-pci,id=scsi1 \
  -device scsi-cd,drive=cd0,bus=scsi1.0 \
  -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::25-:25,hostfwd=tcp::80-:80,hostfwd=tcp::443-:443,hostfwd=udp::5060-:5060,hostfwd=tcp::5061-:5061,hostfwd=udp::10000-20000:10000-20000,hostfwd=udp::4000-4999:4000-4999 \
  -device virtio-net-pci,netdev=net0 \
  -serial file:/tmp/voipnow-console.log \
  -display vnc=:1 \
  -daemonize

"QEMU Configuration Details"

VM details:

  • Machine type: q35 (required for EFI boot)
  • Boot: EFI with OVMF firmware
  • Disk interface: virtio-scsi
  • Network: virtio-net with user networking and host port forwarding
  • Port forwarding: SSH (2222→22), SMTP (25), HTTP (80), HTTPS (443), SIP (5060), SIP TLS (5061), RTP (10000-20000), T.38 (4000-4999)
  • Cloud-init: Attached as CD-ROM via virtio-scsi

How to access the VM

  • SSH: ssh -p 2222 4psa@localhost (VM port 22 forwarded to host port 2222)
  • Web interface: https://localhost (port 443 forwarded)
  • VNC: vncviewer localhost:1 to see the graphical console
  • VM IP: The VM will receive an IP from QEMU's built-in DHCP (typically 10.0.2.15). Access services via localhost with forwarded ports.

"Fresh Boot vs Reusing State"

The script creates a working copy at /tmp/voipnow-vm.qcow2 to preserve your original image. If this file exists when you run the command again, it will reuse the existing VM state (NOT a fresh boot).

To force a fresh boot with clean cloud-init:

bash
rm -f /tmp/voipnow-vm.qcow2

Then run the QEMU command again.

"First Boot Duration"

The first boot will take longer than usual (about 5–10 minutes) while cloud-init configures the system. Wait for initialization to complete before accessing the VM.

  1. Access VoipNow VM and change admin password

    SSH access (as 4psa user):

bash
ssh -p 2222 4psa@localhost
sudo /usr/local/voipnow/bin/chadminpass.sh

Web interface (via port forwarding):

Open https://localhost (port 443 forwarded) and log in with the admin credentials.

  1. Configure firewall on host and VM

    On the KVM host (if you need VNC or SSH access from external networks):

bash
# Open VNC port for remote graphical console access
sudo firewall-cmd --permanent --add-port=5901/tcp
# Open SSH forwarded port (if accessing from external network)
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload

Inside the VM (configure VoIPNow firewall after first boot):

bash
# SSH into the VM
ssh -p 2222 4psa@localhost

# Open all VoIPNow required ports
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-service=smtp
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-port=5060/udp    # SIP
sudo firewall-cmd --permanent --add-port=5061/tcp    # SIP TLS
sudo firewall-cmd --permanent --add-port=10000-20000/udp  # RTP media
sudo firewall-cmd --permanent --add-port=4000-4999/udp    # T.38 fax
sudo firewall-cmd --reload

"Note on User Networking"

When using QEMU user networking (as shown in this guide), the VM's firewall is less critical since all traffic goes through the host's port forwarding. However, configuring the VM firewall is still recommended for security best practices and if you later switch to bridge networking.

Last updated: Feb 2, 2026