Establish clean homelab infrastructure baseline
Reorganize the brownfield repository, remove retired and generated artifacts, harden ignore rules, and record the GitOps/IaC redesign.
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
---
|
||||
# dc_vm role — create the DC's Ubuntu VM locally via libvirt + cloud-init (NoCloud).
|
||||
# Runs on the libvirt host (localhost). Configures nothing inside the OS beyond the
|
||||
# cloud-init seed; the samba_ad_dc role does the AD provisioning afterward.
|
||||
|
||||
dc_vm_name: "{{ samba_ad_dc_hostname | default('dc1') }}"
|
||||
dc_vm_vcpus: 2
|
||||
dc_vm_memory_mb: 2048
|
||||
dc_vm_disk_gb: 25
|
||||
|
||||
# Latest Ubuntu LTS cloud image (24.04 Noble). "current" always points at the newest build.
|
||||
dc_vm_image_url: "https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img"
|
||||
dc_vm_osinfo: "ubuntu24.04"
|
||||
|
||||
# libvirt placement.
|
||||
# The VM root disk is a ZFS zvol (matches data/vm/win2k25 convention).
|
||||
# dc_vm_images_dir only holds the small base image + the cloud-init seed ISO (files).
|
||||
dc_vm_images_dir: "/var/lib/libvirt/images"
|
||||
dc_vm_bridge: "br0" # LAN bridge → puts the DC on 192.168.10.0/24
|
||||
|
||||
# ZFS zvol for the root disk
|
||||
dc_vm_zvol_parent: "data/vm" # parent dataset, one zvol per VM
|
||||
dc_vm_zvol: "{{ dc_vm_zvol_parent }}/{{ dc_vm_name }}"
|
||||
dc_vm_zvol_dev: "/dev/zvol/{{ dc_vm_zvol }}"
|
||||
dc_vm_zvol_volblocksize: "16K" # matches existing VMs
|
||||
dc_vm_zvol_sparse: false # thick-provisioned like data/vm/win2k25
|
||||
|
||||
# Networking for the guest (static — AD requires it). Pulls from group_vars/all.yml.
|
||||
dc_vm_ip: "{{ samba_ad_dc_ip }}"
|
||||
dc_vm_prefix: 24
|
||||
dc_vm_gateway: "192.168.10.1"
|
||||
dc_vm_boot_dns: "{{ samba_ad_dns_forwarder }}" # first-boot resolver (before it is its own DNS)
|
||||
|
||||
# Cloud-init login user + the public key Ansible will connect with.
|
||||
dc_vm_user: "ansible"
|
||||
dc_vm_ssh_pubkey_file: "~/.ssh/id_ed25519.pub" # generate with: ssh-keygen -t ed25519
|
||||
@@ -0,0 +1,113 @@
|
||||
---
|
||||
# Create the DC VM on the local libvirt host. Idempotent: if the domain already
|
||||
# exists it does nothing. Run on localhost with qemu:///system (become: true).
|
||||
|
||||
- name: Resolve the SSH public key to inject
|
||||
ansible.builtin.set_fact:
|
||||
dc_vm_ssh_pubkey: "{{ lookup('file', dc_vm_ssh_pubkey_file | expanduser) }}"
|
||||
|
||||
- name: Fail early if no usable public key
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- dc_vm_ssh_pubkey is search('^ssh-')
|
||||
fail_msg: >-
|
||||
No SSH public key at {{ dc_vm_ssh_pubkey_file }}. Generate one
|
||||
(ssh-keygen -t ed25519) or set dc_vm_ssh_pubkey_file.
|
||||
|
||||
- name: Check whether the libvirt domain already exists
|
||||
ansible.builtin.command: "virsh dominfo {{ dc_vm_name }}"
|
||||
register: dc_vm_dominfo
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Create the VM
|
||||
when: dc_vm_dominfo.rc != 0
|
||||
block:
|
||||
- name: Ensure image directories exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
mode: "0711"
|
||||
loop:
|
||||
- "{{ dc_vm_images_dir }}"
|
||||
- "{{ dc_vm_images_dir }}/base"
|
||||
|
||||
- name: Download the Ubuntu cloud image (once)
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ dc_vm_image_url }}"
|
||||
dest: "{{ dc_vm_images_dir }}/base/{{ dc_vm_image_url | basename }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Check whether the root-disk zvol already exists
|
||||
ansible.builtin.command: "zfs list -H -o name {{ dc_vm_zvol }}"
|
||||
register: dc_vm_zvol_check
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Create the root-disk zvol
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
zfs create {{ '-s ' if dc_vm_zvol_sparse else '' }}-V {{ dc_vm_disk_gb }}G
|
||||
-o volblocksize={{ dc_vm_zvol_volblocksize }}
|
||||
{{ dc_vm_zvol }}
|
||||
when: dc_vm_zvol_check.rc != 0
|
||||
|
||||
- name: Wait for the zvol device node to appear
|
||||
ansible.builtin.wait_for:
|
||||
path: "{{ dc_vm_zvol_dev }}"
|
||||
timeout: 30
|
||||
when: dc_vm_zvol_check.rc != 0
|
||||
|
||||
- name: Write the cloud image into the zvol (raw)
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
qemu-img convert -O raw
|
||||
{{ dc_vm_images_dir }}/base/{{ dc_vm_image_url | basename }}
|
||||
{{ dc_vm_zvol_dev }}
|
||||
when: dc_vm_zvol_check.rc != 0
|
||||
# cloud-init growpart expands the rootfs to fill the zvol on first boot.
|
||||
|
||||
- name: Render the cloud-init seed files
|
||||
ansible.builtin.template:
|
||||
src: "{{ item }}.j2"
|
||||
dest: "{{ dc_vm_images_dir }}/{{ dc_vm_name }}-seed-{{ item }}"
|
||||
mode: "0644"
|
||||
loop:
|
||||
- user-data
|
||||
- meta-data
|
||||
- network-config
|
||||
|
||||
- name: Build the NoCloud seed ISO
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
genisoimage -output {{ dc_vm_images_dir }}/{{ dc_vm_name }}-seed.iso
|
||||
-volid cidata -joliet -rock
|
||||
-graft-points
|
||||
user-data={{ dc_vm_images_dir }}/{{ dc_vm_name }}-seed-user-data
|
||||
meta-data={{ dc_vm_images_dir }}/{{ dc_vm_name }}-seed-meta-data
|
||||
network-config={{ dc_vm_images_dir }}/{{ dc_vm_name }}-seed-network-config
|
||||
args:
|
||||
creates: "{{ dc_vm_images_dir }}/{{ dc_vm_name }}-seed.iso"
|
||||
|
||||
- name: Define and start the domain (cloud-init imports the disk)
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
virt-install
|
||||
--name {{ dc_vm_name }}
|
||||
--memory {{ dc_vm_memory_mb }}
|
||||
--vcpus {{ dc_vm_vcpus }}
|
||||
--osinfo require=off,name={{ dc_vm_osinfo }}
|
||||
--disk path={{ dc_vm_zvol_dev }},format=raw,bus=virtio
|
||||
--disk path={{ dc_vm_images_dir }}/{{ dc_vm_name }}-seed.iso,device=cdrom
|
||||
--network bridge={{ dc_vm_bridge }},model=virtio
|
||||
--graphics none --noautoconsole --import
|
||||
register: virt_install
|
||||
changed_when: true
|
||||
|
||||
- name: Wait for SSH on the new DC
|
||||
ansible.builtin.wait_for:
|
||||
host: "{{ dc_vm_ip }}"
|
||||
port: 22
|
||||
delay: 10
|
||||
timeout: 300
|
||||
when: dc_vm_dominfo.rc != 0
|
||||
@@ -0,0 +1,2 @@
|
||||
instance-id: {{ dc_vm_name }}-001
|
||||
local-hostname: {{ dc_vm_name }}
|
||||
@@ -0,0 +1,20 @@
|
||||
version: 2
|
||||
ethernets:
|
||||
primary:
|
||||
# Match the (single) ethernet NIC by kernel name and configure it in place.
|
||||
# NOTE: do NOT add set-name here — netplan only supports set-name when matching
|
||||
# on mac/driver, not on name, and a name-match + rename leaves the NIC unconfigured.
|
||||
match:
|
||||
name: "en*"
|
||||
dhcp4: false
|
||||
dhcp6: false
|
||||
addresses:
|
||||
- {{ dc_vm_ip }}/{{ dc_vm_prefix }}
|
||||
routes:
|
||||
- to: default
|
||||
via: {{ dc_vm_gateway }}
|
||||
nameservers:
|
||||
addresses:
|
||||
- {{ dc_vm_boot_dns }}
|
||||
search:
|
||||
- {{ samba_ad_realm | lower }}
|
||||
@@ -0,0 +1,20 @@
|
||||
#cloud-config
|
||||
# NoCloud user-data for the Samba AD DC base VM.
|
||||
hostname: {{ dc_vm_name }}
|
||||
fqdn: {{ dc_vm_name }}.{{ samba_ad_realm | lower }}
|
||||
# /etc/hosts is owned by the samba_ad_dc role (pins FQDN to the real IP), not cloud-init.
|
||||
manage_etc_hosts: false
|
||||
preserve_hostname: false
|
||||
|
||||
users:
|
||||
- name: {{ dc_vm_user }}
|
||||
groups: [sudo]
|
||||
shell: /bin/bash
|
||||
sudo: "ALL=(ALL) NOPASSWD:ALL"
|
||||
lock_passwd: true
|
||||
ssh_authorized_keys:
|
||||
- {{ dc_vm_ssh_pubkey }}
|
||||
|
||||
ssh_pwauth: false
|
||||
package_update: true
|
||||
package_upgrade: false
|
||||
Reference in New Issue
Block a user