feat(nh3-svos): VM 111 on nh3-pve-2 for the new SVOS (svos-dev, Prime); generic cloud-init VM playbook
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
# Generic: create a Debian 13 genericcloud VM on nh3-pve-2 with cloud-init (user vh with the operator's keys plus
|
||||
# the infra-ops bootstrap key, static address on VLAN 50). Same steps as playbooks/nh3-albok-vm.yaml, parameterised.
|
||||
# scripts/elway infra-ops@10.100.250.62 --playbook playbooks/nh3-pve-2-cloudinit-vm.yaml \
|
||||
# --var vmid=111 --var name=nh3-svos --var ip=10.100.50.43/24 --var cores=4 --var memory=8192 --var disk=100G \
|
||||
# --var tags=svos --var "description=..."
|
||||
# Then: bootstrap-infra-ops-user.yaml AS vh, then the host's own base playbook (which takes the bootstrap key off vh).
|
||||
vars:
|
||||
vmid: ""
|
||||
name: ""
|
||||
ip: ""
|
||||
gw: 10.100.50.1
|
||||
dns: 10.100.50.40 10.250.50.70
|
||||
cores: "4"
|
||||
memory: "8192"
|
||||
disk: 100G
|
||||
tags: ""
|
||||
description: ""
|
||||
img_url: https://cloud.debian.org/images/cloud/trixie/latest
|
||||
img: debian-13-genericcloud-amd64.qcow2
|
||||
img_dir: /var/lib/vz/import
|
||||
|
||||
steps:
|
||||
- name: refuse unless this is nh3-pve-2, vmbr0 is VLAN-aware, and the VMID and address are free
|
||||
sudo: true
|
||||
shell: |
|
||||
set -e
|
||||
test "$(hostname)" = nh3-pve-2
|
||||
test "$(cat /sys/class/net/vmbr0/bridge/vlan_filtering)" = 1
|
||||
if ping -c2 -W1 $(echo {{ ip }} | cut -d/ -f1) >/dev/null 2>&1; then echo "{{ ip }} ANSWERS — taken"; exit 1; fi
|
||||
changed_when: "false"
|
||||
when: "! qm status {{ vmid }} >/dev/null 2>&1"
|
||||
|
||||
- name: fetch the Debian 13 genericcloud image and check it against SHA512SUMS
|
||||
sudo: true
|
||||
shell: |
|
||||
set -e
|
||||
install -d -m 0755 {{ img_dir }}
|
||||
cd {{ img_dir }}
|
||||
curl -fsSL -o SHA512SUMS.trixie {{ img_url }}/SHA512SUMS
|
||||
curl -fsSL -o {{ img }}.part {{ img_url }}/{{ img }}
|
||||
want=$(awk '$2=="{{ img }}"{print $1}' SHA512SUMS.trixie)
|
||||
test -n "$want"
|
||||
echo "$want {{ img }}.part" | sha512sum -c -
|
||||
mv {{ img }}.part {{ img }}
|
||||
when: "! qm status {{ vmid }} >/dev/null 2>&1"
|
||||
|
||||
- name: create VM {{ vmid }} ({{ name }})
|
||||
sudo: true
|
||||
shell: |
|
||||
set -e
|
||||
qm create {{ vmid }} --name {{ name }} --ostype l26 --cpu x86-64-v3 --cores {{ cores }} --memory {{ memory }} \
|
||||
--scsihw virtio-scsi-single --agent enabled=1 --onboot 1 --tags {{ tags }} \
|
||||
--net0 virtio,bridge=vmbr0,tag=50,firewall=1 \
|
||||
--serial0 socket --vga serial0 \
|
||||
--description "{{ description }}"
|
||||
qm set {{ vmid }} --scsi0 vmstore:0,import-from={{ img_dir }}/{{ img }},discard=on,ssd=1,iothread=1
|
||||
qm disk resize {{ vmid }} scsi0 {{ disk }}
|
||||
qm set {{ vmid }} --ide2 vmstore:cloudinit --boot order=scsi0
|
||||
creates: /etc/pve/qemu-server/{{ vmid }}.conf
|
||||
|
||||
- name: cloud-init — user vh, keys, static address, resolvers
|
||||
sudo: true
|
||||
shell: |
|
||||
set -e
|
||||
k=$(mktemp)
|
||||
cat > "$k" <<'EOF'
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN+1HBwfXrkfTYWdcnWCjLJ6VLAGC87gxH5h5vKaaA3c infra-ops@pfi-fleet
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKGm/lJslGEL2xDBY/7LdUc0Q4GyuxwFtGspYTe6WsVE lkrav@VHHomeG13
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDP/AwgaLghPoQi9RDt+m/9H9jLHDoP93WgzczlhZlSvZoQ5qDpWu5oAQlRwImiWhVL1ClK4FwEz9JULsta7Uq3FaiQvs2ltevrW/EpNbhAfxZa4Z1ELrPAOO8SSlhZ+Zer33SPkfJD9t3Hi9TXheCaANiEtE6hH1nCVLpHWQdbzy+L7EyG8z+/RzNXwwIL8f0BZ8n7FvFujgwc1OQTXlg4fiW3FdB3uzJMVRT59IIsPEq/ODGZZ6XGtHy24Ewcsi8l78I+oKaPdMl8ZXNBQrNb0MPIJnHkQwTrzlDKZ0Oh1UKm7I9i9hDMB/M2+aQ+6MxzY5TLZyDvRYd8R3j9Mnrp3ouCnNcklGAkX7i8hNJ2y8xCbwOeP8sMd+VtQ6hBbNa6KAEaAgGuWHHS0KGGO4HjtvDxJH8e7BnGzveIeCUGLVKMrg08w9nqF6Kzf3Y72ou0yCmnu7kKqocS1Pcr+e5E1MdT4brc2BfYkzqExLp8gxQaJ1Zas2OXPNXpAxL58xc= lkraven@nh3-dev
|
||||
EOF
|
||||
sed -i 's/^ *//' "$k"
|
||||
qm set {{ vmid }} --ciuser vh --sshkeys "$k" --ipconfig0 ip={{ ip }},gw={{ gw }} \
|
||||
--nameserver "{{ dns }}" --searchdomain nh3.internal --ciupgrade 1
|
||||
rm -f "$k"
|
||||
when: "! qm config {{ vmid }} | grep -q '^ciuser: vh'"
|
||||
|
||||
- name: start VM {{ vmid }}
|
||||
sudo: true
|
||||
shell: qm start {{ vmid }}
|
||||
when: "! qm status {{ vmid }} | grep -q running"
|
||||
|
||||
verify:
|
||||
- name: VM is running with the intended shape
|
||||
sudo: true
|
||||
shell: |
|
||||
qm status {{ vmid }}
|
||||
qm config {{ vmid }} | grep -E '^(name|cores|cpu|memory|net0|scsi0|ipconfig0|onboot|ciuser):'
|
||||
qm status {{ vmid }} | grep -q running
|
||||
changed_when: "false"
|
||||
@@ -0,0 +1,80 @@
|
||||
# Base build for nh3-svos (VM 111 on nh3-pve-2, 10.100.50.43): the host for the NEW SVOS operating system
|
||||
# (corviduo/svoperatingsystem). Requested by svos-dev relaying Prime, 2026-10-05. A SEPARATE instance: the existing
|
||||
# High Seat (svos.service on nh3-dev :8770) and Miranda are untouched.
|
||||
# scripts/elway infra-ops@10.100.50.43 --playbook playbooks/nh3-svos-host.yaml
|
||||
# Order: nh3-pve-2-cloudinit-vm.yaml (on nh3-pve-2) → bootstrap-infra-ops-user.yaml AS vh → this.
|
||||
#
|
||||
# Infra owns the box; svos-dev owns the application (install, config, enrollment, acceptance). What this provides:
|
||||
# - service account `svc-svos` (uid/gid 801, nologin; fleet-conventions § 1.3), the only writer of the data root
|
||||
# - /var/lib/svos svc-svos 0700, LOCAL ext4 (the root disk on vmstore): SQLite WAL, one writer, never shared/NFS
|
||||
# - /opt/svos root:svc-svos 2775, the release tree (releases/<id>/ + a `current` link; svos-dev lays it out)
|
||||
# - Python 3.13 (Debian 13) + venv, sqlite3, qemu-guest-agent (vzdump freeze/thaw), timesyncd checked
|
||||
# - /etc/qemu/fsfreeze-hook.d/ exists for the application-consistent snapshot hook svos-dev will add (the guest
|
||||
# agent runs those scripts on vzdump's freeze/thaw)
|
||||
# No Docker: nothing here needs it.
|
||||
steps:
|
||||
- name: take the bootstrap infra-ops key back off vh (vh keeps the operator's keys)
|
||||
sudo: true
|
||||
shell: |
|
||||
set -e
|
||||
f=/home/vh/.ssh/authorized_keys
|
||||
grep -v 'infra-ops@pfi-fleet' "$f" > "$f.new"
|
||||
test -s "$f.new"
|
||||
chown vh:vh "$f.new"; chmod 600 "$f.new"; mv "$f.new" "$f"
|
||||
when: "sudo -n grep -q 'infra-ops@pfi-fleet' /home/vh/.ssh/authorized_keys"
|
||||
|
||||
- name: timezone America/Los_Angeles
|
||||
sudo: true
|
||||
shell: timedatectl set-timezone America/Los_Angeles
|
||||
when: "[ \"$(timedatectl show -p Timezone --value)\" != America/Los_Angeles ]"
|
||||
|
||||
- name: base packages
|
||||
sudo: true
|
||||
shell: DEBIAN_FRONTEND=noninteractive apt-get install -y -q qemu-guest-agent python3 python3-venv sqlite3 rsync jq curl ca-certificates
|
||||
when: "! dpkg -s qemu-guest-agent python3-venv sqlite3 rsync jq >/dev/null 2>&1"
|
||||
|
||||
- name: qemu-guest-agent running
|
||||
sudo: true
|
||||
shell: systemctl start qemu-guest-agent
|
||||
when: "! systemctl is-active --quiet qemu-guest-agent"
|
||||
|
||||
- name: fsfreeze hook directory for the application-consistent snapshot hook
|
||||
sudo: true
|
||||
shell: install -d -o root -g root -m 0755 /etc/qemu/fsfreeze-hook.d
|
||||
changed_when: "false"
|
||||
|
||||
- name: service account svc-svos (uid/gid 801, nologin, home = the data root)
|
||||
sudo: true
|
||||
shell: |
|
||||
set -e
|
||||
getent group 801 >/dev/null && { echo "gid 801 taken"; exit 1; }
|
||||
getent passwd 801 >/dev/null && { echo "uid 801 taken"; exit 1; }
|
||||
groupadd --system --gid 801 svc-svos
|
||||
useradd --system --uid 801 --gid 801 --shell /usr/sbin/nologin --home-dir /var/lib/svos --no-create-home svc-svos
|
||||
when: "! getent passwd svc-svos >/dev/null"
|
||||
|
||||
- name: data root /var/lib/svos (svc-svos 0700) and release tree /opt/svos (root:svc-svos 2775)
|
||||
sudo: true
|
||||
shell: |
|
||||
install -d -o svc-svos -g svc-svos -m 0700 /var/lib/svos
|
||||
install -d -o root -g svc-svos -m 2775 /opt/svos /opt/svos/releases
|
||||
changed_when: "false"
|
||||
|
||||
verify:
|
||||
- name: identities are the fleet pins
|
||||
shell: |
|
||||
test "$(id -u vh)" = 1000 && test "$(id -u infra-ops)" = 850 && test "$(id -u svc-svos)" = 801
|
||||
changed_when: "false"
|
||||
- name: vh no longer carries the infra-ops key
|
||||
sudo: true
|
||||
shell: "! grep -q 'infra-ops@pfi-fleet' /home/vh/.ssh/authorized_keys"
|
||||
changed_when: "false"
|
||||
- name: data root is local ext4 and private
|
||||
sudo: true
|
||||
shell: |
|
||||
test "$(findmnt -T /var/lib/svos -no FSTYPE)" = ext4 && test "$(stat -c '%U %a' /var/lib/svos)" = "svc-svos 700"
|
||||
changed_when: "false"
|
||||
- name: python, sqlite, guest agent, time sync
|
||||
shell: |
|
||||
python3 --version && sqlite3 --version | cut -c1-20 && systemctl is-active qemu-guest-agent && timedatectl show -p NTPSynchronized --value
|
||||
changed_when: "false"
|
||||
Reference in New Issue
Block a user