What i am curious is the following - as information provided is like at an absolute minimum....
- Why do you want to automate a full install of a Proxmox server ?
=> (in my opinion) the times you (re-)install a server is like not a day-2-day task
If you were running a cluster then sometimes add or reinstall of a node can be helpfull, still this again should be not a day-2-day task ?
For maintaining multiple (running) PVE boxes i would opt for automating it, so they are kept in check in regards of version/config.
Again this also means caution, as running ( like me ) a HA-cluster and a separate development-box keeping it in check with Ansible means you cannot simply issue a reboot from the playbook unless you defined parameters to separate the cluster from the dev box.
This in essence means if it is not defined the playbook could down all clusternodes after running it.
Just for info, this is one of the playbooks i have in use :
YAML:
---
# ./roles/proxmox/tasks/main.yml
- name: Add HP repository into sources list using specified filename
ansible.builtin.apt_repository:
repo: deb http://downloads.linux.hpe.com/SDR/repo/mcp buster/current non-free
state: present
filename: mcp
- name: Add ProxMox free repository into sources list using specified filename (Debian 10)
ansible.builtin.apt_repository:
repo: deb http://download.proxmox.com/debian buster pve-no-subscription
state: present
filename: pve-install-repo
when:
- ansible_facts['distribution'] == "Debian"
- ansible_facts['distribution_major_version'] == "10"
- name: Remove ProxMox Enterprise repository from sources list using specified filename (Debian 10)
ansible.builtin.apt_repository:
repo: deb https://enterprise.proxmox.com/debian/pve buster pve-enterprise
state: absent
filename: pve-enterprise
when:
- ansible_facts['distribution'] == "Debian"
- ansible_facts['distribution_major_version'] == "10"
- name: Add ProxMox free repository into sources list using specified filename (Debian 11)
ansible.builtin.apt_repository:
repo: deb http://download.proxmox.com/debian/pve bullseye pve-no-subscription
state: present
filename: pve-install-repo
when:
- ansible_facts['distribution'] == "Debian"
- ansible_facts['distribution_major_version'] == "11"
- name: Remove ProxMox Enterprise repository from sources list using specified filename (Debian 11)
ansible.builtin.apt_repository:
repo: deb https://enterprise.proxmox.com/debian/pve bullseye pve-enterprise
state: absent
filename: pve-enterprise
when:
- ansible_facts['distribution'] == "Debian"
- ansible_facts['distribution_major_version'] == "11"
- name: register hostname to later determine if its part of a cluster
ansible.builtin.command: 'hostname --fqdn'
register: nodename
- name: Install additional packages needed for ProxMox Cluster environment
ansible.builtin.apt:
name:
- lvm2-lockd
- dlm-controld
- gfs2-utils
state: present
when: nodename.stdout is regex("^node0?\.*.")
- name: Update apt-get repo and cache
ansible.builtin.apt:
update_cache: yes
force_apt_get: yes
cache_valid_time: 3600
- name: Upgrade all apt packages
ansible.builtin.apt:
upgrade: dist
force_apt_get: yes
- name: Check if a reboot is needed for ProxMox boxes
ansible.builtin.stat:
path: /var/run/reboot-required
register: check_reboot
- name: Print information about reboot
ansible.builtin.debug:
var: check_reboot
- name: Ensure customised dlm.conf is present
ansible.builtin.template:
src: 'dlm.conf.j2'
dest: '/etc/dlm/dlm.conf'
mode: 0600
when: nodename.stdout is regex("^node0?\.*.")
- name: Ensure lvm.conf contains lvmlockd = 1
ansible.builtin.template:
src: 'lvm.conf.j2'
dest: '/etc/lvm/lvm.conf'
mode: 0600
when: nodename.stdout is regex("^node0?\.*.")
- name: Ensure shared volumes and mountpoint definition file is present
ansible.builtin.template:
src: 'lvmshared.conf.j2'
dest: '/etc/lvm/lvmshared.conf'
mode: 0600
when: nodename.stdout is regex("^node0?\.*.")
- name: Ensure the mountscript for shared volume is available
ansible.builtin.template:
src: lvmmount.sh.j2
dest: '/usr/local/share/lvmmount.sh'
mode: 0700
when: nodename.stdout is regex("^node0?\.*.")
- name: Ensure Systemd service for shared volumes is present
ansible.builtin.template:
src: 'lvshared.service.j2'
dest: '/usr/lib/systemd/system/lvshared.service'
mode: 0644
when: nodename.stdout is regex("^node0?\.*.")
- name: Ensure SystemD service pve-guests has a After=lvshared.service entry
ansible.builtin.lineinfile:
path: /usr/lib/systemd/system/pve-guests.service
regexp: '^After=lvshared.service'
insertafter: '^After=pve-ha-crm.service$'
line: After=lvshared.service
mode: 0644
when: nodename.stdout is regex("^node0?\.*.")
- name: Force systemd to reread configs (2.4 and above)
ansible.builtin.systemd:
daemon_reload: yes
- name: check if /etc/ssh/ssh_known_hosts is present
ansible.builtin.stat:
path: /etc/ssh/ssh_known_hosts
get_checksum: no
register: ssh_known_hosts_stat
- name: Delete /etc/ssh/ssh_known_hosts
ansible.builtin.file:
path: /etc/ssh/ssh_known_hosts
state: absent
when: ssh_known_hosts_stat.stat.exists
- name: Symlink /etc/ssh/ssh_known_hosts to /etc/pve/priv/known_hosts
ansible.builtin.file:
src: /etc/pve/priv/known_hosts
dest: /etc/ssh/ssh_known_hosts
owner: root
state: link
- name: Add nodes to known_hosts
ansible.builtin.known_hosts:
path: /etc/pve/priv/known_hosts
name: '{{ item.name }}'
key: '{{ item.name }} {{ item.key }}'
loop: '{{ my_node_keys }}'
no_log: true
when: nodename.stdout is regex("^node0?\.*.")
- name: check if /root/.ssh/ssh_known_hosts is present
ansible.builtin.stat:
path: /root/.ssh/known_hosts
get_checksum: no
register: root_known_hosts_stat
- name: Delete /root/.ssh/known_hosts
ansible.builtin.file:
path: /root/.ssh/known_hosts
state: absent
when: root_known_hosts_stat.stat.exists
- name: Symlink /root/.ssh/known_hosts to /etc/pve/priv/known_hosts
ansible.builtin.file:
src: /etc/pve/priv/known_hosts
dest: /root/.ssh/known_hosts
owner: root
state: link
- name: Set up Node authorized keys
ansible.posix.authorized_key:
manage_dir: no
path: /etc/pve/priv/authorized_keys
user: root
state: present
key: '{{ item.key }}'
loop: '{{ my_node_keys }}'
no_log: true
when: nodename.stdout is regex("^node0?\.*.")
Disclaimer : i am still working on this playbook - so concider this a work-in-progress.