diff --git a/ansible/files/vms/fedora-headless.xml b/ansible/files/vms/fedora-headless.xml
deleted file mode 100644
index c6449ac..0000000
--- a/ansible/files/vms/fedora-headless.xml
+++ /dev/null
@@ -1,199 +0,0 @@
-
- fedora-headless
- 55feda16-51ae-446e-9c83-4c0eee1e5e00
- Fedora CUDA headless
- 33554432
- 33554432
-
-
-
-
-
- 2
-
-
-
-
-
-
- hvm
- /usr/share/edk2/ovmf/OVMF_CODE.fd
- /var/lib/libvirt/qemu/nvram/fedora-headless_VARS.fd
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- destroy
- restart
- destroy
-
-
-
-
-
- /usr/bin/qemu-system-x86_64
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ansible/files/vms/old/fedora-headless.old.xml b/ansible/files/vms/old/fedora-headless.old.xml
deleted file mode 100644
index a346373..0000000
--- a/ansible/files/vms/old/fedora-headless.old.xml
+++ /dev/null
@@ -1,220 +0,0 @@
-
- fedora-headless
- 55feda16-51ae-446e-9c83-4c0eee1e5e00
- Fedora CUDA headless
- 33554432
- 33554432
-
-
-
-
-
- 10
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- hvm
- /usr/share/edk2/ovmf/OVMF_CODE.fd
- /var/lib/libvirt/qemu/nvram/fedora-headless_VARS.fd
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- destroy
- restart
- destroy
-
-
-
-
-
- /usr/bin/qemu-system-x86_64
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ansible/files/vms/old/windows-11-pro.old.xml b/ansible/files/vms/old/windows-11-pro.old.xml
deleted file mode 100644
index ad03378..0000000
--- a/ansible/files/vms/old/windows-11-pro.old.xml
+++ /dev/null
@@ -1,300 +0,0 @@
-
- windows-11
- 51d5d091-67cb-4113-bd8e-817e7317e1b4
- Microsoft Windows 11
- 25165824
- 25165824
-
-
-
-
-
- 10
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /machine
-
-
- hvm
- /usr/share/edk2/ovmf/OVMF_CODE.secboot.fd
- /var/lib/libvirt/qemu/nvram/windows-11_VARS.fd
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- destroy
- restart
- destroy
-
-
-
-
-
- /usr/bin/qemu-system-x86_64
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- system_u:object_r:svirt_image_t:s0:c399,c880
-
-
-
- +107:+107
-
-
-
diff --git a/ansible/files/vms/windows-11.xml b/ansible/files/vms/windows-11.xml
deleted file mode 100644
index 1948ad0..0000000
--- a/ansible/files/vms/windows-11.xml
+++ /dev/null
@@ -1,224 +0,0 @@
-
- windows-11
- 51d5d091-67cb-4113-bd8e-817e7317e1b4
- Microsoft Windows 11
- 25165824
- 25165824
-
-
-
-
-
- 8
-
-
-
-
-
-
-
-
-
-
-
-
- hvm
- /usr/share/edk2/ovmf/OVMF_CODE.secboot.fd
- /var/lib/libvirt/qemu/nvram/windows-11_VARS.fd
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- destroy
- restart
- destroy
-
-
-
-
-
- /usr/bin/qemu-system-x86_64
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ansible/host_vars/vh-01.alexpires.dev.yml b/ansible/host_vars/vh-01.alexpires.dev.yml
new file mode 100644
index 0000000..e1909da
--- /dev/null
+++ b/ansible/host_vars/vh-01.alexpires.dev.yml
@@ -0,0 +1,189 @@
+hostname: vh-01.alexpires.local
+ansible_user: "{{ lookup('env', 'ANSIBLE_USER') }}"
+
+# Users
+login_users:
+ - username: "{{ ansible_user }}"
+ comment: "Managed by Ansible"
+ sudoer: true
+ sudoer_root_only: true
+ sudoer_no_password: true
+ pubkey: "{{ lookup('file', 'keys/ansible_user.pub') }}"
+ password_disabled: true
+ - username: operator
+ comment: "Managed by Ansible"
+ sudoer: true
+ pubkey: "{{ lookup('file', 'keys/operator.pub') }}"
+ shell: "/bin/zsh"
+ password_expiration: false
+
+# SSH Connection and security
+sshd_port: 22
+ssh_allowed_networks:
+ - "0.0.0.0/0"
+sshd_admin_net: "0.0.0.0/0"
+sshd_allow_groups: "{{ ansible_user }} users"
+sshd_permit_root_login: "no"
+sshd_password_authentication: "no"
+sshd_allow_tcp_forwarding: "yes"
+
+# Due to an issue increase the number of max auth tries
+sshd_max_auth_tries: 10
+
+# Firewall ports
+ufw_enable: true
+fw_allowed_ports:
+ - { rule: "allow", port: "22", proto: "tcp" }
+ - { rule: "allow", port: "9090", proto: "tcp" }
+
+ufw_outgoing_traffic:
+ - 22 # SSH
+ - 53 # DNS
+ - 80 # HTTP
+ - 123 # NTP
+ - 443 # HTTPS
+ - 853 # DNS over TLS
+
+ufw_default_forward_policy: "ACCEPT"
+
+ipv4_sysctl_settings:
+ net.ipv4.ip_forward: 1
+
+disable_ipv6: true
+
+# geoip will override hosts_allow and hosts_deny (so it's disabled - CIS hardening)
+custom_hosts_acls: true
+
+# This fixes polkit issues with sudoers file (CIS hardening)
+hide_pid: 0
+
+# aide
+install_aide: false
+
+# Unattended upgrades
+unattended_reboot: true
+unattended_reboot_time: "04:30"
+
+# Duo Security
+duo_users: ["*", "!provision"]
+duo_api_hostname: api-7cda1654.duosecurity.com
+
+# VMs reserved CPU (for gaming and AI)
+virt_vm_reserved_cpu: "1-5,7-11"
+virt_raw_block_devices:
+ - "nvme0n1"
+ - "nvme0n1p1"
+ - "nvme0n1p2"
+
+virt_extra_grub_args: >
+ i915.modeset=1 i915.enable_gvt=1 i915.enable_fbc=0
+ initcall_blacklist=simpledrm_platform_driver_init
+ rd.driver.blacklist=nouveau modprobe.blacklist=nouveau
+
+virt_vfio_ids:
+ - 10de:2482 # NVIDIA Corporation GA104 [GeForce RTX 3070 Ti]
+ - 10de:228b # NVIDIA Corporation GA106 High Definition Audio Controller
+ - 10de:2504 # NVIDIA Corporation GA106 [GeForce RTX 3060 Lite Hash Rate]
+ - 10de:228e # NVIDIA Corporation GA106 High Definition Audio Controller
+ - 1b73:1100 # Fresco Logic FL1100 USB 3.0 Host Controller
+
+virt_blacklist:
+ - noveau
+ - snd_hda_codec_hdmi
+ - i2c_nvidia_gpu
+ - mxm_wmi
+
+virt_machines:
+ - name: windows-11
+ title: "Microsoft Windows 11"
+ uuid: "51d5d091-67cb-4113-bd8e-817e7317e1b4"
+ autostart: true
+ memory: 25165824
+ cores: 4
+ threads: 2
+ physical_cpus: "2-8,3-9,4-10,5-11"
+ reserved_cpus: "0,6"
+ enable_hyperv: true
+ cdrom: true
+ console: false
+ audio: true
+ secure_boot: true
+ tpm: true
+ tablet: true
+ disk_file: "windows-11.qcow2"
+ mac_address: "52:54:00:cd:dd:2d"
+ block_devs:
+ - block_dev: "/dev/nvme0n1"
+ target_dev: "sdb"
+ host_devs:
+ # Intel MDev device for GVT-g
+ - type: "mdev"
+ source:
+ uuid: "5abeb24f-d6f4-4666-b495-303f15b05723"
+ address: { type: 'pci', domain: '0x0000', bus: '0x07', slot: '0x00', function: '0x0' }
+ # Fresco Logic FL1100 USB 3.0 Host Controller
+ - type: "pci"
+ source:
+ address:
+ domain: "0x0000"
+ bus: "0x06"
+ slot: "0x00"
+ function: "0x0"
+ address: { type: 'pci', domain: '0x0000', bus: '0x10', slot: '0x00', function: '0x0' }
+ # NVIDIA Corporation GA104 [GeForce RTX 3070 Ti]
+ - type: "pci"
+ source:
+ address:
+ domain: "0x0000"
+ bus: "0x01"
+ slot: "0x00"
+ function: "0x0"
+ address: { type: 'pci', domain: '0x0000', bus: '0x0b', slot: '0x00', function: '0x0' }
+ # NVIDIA Corporation GA106 High Definition Audio Controller
+ - type: "pci"
+ source:
+ address:
+ domain: "0x0000"
+ bus: "0x01"
+ slot: "0x00"
+ function: "0x1"
+ address: { type: 'pci', domain: '0x0000', bus: '0x0f', slot: '0x00', function: '0x0' }
+
+ - name: fedora-headless
+ title: "Fedora CUDA headless"
+ uuid: "55feda16-51ae-446e-9c83-4c0eee1e5e00"
+ autostart: true
+ memory: 33554432
+ cores: 1
+ threads: 2
+ physical_cpus: "1-7"
+ reserved_cpus: "0,6"
+ cdrom: false
+ console: true
+ audio: false
+ secure_boot: false
+ tpm: true
+ disk_file: "fedora-headless.qcow2"
+ mac_address: "52:54:00:ae:f3:d0"
+ block_devs:
+ - block_dev: "/dev/nvme0n1"
+ target_dev: "sdb"
+ host_devs:
+ # NVIDIA Corporation GA106 [GeForce RTX 3060 Lite Hash Rate]
+ - type: "pci"
+ source:
+ address:
+ domain: "0x0000"
+ bus: "0x03"
+ slot: "0x00"
+ function: "0x0"
+ address: { type: 'pci',domain: '0x0000',bus: '0x09',slot: '0x00',function: '0x0' }
+ # NVIDIA Corporation GA106 High Definition Audio Controller
+ - type: "pci"
+ source:
+ address:
+ domain: "0x0000"
+ bus: "0x03"
+ slot: "0x00"
+ function: "0x1"
+ address: { type: 'pci',domain: '0x0000',bus: '0x0a',slot: '0x00',function: '0x0' }
diff --git a/ansible/playbook_duo_security.yml b/ansible/playbook_duo_security.yml
index 7a3ba49..d41e887 100644
--- a/ansible/playbook_duo_security.yml
+++ b/ansible/playbook_duo_security.yml
@@ -1,6 +1,6 @@
---
- name: Duo Security
- hosts: public
+ hosts: 2fa
gather_facts: true
roles:
diff --git a/ansible/localhost_playbook_vm_host.yml b/ansible/playbook_virt_host.yml
similarity index 60%
rename from ansible/localhost_playbook_vm_host.yml
rename to ansible/playbook_virt_host.yml
index ebf144a..29f1c86 100644
--- a/ansible/localhost_playbook_vm_host.yml
+++ b/ansible/playbook_virt_host.yml
@@ -1,35 +1,16 @@
- name: Setup GPU passthrough host (Fedora + QEMU/KVM)
- hosts: localhost
+ hosts: virtualization
become: true
vars:
- host_reserved_cpu: "0-1"
- gaming_vm_cpus: "2-9"
- ai_vm_cpus: "10-11"
- vfio_ids:
- - 10de:2482 # NVIDIA Corporation GA104 [GeForce RTX 3070 Ti]
- - 10de:228b # NVIDIA Corporation GA106 High Definition Audio Controller
- - 10de:2504 # NVIDIA Corporation GA106 [GeForce RTX 3060 Lite Hash Rate]
- - 10de:228e # NVIDIA Corporation GA106 High Definition Audio Controller
- - 1b73:1100 # Fresco Logic FL1100 USB 3.0 Host Controller
- # - 144d:a808 # Samsung Electronics Co Ltd NVMe SSD Controller SM981/PM981/PM983
grub_config_file: "/etc/default/grub"
grub_cmdline_args: >
rhgb quiet intel_iommu=on iommu=pt
- isolcpus=1-5,7-11 nohz_full=1-5,7-11 rcu_nocbs=1-5,7-11
- i915.modeset=1 i915.enable_gvt=1 i915.enable_fbc=0
- initcall_blacklist=simpledrm_platform_driver_init
- rd.driver.blacklist=nouveau modprobe.blacklist=nouveau
+ isolcpus={{ virt_vm_reserved_cpu }} nohz_full={{ virt_vm_reserved_cpu }} rcu_nocbs={{ virt_vm_reserved_cpu }}
snd_hda_codec_hdmi.blacklist=1 rd.driver.pre=vfio-pci audit=off
-
- win_partition: "/dev/nvme0n1p1"
- ai_partition: "/dev/nvme0n1p2"
- partitions:
- - { dev: "/dev/nvme0n1p1", label: "win-nvme" }
- - { dev: "/dev/nvme0n1p2", label: "ai-nvme" }
+ default_hugepagesz=1G hugepagesz=1G hugepages=8 mitigations=off loglevel=3 {{ virt_extra_grub_args | default("") | trim}}
tasks:
-
- - name: Install virtualization packages
+ - name: Install required packages
ansible.builtin.dnf:
name:
- qemu-kvm
@@ -38,6 +19,9 @@
- virt-manager
- bridge-utils
- pciutils
+ - tuned
+ - python3-lxml
+ - python3-libvirt
state: present
- name: Enable and start libvirtd
@@ -52,24 +36,22 @@
regexp: '^GRUB_CMDLINE_LINUX='
line: 'GRUB_CMDLINE_LINUX="{{ grub_cmdline_args | trim }}"'
backrefs: true
+ notify: Rebuild GRUB config
- name: Add VFIO PCI device IDs to modprobe
ansible.builtin.copy:
dest: /etc/modprobe.d/vfio.conf
content: |
- options vfio-pci ids={{ vfio_ids | join(',') }}
+ options vfio-pci ids={{ virt_vfio_ids | join(',') }}
install snd_hda_codec_hdmi /bin/false
mode: '0644'
- name: Blacklist Nouveau and other drivers
- ansible.builtin.copy:
+ ansible.builtin.template:
+ src: blacklist.conf.j2
dest: /etc/modprobe.d/ansible-blacklist.conf
- content: |
- blacklist noveau
- blacklist snd_hda_codec_hdmi
- blacklist i2c_nvidia_gpu
- blacklist mxm_wmi
mode: '0644'
+ when: virt_blacklist is defined
- name: Add vfio modules to initramfs config
ansible.builtin.copy:
@@ -77,15 +59,14 @@
content: |
add_drivers+=" vfio vfio_iommu_type1 vfio_pci "
mode: '0644'
+ notify: Rebuild initramfs
- - name: Rebuild initramfs
- changed_when: false
- ansible.builtin.command: dracut -f
-
- - name: Rebuild GRUB config
- changed_when: false
- ansible.builtin.command: grub2-mkconfig -o /boot/grub2/grub.cfg
- when: ansible_facts['distribution'] == "Fedora"
+ - name: Configure hugepages
+ ansible.posix.sysctl:
+ name: vm.nr_hugepages
+ value: "{{ hugepages_count | default('2048') }}"
+ state: present
+ reload: true
- name: Enable KVM modules at boot
ansible.builtin.copy:
@@ -98,40 +79,62 @@
vfio_iommu_type1
mode: '0644'
+ - name: Set I/O scheduler to 'none' for NVMes
+ ansible.builtin.copy:
+ dest: /etc/udev/rules.d/60-ioscheduler.rules
+ content: |
+ ACTION=="add|change", KERNEL=="nvme[0-9]*", ATTR{queue/scheduler}="none"
+ mode: '0644'
+ notify:
+ - Reload udev rules
+ - Trigger udev to apply changes
+
+ - name: Activate virtual-host tuned profile
+ ansible.builtin.command: tuned-adm profile virtual-host
+ changed_when: false
+
+ - name: Set permissions for partition passthrough
+ ansible.builtin.file:
+ path: "/dev/{{ item }}"
+ owner: qemu
+ group: kvm
+ mode: '0660'
+ loop: "{{ virt_raw_block_devices }}"
+
+ - name: Create udev rules for persistent access
+ ansible.builtin.template:
+ src: 99-qemu-nvme.rules.j2
+ dest: /etc/udev/rules.d/99-qemu-nvme.rules
+ mode: '0644'
+ notify:
+ - Reload udev rules
+ - Trigger udev to apply changes
+
+ - name: Create or update virtual machine
+ vars:
+ vm: "{{ item }}"
+ loop: "{{ virt_machines }}"
+ community.libvirt.virt:
+ autostart: "{{ vm.autostart | default(false) }}"
+ name: "{{ vm.name }}"
+ state: running
+ command: define
+ xml: "{{ lookup('template', 'domain.xml.j2') }}"
+
+ - name: Ensure virtual machines are running
+ vars:
+ vm: "{{ item }}"
+ loop: "{{ virt_machines }}"
+ community.libvirt.virt:
+ name: "{{ vm.name }}"
+ state: running
+
- name: Notify user to reboot for changes
ansible.builtin.debug:
msg: |
Reboot your system to apply IOMMU, CPU isolation, and VFIO settings.
After reboot, verify using: `dmesg | grep -i vfio` and `lspci -nnk`
- - name: Ensure partitions are unmounted
- ansible.posix.mount:
- path: "/mnt/{{ item.label }}"
- src: "{{ item.dev }}"
- state: absent
- fstype: auto
- loop: "{{ partitions }}"
-
- - name: Set permissions for partition passthrough
- ansible.builtin.file:
- path: "{{ item.dev }}"
- owner: qemu
- group: kvm
- mode: '0660'
- loop: "{{ partitions }}"
-
- - name: Create udev rules for persistent access
- ansible.builtin.copy:
- dest: /etc/udev/rules.d/99-qemu-nvme.rules
- content: |
- KERNEL=="nvme0n1", OWNER="qemu", GROUP="kvm", MODE="0660"
- KERNEL=="nvme0n1p1", OWNER="qemu", GROUP="kvm", MODE="0660"
- KERNEL=="nvme0n1p2", OWNER="qemu", GROUP="kvm", MODE="0660"
- mode: '0644'
- notify:
- - Reload udev rules
- - Trigger udev to apply changes
-
handlers:
- name: Reload udev rules
changed_when: false
@@ -140,3 +143,12 @@
- name: Trigger udev to apply changes
changed_when: false
ansible.builtin.command: udevadm trigger
+
+ - name: Rebuild initramfs
+ changed_when: false
+ ansible.builtin.command: dracut -f
+
+ - name: Rebuild GRUB config
+ changed_when: false
+ ansible.builtin.command: grub2-mkconfig -o /boot/grub2/grub.cfg
+ when: ansible_facts['distribution'] == "Fedora"
diff --git a/ansible/requirements.yml b/ansible/requirements.yml
index a6b0fd8..d640cbb 100644
--- a/ansible/requirements.yml
+++ b/ansible/requirements.yml
@@ -2,3 +2,5 @@
collections:
- ansible.posix
- community.general
+ - containers.podman
+ - community.libvirt
diff --git a/ansible/roles/cis/tasks/ctrlaltdel.yml b/ansible/roles/cis/tasks/ctrlaltdel.yml
index 80da1ec..1c38c91 100644
--- a/ansible/roles/cis/tasks/ctrlaltdel.yml
+++ b/ansible/roles/cis/tasks/ctrlaltdel.yml
@@ -12,7 +12,18 @@
- CCE-80785-9
- systemd
-- name: Disable systemd ctrl-alt-del - RedHat family
+- name: Remove existing symlink for ctrl-alt-del.target if it exists
+ become: true
+ ansible.builtin.file:
+ path: /etc/systemd/system/ctrl-alt-del.target
+ state: absent
+ when: ansible_os_family == "RedHat"
+ tags:
+ - ctrl-alt-del
+ - CCE-80785-9
+ - systemd
+
+- name: Mask ctrl-alt-del.target to disable Ctrl+Alt+Del
become: true
ansible.builtin.systemd:
name: ctrl-alt-del.target
@@ -25,4 +36,4 @@
- ctrl-alt-del
- CCE-80785-9
- systemd
-...
+
diff --git a/ansible/roles/cis/tasks/users.yml b/ansible/roles/cis/tasks/users.yml
index 87a71e2..1b48402 100644
--- a/ansible/roles/cis/tasks/users.yml
+++ b/ansible/roles/cis/tasks/users.yml
@@ -5,13 +5,17 @@
name: "{{ item }}"
state: absent
remove: true
+ loop: "{{ delete_users }}"
register: remove_users
- with_items:
- - "{{ delete_users }}"
- failed_when: >
- remove_users is not success and
- not ("not removing" in remove_users.msg or
- "not found" in remove_users.msg)
+ ignore_errors: true
+ tags:
+ - users
+
+- name: Show warning for users that could not be removed
+ debug:
+ msg: "Could not remove user '{{ item.item }}'. Error: {{ item.msg | default('unknown error') }}"
+ loop: "{{ remove_users.results | selectattr('failed', 'equalto', true) | list }}"
+ when: remove_users is defined
tags:
- users
diff --git a/ansible/roles/duo/tasks/main.yml b/ansible/roles/duo/tasks/main.yml
index 9abd606..84bef13 100644
--- a/ansible/roles/duo/tasks/main.yml
+++ b/ansible/roles/duo/tasks/main.yml
@@ -47,9 +47,9 @@
- name: Add Duo Source (RedHat)
become: true
ansible.builtin.yum_repository:
- name: Duo Security
+ name: duo-security
description: Duo Security Repository
- baseurl: https://pkg.duosecurity.com/RHEL/$releasever/$basearch
+ baseurl: https://pkg.duosecurity.com/Fedora/$releasever/$basearch
gpgcheck: true
gpgkey: https://duo.com/DUO-GPG-PUBLIC-KEY.asc
enabled: true
@@ -57,7 +57,7 @@
- name: Install Duo Unix Application Integration
become: true
ansible.builtin.dnf:
- name: duo-unix
+ name: duo_unix
state: present
- name: Install Duo config
diff --git a/ansible/roles/login/tasks/main.yml b/ansible/roles/login/tasks/main.yml
index ed3aeb4..6608cf4 100644
--- a/ansible/roles/login/tasks/main.yml
+++ b/ansible/roles/login/tasks/main.yml
@@ -11,17 +11,20 @@
password: "{{ lookup('env', 'USER_PASSWORD_' + (item.username | upper)) | password_hash('sha512', user_password_salt) }}"
state: "{{ 'absent' if item.enabled is defined and not item.enabled else 'present' }}"
shell: "{{ item.shell if item.shell is defined else '/bin/bash' }}"
+ groups: "{{ item.groups | default(omit) }}"
+ uid: "{{ item.uid | default(omit) }}"
loop: "{{ login_users }}"
+
- name: Disable password expiration
ansible.builtin.command: chage -M -1 "{{ item.username }}"
- become: yes
+ become: true
when: item.password_expiration is defined and not item.password_expiration
loop: "{{ login_users }}"
- name: Disable password login
ansible.builtin.command: passwd -d "{{ item.username }}"
- become: yes
+ become: true
when: item.password_disabled is defined and item.password_disabled
loop: "{{ login_users }}"
diff --git a/ansible/templates/99-qemu-nvme.rules.j2 b/ansible/templates/99-qemu-nvme.rules.j2
new file mode 100644
index 0000000..e65c83d
--- /dev/null
+++ b/ansible/templates/99-qemu-nvme.rules.j2
@@ -0,0 +1,3 @@
+{% for dev in virt_raw_block_devices %}
+KERNEL=="{{ dev }}", OWNER="qemu", GROUP="kvm", MODE="0660"
+{% endfor %}
\ No newline at end of file
diff --git a/ansible/templates/blacklist.conf.j2 b/ansible/templates/blacklist.conf.j2
new file mode 100644
index 0000000..7be0dd5
--- /dev/null
+++ b/ansible/templates/blacklist.conf.j2
@@ -0,0 +1,3 @@
+{% for driver in virt_blacklist %}
+blacklist {{ driver }}
+{% endfor %}
\ No newline at end of file
diff --git a/ansible/templates/domain.xml.j2 b/ansible/templates/domain.xml.j2
new file mode 100644
index 0000000..d5de25a
--- /dev/null
+++ b/ansible/templates/domain.xml.j2
@@ -0,0 +1,255 @@
+
+ {{ vm.name }}
+ {{ vm.uuid }}
+ {{ vm.title }}
+ {{ vm.memory }}
+ {{ vm.memory }}
+
+
+
+
+
+ {{ vm.cores * vm.threads }}
+
+ {% set pairs = vm.physical_cpus.split(',') %}
+ {% set ns = namespace(vcpu=0) %}
+ {% for pair in pairs %}
+ {% set parts = pair.split('-') %}
+
+ {% set ns.vcpu = ns.vcpu + 1 %}
+
+ {% set ns.vcpu = ns.vcpu + 1 %}
+ {% endfor %}
+
+
+
+ hvm
+ /usr/share/edk2/ovmf/OVMF_CODE{% if vm.secure_boot %}.secboot{% endif %}.fd
+ /var/lib/libvirt/qemu/nvram/{{ vm.name }}_VARS.fd
+
+
+
+
+
+
+{% if vm.enable_hyperv is defined %}
+ {% if vm.enable_hyperv | default(false) %}
+
+
+
+
+
+
+ {% endif %}
+{% endif %}
+
+
+
+
+
+
+
+
+
+
+{% if vm.enable_hyperv is defined %}
+ {% if vm.enable_hyperv | default(false) %}
+
+ {% endif %}
+{% endif %}
+
+ destroy
+ restart
+ destroy
+
+
+
+
+
+ {{ vm.emulator | default("/usr/bin/qemu-system-x86_64") }}
+
+
+
+
+
+
+
+ {% for block_dev in vm.block_devs %}
+
+
+
+
+
+ {% endfor %}
+ {% if vm.cdrom %}
+
+
+
+
+
+
+ {% endif %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% if vm.smartcard is defined %}
+ {% if vm.smartcard | default(false) %}
+
+
+
+
+ {% endif %}
+ {% endif %}
+ {% if vm.virtio_fs is defined %}
+ {% if vm.virtio_fs | default(false) %}
+
+
+
+
+
+ {% endif %}
+ {% endif %}
+
+
+
+
+
+
+ {% if vm.tablet is defined %}
+ {% if vm.tablet | default(false) %}
+
+ {% endif %}
+ {% endif %}
+ {% if vm.console %}
+
+
+
+
+
+
+
+
+ {% endif %}
+
+
+ {% if vm.tpm %}
+
+
+
+ {% endif %}
+ {% if vm.audio %}
+
+ {% endif %}
+{% for dev in vm.host_devs %}
+ {% if dev.type == 'mdev' %}
+
+
+
+
+ {% elif dev.type == 'pci' %}
+
+
+
+
+ {% endif %}
+ {% if dev.address is defined %}
+
+ {% endif %}
+
+{% endfor %}
+
+
+
+
+
\ No newline at end of file
diff --git a/inventory/hosts b/inventory/hosts
index 28b0904..4301a88 100644
--- a/inventory/hosts
+++ b/inventory/hosts
@@ -5,6 +5,7 @@ dev-01.alexpires.dev
[hardening]
prod-01.alexpires.me
dev-01.alexpires.dev
+vh-01.alexpires.dev
[ubuntu]
prod-01.alexpires.me
@@ -15,6 +16,7 @@ prod-01.alexpires.me
[private]
dev-01.alexpires.dev
+vh-01.alexpires.dev
[gitea]
prod-01.alexpires.me
@@ -48,3 +50,11 @@ prod-01.alexpires.me
[trivy]
prod-01.alexpires.me
+
+[virtualization]
+vh-01.alexpires.dev
+
+[2fa]
+prod-01.alexpires.me
+dev-01.alexpires.dev
+vh-01.alexpires.dev
diff --git a/scripts/cpu_power_monitor.py b/scripts/cpu_power_monitor.py
index 7e55978..f115b38 100644
--- a/scripts/cpu_power_monitor.py
+++ b/scripts/cpu_power_monitor.py
@@ -1,33 +1,38 @@
import time
import os
-RAPL_PATH = "/sys/class/powercap/intel-rapl:0/energy_uj"
+RAPL_PATH = "/sys/class/powercap/intel-rapl:0/energy_uj"
+INTERVAL_SEC = 1.0 # configurable via command-line argument or env var
-def read_energy():
+def read_energy(path):
try:
- with open(RAPL_PATH, "r") as f:
+ with open(path, "r") as f:
return int(f.read().strip())
except FileNotFoundError:
- print(f"Error: {RAPL_PATH} not found.")
- exit(1)
+ raise RuntimeError(f"RAPL support not available: {path}")
-def calculate_power(interval=1.0):
- print(f"Monitoring CPU package power every {interval} second(s)... (Ctrl+C to stop)")
- while True:
- energy_before = read_energy()
- time.sleep(interval)
- energy_after = read_energy()
-
- delta_uj = energy_after - energy_before
- power_watts = (delta_uj / 1_000_000) / interval
-
- print(f"Power Usage: {power_watts:.2f} Watts")
+def calculate_power(energy_before, energy_after, interval_sec):
+ delta_uj = energy_after - energy_before
+ power_watts = (delta_uj / 1_000_000) / interval_sec
+ return f"{power_watts:.2f} Watts"
if __name__ == "__main__":
if os.geteuid() != 0:
print("Please run this script as root.")
exit(1)
+
try:
- calculate_power(interval=1.0)
+ # RAPL support check
+ with open(RAPL_PATH, "r") as f:
+ _ = int(f.read().strip())
+
+ while True:
+ energy_before = read_energy(RAPL_PATH)
+ time.sleep(INTERVAL_SEC)
+ energy_after = read_energy(RAPL_PATH)
+
+ power_reading = calculate_power(energy_before, energy_after, INTERVAL_SEC)
+ print(f"Power Usage: {power_reading}")
+
except KeyboardInterrupt:
print("\nStopped.")
\ No newline at end of file