Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ba366a55a2 | |||
| 6d352d59be | |||
| f289a3b3bc | |||
| 1c0e994bfb | |||
| 37aeddca6c | |||
| d1568586e9 | |||
| 9a9bfa7e23 | |||
| 95f059c0a8 | |||
| 28791acfda | |||
| ff43d53f53 |
@@ -1,3 +1,6 @@
|
|||||||
# ---> Ansible
|
# ---> Ansible
|
||||||
*.retry
|
*.retry
|
||||||
inventory/group_vars/secret/
|
inventory/group_vars/secret/
|
||||||
|
|
||||||
|
# Ignore python venv
|
||||||
|
.venv
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
physical:
|
physical:
|
||||||
hosts:
|
hosts:
|
||||||
192.168.0.40:
|
192.168.0.45:
|
||||||
ansible_become_password: "{{ ansible_become_passwd }}"
|
ansible_become_password: "{{ ansible_become_passwd }}"
|
||||||
|
|||||||
@@ -15,9 +15,3 @@
|
|||||||
vars:
|
vars:
|
||||||
ansible_user_passwd_hash: "{{ ansible_password | password_hash('sha512', 's3edscrj45e6r') }}"
|
ansible_user_passwd_hash: "{{ ansible_password | password_hash('sha512', 's3edscrj45e6r') }}"
|
||||||
user_passwd_hash: "{{ user_password | password_hash('sha512', 's3ed6123jhgcr') }}"
|
user_passwd_hash: "{{ user_password | password_hash('sha512', 's3ed6123jhgcr') }}"
|
||||||
|
|
||||||
handlers:
|
|
||||||
- name: restart sshd
|
|
||||||
service:
|
|
||||||
name: sshd
|
|
||||||
state: restarted
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
- name: Deploy a virtual machine from a cloud init image
|
||||||
|
hosts: localhost
|
||||||
|
gather_facts: false
|
||||||
|
roles:
|
||||||
|
- ../roles/basic_proxmox_vm
|
||||||
|
|
||||||
|
- name: Basic Proxmox guest deployment
|
||||||
|
hosts: all
|
||||||
|
remote_user: ansible
|
||||||
|
roles:
|
||||||
|
- ../roles/basic_postinstall
|
||||||
|
vars_files:
|
||||||
|
../inventory/group_vars/all/secrets.yaml
|
||||||
|
vars:
|
||||||
|
ansible_user_passwd_hash: "{{ ansible_password | password_hash('sha512', 's3edscrj45e6r') }}"
|
||||||
|
user_passwd_hash: "{{ user_password | password_hash('sha512', 's3ed6123jhgcr') }}"
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: restart ssh-server
|
||||||
|
service:
|
||||||
|
name: ssh
|
||||||
|
state: restarted
|
||||||
|
|
||||||
|
- name: restart sshd-server
|
||||||
|
service:
|
||||||
|
name: sshd
|
||||||
|
state: restarted
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
ansible-compat==26.6.0
|
||||||
|
ansible-core==2.21.1
|
||||||
|
ansible-lint==26.6.0
|
||||||
|
attrs==26.1.0
|
||||||
|
black==26.5.1
|
||||||
|
bracex==3.0
|
||||||
|
cffi==2.1.0
|
||||||
|
click==8.4.2
|
||||||
|
cryptography==49.0.0
|
||||||
|
distro==1.9.0
|
||||||
|
filelock==3.29.7
|
||||||
|
Jinja2==3.1.6
|
||||||
|
jsonschema==4.26.0
|
||||||
|
jsonschema-specifications==2025.9.1
|
||||||
|
MarkupSafe==3.0.3
|
||||||
|
mypy_extensions==1.1.0
|
||||||
|
packaging==26.2
|
||||||
|
pathspec==1.1.1
|
||||||
|
platformdirs==4.10.0
|
||||||
|
pycparser==3.0
|
||||||
|
pytokens==0.4.1
|
||||||
|
PyYAML==6.0.3
|
||||||
|
referencing==0.37.0
|
||||||
|
resolvelib==1.2.1
|
||||||
|
rpds-py==2026.6.3
|
||||||
|
ruamel.yaml==0.19.1
|
||||||
|
ruamel.yaml.clib==0.2.15
|
||||||
|
subprocess-tee==0.4.2
|
||||||
|
wcmatch==11.0
|
||||||
|
yamllint==1.38.0
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
- name: Create a new user with a password, set shell
|
- name: Create a new user with a password, set shell
|
||||||
remote_user: ansible
|
remote_user: ansible
|
||||||
user:
|
ansible.builtin.user:
|
||||||
name: max
|
name: max
|
||||||
groups: sshusers,sudo
|
groups: sshusers,sudo
|
||||||
password: "{{ user_passwd_hash }}"
|
password: "{{ user_passwd_hash }}"
|
||||||
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
- name: Copy omz installation wrapper script to the target machine
|
- name: Copy omz installation wrapper script to the target machine
|
||||||
remote_user: ansible
|
remote_user: ansible
|
||||||
copy:
|
ansible.builtin.copy:
|
||||||
src: ../files/install_omz.sh
|
src: "{{ role_path }}/files/install_omz.sh"
|
||||||
dest: /home/max/install_omz.sh
|
dest: /home/max/install_omz.sh
|
||||||
owner: max
|
owner: max
|
||||||
group: max
|
group: max
|
||||||
@@ -26,13 +26,14 @@
|
|||||||
# WARNING: UNPRIVILEGED USER (not ansible) COMMANDS
|
# WARNING: UNPRIVILEGED USER (not ansible) COMMANDS
|
||||||
- name: Install oh my zsh
|
- name: Install oh my zsh
|
||||||
remote_user: max
|
remote_user: max
|
||||||
become: no
|
become: false
|
||||||
command: /home/max/install_omz.sh
|
ansible.builtin.command: /home/max/install_omz.sh
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
- name: Configure oh my zsh, by pushing the config file
|
- name: Configure oh my zsh, by pushing the config file
|
||||||
remote_user: ansible
|
remote_user: ansible
|
||||||
copy:
|
ansible.builtin.copy:
|
||||||
src: ../files/.zshrc
|
src: "{{ role_path }}/files/.zshrc"
|
||||||
dest: /home/max/.zshrc
|
dest: /home/max/.zshrc
|
||||||
owner: max
|
owner: max
|
||||||
group: max
|
group: max
|
||||||
@@ -40,8 +41,8 @@
|
|||||||
|
|
||||||
- name: Configure vim, by pushing the config
|
- name: Configure vim, by pushing the config
|
||||||
remote_user: ansible
|
remote_user: ansible
|
||||||
copy:
|
ansible.builtin.copy:
|
||||||
src: ../files/.vimrc
|
src: "{{ role_path }}/files/.vimrc"
|
||||||
dest: /home/max/.vimrc
|
dest: /home/max/.vimrc
|
||||||
owner: max
|
owner: max
|
||||||
group: max
|
group: max
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
src: "{{ role_path }}/files/hardened_sshd.conf"
|
src: "{{ role_path }}/files/hardened_sshd.conf"
|
||||||
dest: /etc/ssh/sshd_config.d/hardened_sshd.conf
|
dest: /etc/ssh/sshd_config.d/hardened_sshd.conf
|
||||||
mode: u=rw,g=r,o=r
|
mode: u=rw,g=r,o=r
|
||||||
notify: restart ssh-server
|
|
||||||
when: ansible_facts['distribution'] == 'Ubuntu'
|
when: ansible_facts['distribution'] == 'Ubuntu'
|
||||||
|
|
||||||
- name: Configure ssh-server daemon
|
- name: Configure ssh-server daemon
|
||||||
@@ -13,7 +12,6 @@
|
|||||||
src: "{{ role_path }}/files/hardened_sshd.conf"
|
src: "{{ role_path }}/files/hardened_sshd.conf"
|
||||||
dest: /etc/ssh/sshd_config.d/hardened_sshd.conf
|
dest: /etc/ssh/sshd_config.d/hardened_sshd.conf
|
||||||
mode: u=rw,g=r,o=r
|
mode: u=rw,g=r,o=r
|
||||||
notify: restart sshd-server
|
|
||||||
when: ansible_facts['distribution'] == 'Debian'
|
when: ansible_facts['distribution'] == 'Debian'
|
||||||
|
|
||||||
- name: Configure ssh client
|
- name: Configure ssh client
|
||||||
@@ -22,3 +20,17 @@
|
|||||||
src: "{{ role_path }}/files/hardened_ssh.conf"
|
src: "{{ role_path }}/files/hardened_ssh.conf"
|
||||||
dest: /etc/ssh/ssh_config.d/hardened_ssh.conf
|
dest: /etc/ssh/ssh_config.d/hardened_ssh.conf
|
||||||
mode: u=rw,g=r,o=r
|
mode: u=rw,g=r,o=r
|
||||||
|
|
||||||
|
- name: Restart ssh-server Debian
|
||||||
|
remote_user: ansible
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: sshd
|
||||||
|
state: restarted
|
||||||
|
when: ansible_facts['distribution'] == 'Debian'
|
||||||
|
|
||||||
|
- name: Restart ssh-server Ubuntu
|
||||||
|
remote_user: ansible
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: ssh
|
||||||
|
state: restarted
|
||||||
|
when: ansible_facts['distribution'] == 'Ubuntu'
|
||||||
|
|||||||
@@ -37,6 +37,6 @@
|
|||||||
- name: Update and install packages on Alpine
|
- name: Update and install packages on Alpine
|
||||||
when: (ansible_facts['distribution'] == "Alpine")
|
when: (ansible_facts['distribution'] == "Alpine")
|
||||||
community.general.apk:
|
community.general.apk:
|
||||||
name: vim ranger zsh rsync git curl kitty
|
name: vim ranger zsh rsync git curl kitty openssh
|
||||||
update_cache: true
|
update_cache: true
|
||||||
remote_user: ansible
|
remote_user: ansible
|
||||||
|
|||||||
@@ -3,18 +3,18 @@
|
|||||||
- name: Install sudo on apt systems
|
- name: Install sudo on apt systems
|
||||||
when: (ansible_facts['distribution'] == "Debian") or
|
when: (ansible_facts['distribution'] == "Debian") or
|
||||||
(ansible_facts['distribution'] == "Ubuntu")
|
(ansible_facts['distribution'] == "Ubuntu")
|
||||||
apt:
|
ansible.builtin.apt:
|
||||||
name:
|
name:
|
||||||
- sudo
|
- sudo
|
||||||
update-cache: yes
|
update-cache: true
|
||||||
|
|
||||||
- name: Update Alpine packages
|
# The same commands for Alpine
|
||||||
|
- name: Update and install packages on Alpine
|
||||||
when: (ansible_facts['distribution'] == "Alpine")
|
when: (ansible_facts['distribution'] == "Alpine")
|
||||||
command: /sbin/apk update
|
community.general.apk:
|
||||||
|
name: sudo
|
||||||
- name: Install sudo package on Alpine
|
update_cache: true
|
||||||
when: (ansible_facts['distribution'] == "Alpine")
|
remote_user: ansible
|
||||||
command: /sbin/apk add sudo
|
|
||||||
|
|
||||||
|
|
||||||
## Creating and setting up the ansible user
|
## Creating and setting up the ansible user
|
||||||
@@ -26,12 +26,12 @@
|
|||||||
|
|
||||||
## Add the user to sshusers (for ssh access) and sudo (gain root access)
|
## Add the user to sshusers (for ssh access) and sudo (gain root access)
|
||||||
- name: Create a new user with a password for Ansible
|
- name: Create a new user with a password for Ansible
|
||||||
user:
|
ansible.builtin.user:
|
||||||
name: ansible
|
name: ansible
|
||||||
password: "{{ ansible_user_passwd_hash }}"
|
password: "{{ ansible_user_passwd_hash }}"
|
||||||
|
|
||||||
groups: sshusers,sudo
|
groups: sshusers,sudo
|
||||||
append: yes
|
append: true
|
||||||
|
|
||||||
## Since password authentication in SSH will be disabled, we need to add an authorized key
|
## Since password authentication in SSH will be disabled, we need to add an authorized key
|
||||||
- name: Set authorized key taken from file
|
- name: Set authorized key taken from file
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
remote_user: ansible
|
remote_user: ansible
|
||||||
when: (ansible_facts['distribution'] == "Debian") or
|
when: (ansible_facts['distribution'] == "Debian") or
|
||||||
(ansible_facts['distribution'] == "Ubuntu")
|
(ansible_facts['distribution'] == "Ubuntu")
|
||||||
apt:
|
ansible.builtin.apt:
|
||||||
name:
|
name:
|
||||||
- nano
|
- nano
|
||||||
state: absent
|
state: absent
|
||||||
become: yes
|
become: true
|
||||||
|
|
||||||
|
|
||||||
# Clean up all orphaned packages
|
# Clean up all orphaned packages
|
||||||
@@ -16,12 +16,16 @@
|
|||||||
remote_user: ansible
|
remote_user: ansible
|
||||||
when: (ansible_facts['distribution'] == "Debian") or
|
when: (ansible_facts['distribution'] == "Debian") or
|
||||||
(ansible_facts['distribution'] == "Ubuntu")
|
(ansible_facts['distribution'] == "Ubuntu")
|
||||||
apt:
|
ansible.builtin.apt:
|
||||||
autoremove: yes
|
autoremove: true
|
||||||
purge: yes
|
purge: true
|
||||||
|
|
||||||
|
|
||||||
- name: Install sudo package on Alpine
|
- name: Install sudo package on Alpine
|
||||||
remote_user: ansible
|
remote_user: ansible
|
||||||
when: (ansible_facts['distribution'] == "Alpine")
|
when: (ansible_facts['distribution'] == "Alpine")
|
||||||
command: /sbin/apk del nano
|
community.general.apk:
|
||||||
|
name:
|
||||||
|
- nano
|
||||||
|
state: absent
|
||||||
|
become: true
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
- name: Generate locales
|
- name: Generate locales
|
||||||
ansible.builtin.locale_gen:
|
community.general.locale_gen:
|
||||||
name:
|
name:
|
||||||
- en_US.UTF-8
|
- en_US.UTF-8
|
||||||
- ru_RU.UTF-8
|
- ru_RU.UTF-8
|
||||||
@@ -15,5 +15,5 @@
|
|||||||
LC_ALL=en_US.UTF-8
|
LC_ALL=en_US.UTF-8
|
||||||
|
|
||||||
- name: Set time
|
- name: Set time
|
||||||
ansible.builtin.timezone:
|
community.general.timezone:
|
||||||
name: Europe/Samara
|
name: Europe/Samara
|
||||||
@@ -1,18 +1,21 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
- name: Create new container with minimal options defining network interface with static ip
|
- name: Create new container with minimal options defining network interface with static ip
|
||||||
become: no
|
become: false
|
||||||
community.proxmox.proxmox:
|
community.proxmox.proxmox:
|
||||||
|
validate_certs: false
|
||||||
node: proxmox-server
|
node: proxmox-server
|
||||||
api_user: root@pam
|
api_user: root@pam
|
||||||
api_host: 192.168.0.2
|
api_host: 192.168.0.2
|
||||||
api_token_id: ansible
|
api_token_id: ansible
|
||||||
api_token_secret: "{{ proxmox_token_secret }}"
|
api_token_secret: "{{ proxmox_token_secret }}"
|
||||||
|
|
||||||
|
cmode: "shell"
|
||||||
vmid: 1040
|
vmid: 1040
|
||||||
password: ansible-test
|
password: ansible-test
|
||||||
hostname: "ansible-test"
|
hostname: "ansible-test"
|
||||||
ostemplate: 'main:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst'
|
# ostemplate: 'main:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst'
|
||||||
|
ostemplate: 'main:vztmpl/debian-13-golden-image.tar.gz'
|
||||||
memory: 2048
|
memory: 2048
|
||||||
cores: 5
|
cores: 5
|
||||||
state: present
|
state: present
|
||||||
@@ -24,8 +27,9 @@
|
|||||||
net0: "name=eth0,gw=192.168.0.1,ip=192.168.0.40/24,bridge=vmbr0"
|
net0: "name=eth0,gw=192.168.0.1,ip=192.168.0.40/24,bridge=vmbr0"
|
||||||
|
|
||||||
- name: Make sure the container has started
|
- name: Make sure the container has started
|
||||||
become: no
|
become: false
|
||||||
community.proxmox.proxmox:
|
community.proxmox.proxmox:
|
||||||
|
validate_certs: false
|
||||||
node: proxmox-server
|
node: proxmox-server
|
||||||
api_user: root@pam
|
api_user: root@pam
|
||||||
api_host: 192.168.0.2
|
api_host: 192.168.0.2
|
||||||
@@ -34,3 +38,10 @@
|
|||||||
|
|
||||||
vmid: 1040
|
vmid: 1040
|
||||||
state: started
|
state: started
|
||||||
|
|
||||||
|
- name: Sleep for a minute to ensure that ssh is ready
|
||||||
|
become: false
|
||||||
|
ansible.builtin.wait_for:
|
||||||
|
timeout: 60
|
||||||
|
delegate_to: localhost
|
||||||
|
changed_when: false
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
- name: Create a new VM with minimal options
|
||||||
|
become: false
|
||||||
|
community.proxmox.proxmox_kvm:
|
||||||
|
validate_certs: false
|
||||||
|
node: proxmox-server
|
||||||
|
api_user: root@pam
|
||||||
|
api_host: 192.168.0.2
|
||||||
|
api_token_id: ansible
|
||||||
|
api_token_secret: "{{ proxmox_token_secret }}"
|
||||||
|
|
||||||
|
clone: debian-13-cloud-init-template
|
||||||
|
newid: 1041
|
||||||
|
name: ansible-ci-test
|
||||||
|
storage: main
|
||||||
|
format: qcow2
|
||||||
|
full: true
|
||||||
|
timeout: 500
|
||||||
|
|
||||||
|
- name: Tweak the hardware settings
|
||||||
|
become: false
|
||||||
|
community.proxmox.proxmox_kvm:
|
||||||
|
validate_certs: false
|
||||||
|
node: proxmox-server
|
||||||
|
api_user: root@pam
|
||||||
|
api_host: 192.168.0.2
|
||||||
|
api_token_id: ansible
|
||||||
|
api_token_secret: "{{ proxmox_token_secret }}"
|
||||||
|
|
||||||
|
vmid: 1041
|
||||||
|
cores: 4
|
||||||
|
memory: 4096 # Minimal value for debian based OS for smooth workflow
|
||||||
|
update: true
|
||||||
|
|
||||||
|
- name: Make sure the VM has started
|
||||||
|
become: false
|
||||||
|
community.proxmox.proxmox_kvm:
|
||||||
|
validate_certs: false
|
||||||
|
node: proxmox-server
|
||||||
|
api_user: root@pam
|
||||||
|
api_host: 192.168.0.2
|
||||||
|
api_token_id: ansible
|
||||||
|
api_token_secret: "{{ proxmox_token_secret }}"
|
||||||
|
|
||||||
|
vmid: 1041
|
||||||
|
state: started
|
||||||
|
|
||||||
|
- name: Sleep for 3 minutes to ensure that cloud-init's done its thing
|
||||||
|
become: false
|
||||||
|
ansible.builtin.wait_for:
|
||||||
|
timeout: 180
|
||||||
|
delegate_to: localhost
|
||||||
|
changed_when: false
|
||||||
@@ -2,14 +2,14 @@
|
|||||||
- name: Internet connection test block
|
- name: Internet connection test block
|
||||||
block:
|
block:
|
||||||
- name: Test reachability to ya.ru
|
- name: Test reachability to ya.ru
|
||||||
become: yes # Usually it's not necessary, but sometimes there are some wierd issues with ping, especially on Alpine
|
become: true # Usually it's not necessary, but sometimes there are some wierd issues with ping, especially on Alpine
|
||||||
shell: ping -c 5 ya.ru > /dev/null
|
ansible.builtin.shell: ping -c 5 ya.ru > /dev/null
|
||||||
changed_when: false # This task does not change the system
|
changed_when: false # This task does not change the system
|
||||||
|
|
||||||
rescue:
|
rescue:
|
||||||
# This won't work for now. CA certificate reissuing is required!git
|
# This won't work for now. CA certificate reissuing is required!
|
||||||
- name: Create a test file
|
- name: Create a test file
|
||||||
become: no
|
become: false
|
||||||
ansible.builtin.uri:
|
ansible.builtin.uri:
|
||||||
url: "{{ ha_addr }}/api/webhook/{{ ha_webhook_token }}"
|
url: "{{ ha_addr }}/api/webhook/{{ ha_webhook_token }}"
|
||||||
ca_path: ../files/ca.pem
|
ca_path: ../files/ca.pem
|
||||||
@@ -20,19 +20,25 @@
|
|||||||
- name: Disk free space test block
|
- name: Disk free space test block
|
||||||
block:
|
block:
|
||||||
- name: Test free disk space in root
|
- name: Test free disk space in root
|
||||||
become: no
|
become: false
|
||||||
shell: df -h / | tail -1 | awk '{gsub(/%/, "", $5); print $5}'
|
ansible.builtin.shell: set -o pipefail && df -h / | tail -1 | awk '{gsub(/%/, "", $5); print $5}'
|
||||||
register: result
|
register: common_healthcheck_result
|
||||||
failed_when: result.stdout | int > 85
|
failed_when: common_healthcheck_result.stdout | int > 85
|
||||||
changed_when: false # This task does not change the system
|
changed_when: false # This task does not change the system
|
||||||
|
|
||||||
rescue:
|
rescue:
|
||||||
- name: Notify with ntfy
|
- name: Notify with ntfy
|
||||||
become: no
|
become: false
|
||||||
ansible.builtin.command: |
|
ansible.builtin.uri:
|
||||||
curl -H "Authorization: Bearer {{ ntfy_topic_token }}" \
|
url: "{{ ntfy_topic }}"
|
||||||
-d "{{ ansible_facts['hostname'] }}: Disk space is low" \
|
method: POST
|
||||||
{{ ntfy_topic }}
|
body_format: json
|
||||||
|
status_code: [200, 202]
|
||||||
|
return_content: true
|
||||||
|
headers:
|
||||||
|
Authorization: "Bearer {{ ntfy_topic_token }}"
|
||||||
|
body:
|
||||||
|
- "{{ ansible_facts['hostname'] }}: Disk space is low"
|
||||||
delegate_to: 127.0.0.1
|
delegate_to: 127.0.0.1
|
||||||
failed_when: false
|
failed_when: false
|
||||||
changed_when: false # This task does not change the system
|
changed_when: false # This task does not change the system
|
||||||
|
|||||||
Reference in New Issue
Block a user