libvirt instead of incus

This commit is contained in:
death916 2025-07-06 03:02:01 -07:00
parent 73462abc63
commit 3dc8dfb5eb
7 changed files with 158 additions and 80 deletions

View file

@ -9,9 +9,7 @@
arrSuite.enable = true; arrSuite.enable = true;
services.samba.shares.Media.path = "/media/storage/media"; services.samba.shares.Media.path = "/media/storage/media";
virtualisation.incus.enable = true; # virtualisation.incus.enable = true;
users.users.audiobookshelf = { users.users.audiobookshelf = {
isSystemUser = true; isSystemUser = true;
@ -20,8 +18,6 @@
users.groups.media_services = { }; users.groups.media_services = { };
services.audiobookshelf = { services.audiobookshelf = {
enable = true; enable = true;
user = "audiobookshelf"; user = "audiobookshelf";
@ -30,8 +26,6 @@
port = 13378; port = 13378;
}; };
users.users.qbittorrent.extraGroups = [ "media_services" ]; users.users.qbittorrent.extraGroups = [ "media_services" ];
users.groups.qbittorrent = { }; users.groups.qbittorrent = { };
@ -69,7 +63,10 @@
image = "sigoden/dufs:latest"; image = "sigoden/dufs:latest";
ports = [ "5000:5000" ]; ports = [ "5000:5000" ];
volumes = [ "/media/storage/media/:/data" ]; volumes = [ "/media/storage/media/:/data" ];
cmd = [ "/data" "-A" ]; cmd = [
"/data"
"-A"
];
}; };
c2c-scraper = { c2c-scraper = {
image = "death916/c2cscrape:latest"; image = "death916/c2cscrape:latest";
@ -77,7 +74,9 @@
"/media/storage/media/books/audio/podcasts/C2C:/downloads" "/media/storage/media/books/audio/podcasts/C2C:/downloads"
"/media/storage/media/docker/volumes/c2cscrape:/app/data" "/media/storage/media/docker/volumes/c2cscrape:/app/data"
]; ];
environment = { TZ = "America/Los_Angeles"; }; environment = {
TZ = "America/Los_Angeles";
};
autoStart = true; autoStart = true;
extraOptions = [ "--dns=8.8.8.8" ]; extraOptions = [ "--dns=8.8.8.8" ];
}; };
@ -101,7 +100,10 @@
Type = "oneshot"; Type = "oneshot";
User = "root"; User = "root";
ExecStart = "/usr/local/bin/nixos-kopia-backup.sh"; ExecStart = "/usr/local/bin/nixos-kopia-backup.sh";
path = with pkgs; [ coreutils kopia ]; path = with pkgs; [
coreutils
kopia
];
}; };
}; };
@ -126,6 +128,21 @@
security.sudo.wheelNeedsPassword = true; security.sudo.wheelNeedsPassword = true;
virtualisation.libvirtd = {
enable = true;
qemu = {
ovmf = true; # UEFI support for HAOS
};
};
services.homeassistant-vm = {
enable = false;
imagePath = "/var/lib/libvirt/images/haos.qcow2";
memory = 6096;
vcpus = 4;
bridge = "br0";
};
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
git git
vim vim
@ -145,5 +162,8 @@
manix manix
nh nh
qemu qemu
virt-install
virt-manager
usbutils
]; ];
} }

View file

@ -11,7 +11,15 @@
isNormalUser = true; isNormalUser = true;
home = "/home/${primaryUser}"; home = "/home/${primaryUser}";
description = "${primaryUser}"; description = "${primaryUser}";
extraGroups = [ "wheel" "media_services" "nextcloud" "docker" "qbittorent" "incus-admin" ]; extraGroups = [
"wheel"
"media_services"
"nextcloud"
"docker"
"qbittorent"
"incus-admin"
"libvirtd"
];
openssh.authorizedKeys.keys = [ openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCte9KjJUSn4xBPEKCk9QER6+jF+C0uBatVl27zIamYsryyHdFrmqK2DAg7OhqTHqzjxID6sp6d57MsJqOUAtwXbUDMLffqBSerUxfTm+1SPDrhL0GSvo0QVjMLVseOEq8d2qXgW1R7dIk412VbO5e9SAump5aJOHI/SzT6VLoUczalmqrjnDacWQMeLu/TSOZHcfrhjYSg+b1xbc1vHp6C4obOb8JIj/anAieT/1P36MhlNW79ow6PWenLemBYeeezFrKtESF1oMc8jmcxogzgLamlqhKYAHlKhOuBF6u0nRneI5IPDbbMF5zwEv5szCEKj8XZJVYUk8uUg7ARyppjcA7yAXuaNKBNxa7tfjqWrDWOACn97ufE5FFJt0XH5JzkXcDh96K8ZSZaWxMRu2s+GlIu/1F415xtVfe1d79HYkWke/ewaQ4NqgOt8f7wRvyzabpQZDzkaXO0UoK65O2HyUur33XWCEmV+1pB6BrS8pD+1I4Tvbnc+rOgtHTTRfKqezKqZmaErEOxClBwvWjvn0PzhGSoClTGXPjhl239/sH0JGY09dTBh8GtAVbfv+jFO6nm6aR7O/OwSaohY3uOdRo8XyxJr4XyGAaBNRdm6BUJRnB4W51J49IQBZzIe2NUkNMHeUT4jkxFpfhkujnSFw2ZnOLkERpwkltAlbwuLw== tavn1992@gmail.com" "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCte9KjJUSn4xBPEKCk9QER6+jF+C0uBatVl27zIamYsryyHdFrmqK2DAg7OhqTHqzjxID6sp6d57MsJqOUAtwXbUDMLffqBSerUxfTm+1SPDrhL0GSvo0QVjMLVseOEq8d2qXgW1R7dIk412VbO5e9SAump5aJOHI/SzT6VLoUczalmqrjnDacWQMeLu/TSOZHcfrhjYSg+b1xbc1vHp6C4obOb8JIj/anAieT/1P36MhlNW79ow6PWenLemBYeeezFrKtESF1oMc8jmcxogzgLamlqhKYAHlKhOuBF6u0nRneI5IPDbbMF5zwEv5szCEKj8XZJVYUk8uUg7ARyppjcA7yAXuaNKBNxa7tfjqWrDWOACn97ufE5FFJt0XH5JzkXcDh96K8ZSZaWxMRu2s+GlIu/1F415xtVfe1d79HYkWke/ewaQ4NqgOt8f7wRvyzabpQZDzkaXO0UoK65O2HyUur33XWCEmV+1pB6BrS8pD+1I4Tvbnc+rOgtHTTRfKqezKqZmaErEOxClBwvWjvn0PzhGSoClTGXPjhl239/sH0JGY09dTBh8GtAVbfv+jFO6nm6aR7O/OwSaohY3uOdRo8XyxJr4XyGAaBNRdm6BUJRnB4W51J49IQBZzIe2NUkNMHeUT4jkxFpfhkujnSFw2ZnOLkERpwkltAlbwuLw== tavn1992@gmail.com"
]; ];

View file

@ -0,0 +1,31 @@
{ pkgs, ... }:
{
environment.systemPackages = [
(pkgs.writeShellScriptBin "haos" ''
VM_NAME="homeassistant"
case "$1" in
start) virsh start "$VM_NAME" ;;
stop) virsh shutdown "$VM_NAME" ;;
status) virsh list --all | grep "$VM_NAME" ;;
ip) virsh domifaddr "$VM_NAME" | awk '/ipv4/ {print $4}' | cut -d/ -f1 ;;
console) virsh console "$VM_NAME" ;;
destroy)
echo "This will permanently delete the VM. Are you sure? (y/N)"
read -r confirmation
if [[ "$confirmation" =~ ^[Yy]$ ]]; then
virsh destroy "$VM_NAME" || true
virsh undefine "$VM_NAME" --remove-all-storage || true
echo "VM destroyed."
else
echo "Destruction cancelled."
fi
;;
*)
echo "Usage: haos {start|stop|status|ip|console|destroy}"
;;
esac
'')
];
}

View file

@ -0,0 +1,43 @@
{ config, pkgs, ... }:
let
cfg = config.services.homeassistant-vm;
in
{
environment.systemPackages = [
(pkgs.writeShellScriptBin "deploy-haos" ''
set -e
IMAGE="${cfg.imagePath}"
VM_NAME="homeassistant"
BRIDGE="${cfg.bridge}"
MEM_MB="${toString cfg.memory}"
VCPUS="${toString cfg.vcpus}"
if [ ! -f "$IMAGE" ]; then
echo "Error: HAOS image not found at $IMAGE"
exit 1
fi
if virsh list --all | grep -q " $VM_NAME "; then
echo "VM $VM_NAME already exists"
exit 0
fi
virt-install \
--name "$VM_NAME" \
--memory "$MEM_MB" \
--vcpus "$VCPUS" \
--import \
--disk path="$IMAGE",format=qcow2,bus=virtio \
--network bridge="$BRIDGE",model=virtio \
--os-variant generic \
--graphics none \
--noautoconsole \
--boot uefi
echo "Home Assistant VM deployed!"
echo "Get IP with: haos ip"
'')
];
}

View file

@ -1,67 +0,0 @@
# /home/death916/nixconfig/modules/vms/home-assistant.nix
{ config, pkgs, ... }:
let
# The incus-migrate tool is a separate package that we need to reference.
incus-migrate = pkgs.incus-migrate;
# The path to your HAOS image, as requested.
haos-image-path = "/home/death916/incus/haos_ova-15.2.qcow2";
# This script will run on boot to ensure the VM exists.
# It uses incus-migrate with a configuration file.
setupScript = pkgs.writeShellScript "ha-vm-setup.sh" ''
set -e
INCUS_CMD="${pkgs.incus}/bin/incus"
VM_NAME="home-assistant"
# 1. Check if the VM already exists. If so, do nothing.
if $INCUS_CMD info "''${VM_NAME}" >/dev/null 2>&1; then
echo "VM ''${VM_NAME} already exists. Ensuring it is running."
$INCUS_CMD start "''${VM_NAME}"
exit 0
fi
# 2. If the VM does not exist, create it using incus-migrate.
echo "Creating HAOS VM (''${VM_NAME}) with incus-migrate..."
# The configuration for incus-migrate, passed via stdin.
# This tells the tool what to do non-interactively.
cat <<EOF | ${incus-migrate}/bin/incus-migrate
name: ''${VM_NAME}
source_driver: disk
source_config:
path: "${haos-image-path}"
uefi: true
config:
limits.cpu: "2"
limits.memory: "4GiB"
EOF
# 3. Resize the disk after creation.
# incus-migrate doesn't set the size directly, so we do it here.
echo "Resizing root disk to 32GiB..."
$INCUS_CMD config device override "''${VM_NAME}" root size=32GiB
# 4. Start the VM.
$INCUS_CMD start "''${VM_NAME}"
'';
in
{
# This systemd service runs our setup script.
systemd.services.setup-ha-vm = {
description = "Setup Home Assistant Incus VM using incus-migrate";
after = [ "incus.service" ];
requires = [ "incus.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${setupScript}";
};
};
# Ensure incus-migrate is available in the system path for the service.
environment.systemPackages = [ pkgs.incus-migrate ];
}

View file

@ -0,0 +1,40 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.homeassistant-vm;
in
{
options.services.homeassistant-vm = {
enable = mkEnableOption "Home Assistant OS Virtual Machine";
imagePath = mkOption {
type = types.str;
default = "/var/lib/libvirt/images/haos.qcow2";
description = "Path to the HAOS qcow2 image";
};
memory = mkOption {
type = types.int;
default = 4096;
description = "Memory in MB";
};
vcpus = mkOption {
type = types.int;
default = 2;
description = "Number of CPUs";
};
bridge = mkOption {
type = types.str;
default = "br0";
description = "Bridge interface for VM networking";
};
};
config = mkIf cfg.enable {
imports = [
./ha-deploy-script.nix
./ha-control-script.nix
];
};
}

View file

@ -14,5 +14,8 @@
../modules/nixos/common/base.nix ../modules/nixos/common/base.nix
../modules/nixos/homelab/user.nix ../modules/nixos/homelab/user.nix
../modules/nixos/common/tailscale.nix ../modules/nixos/common/tailscale.nix
../modules/vms/ha-control-script.nix
../modules/vms/homeassistant-vm.nix
../modules/vms/ha-deploy-script.nix
]; ];
} }