Compare commits

26 Commits

Author SHA1 Message Date
max daa5826573 feat(pb,role,task): completes the LXC deployment workflow using new validation tasks 2026-09-17 10:50:46 +04:00
max 0696218eb6 feat(pb,task): moves input validation into separated tasks files. Play fails immediately if a validation fails 2026-09-17 10:16:05 +04:00
max 4789bbd850 fix(pb): makes hostname validation strict enough 2026-09-16 17:51:49 +04:00
max e5e4aa1832 fix(role): omz installation 2026-09-16 17:25:09 +04:00
max 74f567c8eb fix(role): adds root and human_admin_user to sudoers in Alpine 2026-09-16 16:51:08 +04:00
max 996e242180 fix(role): enables qemu-guest-agent service only if the host is a VM 2026-09-16 09:44:01 +04:00
max 9627a4a5e0 feat(pb): removes TLS certificates after the distribution 2026-09-16 09:41:32 +04:00
max e20776a571 Merge branch 'main' into dev
Keep feature branch updated to avoid future issues
2026-09-16 09:08:38 +04:00
max 130ad1dba5 feat(role): installs qemu-guest-agent on Alpine, enables and starts the service 2026-09-15 19:33:43 +04:00
max 6649426ca7 feat(pb): makes human admin user optional 2026-09-15 17:53:18 +04:00
max c7418ad40f feat(pb): adds IP address validation for LXC and VM deployment 2026-09-15 15:06:44 +05:00
max b3771097c2 feat(pb): adds default values for var prompts 2026-09-14 20:09:58 +04:00
max 2e1f8d4146 Merge pull request 'Update crt play' (#18) from update_crt_play into dev
Reviewed-on: #18
2026-09-14 17:00:42 +04:00
max 14e09c7ee7 fix(role): replaces ansible.builtin.fetch with ansible.posix.synchronize to pull the directory 2026-09-14 16:53:47 +04:00
max e59f07fb6d feat(pb,role): adds alpine as an option for VM deploying 2026-09-14 14:50:44 +04:00
max 6bef8b28e5 feat(role): ensures that sudo group exists 2026-09-14 14:50:44 +04:00
max eb7fd456e4 fix(role): replaces ssh with openssh, adds tzdata 2026-09-14 14:50:44 +04:00
max 5f4f84ea15 feat(role): sets locale for alpine correctly 2026-09-14 14:50:44 +04:00
max 8f4fee8b63 change(inv): moves localhost to hosts.yaml, removes dedicated localhost.yaml 2026-09-14 14:50:44 +04:00
max 1d3bc59a8b fix(playbook): play name in maintain playbook 2026-09-14 14:50:44 +04:00
max 49bd2f630b feat(role,pb,inv): new role for updating certificates on web-servers 2026-09-14 09:58:47 +04:00
max 07b33028d1 fix(playbook): play name in maintain playbook 2026-09-14 09:44:21 +04:00
max cc68a1f863 fix (roles): ssh config to be placed in ~/.shh 2026-09-02 19:08:46 +05:00
max 4897cdadbd feat (roles): copies a config with hosts rules in human admin ~/.ssh 2026-09-01 10:18:30 +05:00
max e0571783ba fix (docs): a typ in README.md 2026-09-01 09:31:48 +05:00
max c633ead7cc CHANGE: updates README.md 2026-08-24 15:28:22 +05:00
21 changed files with 455 additions and 75 deletions
+18 -1
View File
@@ -1,3 +1,20 @@
# ansible_home # ansible_home
My own home services automation repository ## How to use it?
It's better to use a virtual environment to avoid incompatibility issues
```bash
git clone https://git.vmn.su/max/vmn-ansible
cd vmn-ansible
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
ansible-galaxy collection install -r requirements.yaml
ansible-galaxy role install -r requirements.yaml
ansible-playbook playbooks/deploy_and_set_up_lxc_on_proxmox.yaml --vault-pass-file $VAULT_PASS_PATH -i inventory/localhost.yaml --private-key $SSH_KEY
```
**deploy** playbooks must be used with `inventory/localhost.yaml`, they need access to proxmox host only
There are also a systemd service and timer under `systemd` directory
+19 -4
View File
@@ -1,11 +1,18 @@
--- ---
all: all:
children: children:
this_host:
hosts:
localhost:
ansible_become_password: "{{ ansible_become_passwd }}"
ansible_connection: local
ansible_python_interpreter: "{{ ansible_playbook_python }}"
physical: physical:
proxmox_1: hosts:
ansible_host: "{{ proxmox_1_host }}" proxmox_1:
ansible_become_password: "{{ ansible_become_passwd }}" ansible_host: "{{ proxmox_1_host }}"
services_to_run: [] ansible_become_password: "{{ ansible_become_passwd }}"
services_to_run: []
virtual: virtual:
hosts: hosts:
localhost: localhost:
@@ -39,3 +46,11 @@ all:
ansible_become_password: "{{ ansible_become_passwd }}" ansible_become_password: "{{ ansible_become_passwd }}"
services_to_run: services_to_run:
- coder_ai - coder_ai
web-servers:
hosts:
cert-proxy:
ansible_host: 192.168.0.47
ansible_become_password: "{{ ansible_become_passwd }}"
monitoring:
ansible_host: 192.168.0.49
ansible_become_password: "{{ ansible_become_passwd }}"
-7
View File
@@ -1,7 +0,0 @@
---
physical:
hosts:
localhost:
ansible_become_password: "{{ ansible_become_passwd }}"
ansible_connection: local
ansible_python_interpreter: "{{ ansible_playbook_python }}"
+25 -37
View File
@@ -1,6 +1,6 @@
--- ---
- name: Deploy LXC - name: Deploy LXC
hosts: all hosts: localhost
remote_user: ansible remote_user: ansible
gather_facts: false gather_facts: false
@@ -10,50 +10,30 @@
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') }}"
vars_prompt: pre_tasks:
- name: lxc_hostname - name: Include input and validation for hostname
prompt: "Hostname for the container (may only contain letters (a-z, A-Z), numbers (0-9), and hyphens)" ansible.builtin.include_tasks: ../tasks/hostname_validation.yaml
private: false
- name: Include input and validation for password
ansible.builtin.include_tasks: ../tasks/password_validation.yaml
- name: lxc_root_password - name: Include input and validation for IP
prompt: "Root password" ansible.builtin.include_tasks: ../tasks/ip_validation.yaml
private: true
confirm: true
encrypt: sha512_crypt
- name: lxc_ip_address - name: Include input and validation for LXC privilege
prompt: "IP address for the container (in x.x.x.x/x formant)" ansible.builtin.include_tasks: ../tasks/lxc_privileged_validation.yaml
private: false
- name: lxc_is_privileged - name: Include input and validation for human admin user creation
prompt: "Unprivileged LXC (true/false)?" ansible.builtin.include_tasks: ../tasks/human_admin_user_validation.yaml
private: false
pre_tasks:
- name: Validate hostname
ansible.builtin.fail:
msg: |
Invalid hostname: "{{ lxc_hostname }}"
Hostname may only contain letters (a-z, A-Z), numbers (0-9), and hyphens (-).
when: not lxc_hostname is regex('^[a-zA-Z0-9-]+$')
run_once: true
roles: roles:
- ../roles/deploy_lxc_on_proxmox - ../roles/deploy_lxc_on_proxmox
tasks: tasks:
- name: Make the prompted hostname available to the whole playbook
ansible.builtin.set_fact:
fact_lxc_hostname: "{{ lxc_hostname }}"
- name: Make the prompted IP available to the whole playbook
ansible.builtin.set_fact:
#fact_lxc_ip_address: "{{ lxc_ip_address | ansible.utils.ipaddr('address') }}"
fact_lxc_ip_address: "{{ lxc_ip_address.split('/') | first }}"
- name: Add the target host to the inventory - name: Add the target host to the inventory
ansible.builtin.add_host: ansible.builtin.add_host:
name: "{{ fact_lxc_ip_address }}" name: "{{ lxc_ip_address }}"
groups: new_host groups: new_host
ansible_user: ansible ansible_user: ansible
ansible_become_password: "{{ ansible_become_passwd }}" ansible_become_password: "{{ ansible_become_passwd }}"
@@ -73,7 +53,15 @@
- ../roles/configure_ansible_user - ../roles/configure_ansible_user
- ../roles/harden_ssh - ../roles/harden_ssh
- ../roles/base_system - ../roles/base_system
- ../roles/human_admin_user
# Update configs - omz, nvim, ranger and so on. Distribute the last version of those configs tasks:
- ../roles/update_configs - name: Include human admin user role
ansible.builtin.include_role:
name: ../roles/human_admin_user
when: "hostvars['localhost']['lxc_human_admin_user'] | bool"
- name: Include update configs role
ansible.builtin.include_role:
name: ../roles/update_configs
when: "hostvars['localhost']['lxc_human_admin_user'] | bool"
+73 -9
View File
@@ -1,6 +1,6 @@
--- ---
- name: Deploy VM - name: Deploy VM
hosts: all hosts: localhost
remote_user: ansible remote_user: ansible
gather_facts: false gather_facts: false
@@ -13,39 +13,95 @@
vars_prompt: vars_prompt:
- name: vm_hostname - name: vm_hostname
prompt: "Hostname for the VM (may only contain letters (a-z, A-Z), numbers (0-9), and hyphens)" prompt: "Hostname for the VM (may only contain letters (a-z, A-Z), numbers (0-9), and hyphens)"
default: "new-vm-test"
private: false
- name: vm_os_template
prompt: "Select OS template. Available: debian-13 | alpine"
default: "debian-13"
private: false
- name: vm_become_method
prompt: "Select become method. Available: sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas | machinectl"
default: "sudo"
private: false
- name: vm_create_human_admin_user
prompt: "Create human admin user? (true/false)?"
default: true
private: false private: false
- name: vm_ip_address - name: vm_ip_address
prompt: "IP address for the VM (in x.x.x.x/x formant)" prompt: "IP address for the VM (in x.x.x.x/x formant)"
default: "192.168.0.89/24"
private: false private: false
pre_tasks: pre_tasks:
- name: Validate hostname - name: Validate hostname
ansible.builtin.fail: ansible.builtin.fail:
msg: | msg: |
Invalid hostname: "{{ vm_hostname }}" Invalid hostname: "{{ lxc_hostname }}"
Hostname may only contain letters (a-z, A-Z), numbers (0-9), and hyphens (-). Hostname must:
when: not vm_hostname is regex('^[a-zA-Z0-9-]+$') - contain only letters (a-z, A-Z), digits (0-9), hyphens (-), and dots (.)
- not start or end with a hyphen or dot
- have each label between 1 and 63 characters
- not exceed 253 characters in total
when: >
lxc_hostname | length > 253 or
lxc_hostname is not regex('^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$')
run_once: true
- name: Validate IP address
ansible.builtin.fail:
msg: |
Invalid IP address: "{{ vm_ip_address }}"
IP address must be in x.x.x.x/x format (e.g., 192.168.0.89/24).
when: not vm_ip_address is regex('^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)(\\/(3[0-2]|[12]?\\d))?$')
run_once: true
- name: Validate OS template
ansible.builtin.fail:
msg: |
Invalid OS template: "{{ vm_os_template }}"
Select from available options: debian-13, alpine
when: vm_os_template not in ['debian-13', 'alpine']
run_once: true
- name: Validate become method
ansible.builtin.fail:
msg: |
Invalid become method: "{{ vm_become_method }}"
Select from available options: sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas | machinectl
when: vm_become_method not in ['sudo', 'su', 'pbrun', 'pfexec', 'doas', 'dzdo', 'ksu', 'runas', 'machinectl']
run_once: true run_once: true
roles: roles:
- ../roles/deploy_vm_on_proxmox - ../roles/deploy_vm_on_proxmox
tasks: tasks:
- name: Make the prompted hostname available to the whole playbook - name: Make the hostname available to the whole playbook
ansible.builtin.set_fact: ansible.builtin.set_fact:
fact_vm_hostname: "{{ vm_hostname }}" fact_vm_hostname: "{{ vm_hostname }}"
- name: Make the prompted IP available to the whole playbook - name: Make the OS template available to the whole playbook
ansible.builtin.set_fact:
fact_vm_os_template: "{{ vm_os_template }}"
- name: Make the IP available to the whole playbook
ansible.builtin.set_fact: ansible.builtin.set_fact:
fact_vm_ip_address: "{{ vm_ip_address.split('/') | first }}" fact_vm_ip_address: "{{ vm_ip_address.split('/') | first }}"
- name: Make the "human admin user" selection available to the whole playbook
ansible.builtin.set_fact:
fact_vm_create_human_admin_user: "{{ vm_create_human_admin_user }}"
- name: Add the target host to the inventory - name: Add the target host to the inventory
ansible.builtin.add_host: ansible.builtin.add_host:
name: "{{ fact_vm_ip_address }}" name: "{{ fact_vm_ip_address }}"
groups: new_host groups: new_host
ansible_user: ansible ansible_user: ansible
ansible_become_password: "{{ ansible_become_passwd }}" ansible_become_password: "{{ ansible_become_passwd }}"
ansible_become_method: "{{ vm_become_method }}"
- name: Configure VM - name: Configure VM
@@ -62,7 +118,15 @@
- ../roles/configure_ansible_user - ../roles/configure_ansible_user
- ../roles/harden_ssh - ../roles/harden_ssh
- ../roles/base_system - ../roles/base_system
- ../roles/human_admin_user
# Update configs - omz, nvim, ranger and so on. Distribute the last version of those configs tasks:
- ../roles/update_configs - name: Include human admin user role
ansible.builtin.include_role:
name: ../roles/human_admin_user
when: "hostvars['localhost']['fact_vm_create_human_admin_user'] | bool"
- name: Include update configs role
ansible.builtin.include_role:
name: ../roles/update_configs
when: "hostvars['localhost']['fact_vm_create_human_admin_user'] | bool"
+28 -1
View File
@@ -1,5 +1,5 @@
--- ---
- name: Deploy and set up an LXC container in Proxmox - name: Perform regular maintenance
hosts: virtual hosts: virtual
remote_user: ansible remote_user: ansible
@@ -20,3 +20,30 @@
- ../roles/update_configs - ../roles/update_configs
# Make sure that the services that are supposed to run are running # Make sure that the services that are supposed to run are running
- ../roles/check_services - ../roles/check_services
- name: Ensure all web-servers have fresh TLS certificates
hosts: web-servers
remote_user: ansible
vars_files:
../inventory/group_vars/all/secrets.yaml
roles:
# Pull certificates from cert_proxy and distribute them among the servers
- ../roles/update_certificates
post_tasks:
- name: Delete certificates from cert-proxy
ansible.builtin.file:
name: /tmp/letsencrypt
state: absent
when: "inventory_hostname == 'cert-proxy'"
run_once: true
- name: Delete certificates from ansible-server
ansible.builtin.file:
name: /tmp/letsencrypt
state: absent
run_once: true
delegate_to: 127.0.0.1
+23 -1
View File
@@ -7,7 +7,7 @@
become: true become: true
remote_user: ansible remote_user: ansible
- name: Install qemu-guest-agent on VM - name: Install qemu-guest-agent on VM with apt-based systems
when: when:
- ansible_facts['os_family'] == "Debian" - ansible_facts['os_family'] == "Debian"
- ansible_facts['virtualization_type'] == "kvm" - ansible_facts['virtualization_type'] == "kvm"
@@ -29,3 +29,25 @@
name: "{{ alpine_packages }}" name: "{{ alpine_packages }}"
update_cache: true update_cache: true
remote_user: ansible remote_user: ansible
- name: Install qemu-guest-agent on VM with Alpine
when:
- ansible_facts['distribution'] == "Alpine"
- ansible_facts['virtualization_type'] == "kvm"
community.general.apk:
name: qemu-guest-agent
update_cache: true
become: true
remote_user: ansible
tags:
- kvm-guests
- packages
- name: Enable qemu-guest-agent
ansible.builtin.service:
name: qemu-guest-agent
enabled: yes
state: started
when: ansible_facts['virtualization_type'] == "kvm"
@@ -1,19 +1,63 @@
--- ---
- name: Generate locales - name: Generate locales for Debian-based systems
community.general.locale_gen: community.general.locale_gen:
name: name:
- en_US.UTF-8 - en_US.UTF-8
- ru_RU.UTF-8 - ru_RU.UTF-8
state: present state: present
when: (ansible_facts['distribution'] == "Debian") or
(ansible_facts['distribution'] == "Ubuntu")
- name: Set locale - name: Set locale for Debian-based systems
ansible.builtin.copy: ansible.builtin.copy:
dest: /etc/locale.conf dest: /etc/locale.conf
mode: '0644' mode: '0644'
content: | content: |
LANG=en_US.UTF-8 LANG=en_US.UTF-8
LC_ALL=en_US.UTF-8 LC_ALL=en_US.UTF-8
when: (ansible_facts['distribution'] == "Debian") or
(ansible_facts['distribution'] == "Ubuntu")
# The same for Alpine
- name: Install musl-locales package for Alpine
community.general.apk:
name: musl-locales
state: present
when: ansible_facts['distribution'] == "Alpine"
- name: Copy default locale profile to a custom override file for Alpine
ansible.builtin.copy:
src: /etc/profile.d/20locale.sh
dest: /etc/profile.d/locale.sh
remote_src: true
mode: '0644'
owner: root
group: root
force: false # Do not overwrite if the file already exists
when: ansible_facts['distribution'] == "Alpine"
- name: Set LANG and LC_ALL in the custom locale file for Alpine
ansible.builtin.lineinfile:
path: /etc/profile.d/locale.sh
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
state: present
loop:
- { regexp: '^export LANG=', line: 'export LANG=en_US.UTF-8' }
- { regexp: '^export LC_ALL=', line: 'export LC_ALL=en_US.UTF-8' }
when: ansible_facts['distribution'] == "Alpine"
- name: Ensure Unicode is enabled in /etc/rc.conf for Alpine
ansible.builtin.lineinfile:
path: /etc/rc.conf
regexp: '^#?unicode='
line: 'unicode="YES"'
state: present
when: ansible_facts['distribution'] == "Alpine"
# Works fine for all
- name: Set time - name: Set time
community.general.timezone: community.general.timezone:
name: Europe/Samara name: Europe/Samara
@@ -6,8 +6,9 @@ alpine_packages:
- git - git
- kitty - kitty
- neovim - neovim
- openssh
- openssh-server - openssh-server
- ranger - ranger
- rsync - rsync
- ssh - tzdata
- zsh - zsh
+28 -1
View File
@@ -8,14 +8,35 @@
- sudo - sudo
update-cache: true update-cache: true
- name: Ensure /etc/resolv.conf exists with DNS servers
when: (ansible_facts['distribution'] == "Alpine")
ansible.builtin.copy:
dest: /etc/resolv.conf
content: |
nameserver 192.168.0.1
nameserver 8.8.8.8
mode: '0644'
owner: root
group: root
become: true
# The same commands for Alpine # The same commands for Alpine
- name: Update and install packages on Alpine - name: Install sudo on Alpine
when: (ansible_facts['distribution'] == "Alpine") when: (ansible_facts['distribution'] == "Alpine")
community.general.apk: community.general.apk:
name: sudo name: sudo
update_cache: true update_cache: true
remote_user: ansible remote_user: ansible
- name: Enable sudo for root and human_admin_user
when: (ansible_facts['distribution'] == "Alpine")
ansible.builtin.copy:
dest: /etc/sudoers.d/80-ansible-created-users
content: |
root ALL=(ALL) ALL:ALL
{{ human_admin_user }} ALL=(ALL) ALL:ALL
remote_user: ansible
## Creating and setting up the ansible user ## Creating and setting up the ansible user
## First, create sshusers group to grant ssh access ## First, create sshusers group to grant ssh access
@@ -24,6 +45,12 @@
name: sshusers name: sshusers
state: present state: present
- name: Ensure group "sudo" exists
ansible.builtin.group:
name: sudo
state: present
## 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
ansible.builtin.user: ansible.builtin.user:
+2 -2
View File
@@ -14,7 +14,7 @@
password: "{{ lxc_root_password }}" password: "{{ lxc_root_password }}"
hostname: "{{ lxc_hostname }}" hostname: "{{ lxc_hostname }}"
ostemplate: 'main:vztmpl/debian-13-golden-image.tar.gz' ostemplate: 'main:vztmpl/debian-13-golden-image.tar.gz'
unprivileged: "{{ lxc_is_privileged }}" unprivileged: "{{ lxc_privileged }}"
memory: 2048 memory: 2048
cores: 2 cores: 2
state: present state: present
@@ -26,7 +26,7 @@
storage: local storage: local
pubkey: "{{ lookup('file', lookup('env', 'HOME') + '/.ssh/ansible_key.pub') }}" pubkey: "{{ lookup('file', lookup('env', 'HOME') + '/.ssh/ansible_key.pub') }}"
netif: netif:
net0: "name=eth0,gw=192.168.0.1,ip={{ lxc_ip_address }},bridge=vmbr0" net0: "name=eth0,gw=192.168.0.1,ip={{ lxc_ip_address }}/{{ lxc_netmask }},bridge=vmbr0"
- name: Make sure the container has started - name: Make sure the container has started
become: false become: false
@@ -10,7 +10,7 @@
api_token_id: ansible api_token_id: ansible
api_token_secret: "{{ proxmox_token_secret }}" api_token_secret: "{{ proxmox_token_secret }}"
clone: debian-13-cloud-init-template clone: "{{ vm_os_template }}-cloud-init-template"
name: "{{ vm_hostname }}" name: "{{ vm_hostname }}"
storage: main storage: main
format: qcow2 format: qcow2
+7 -5
View File
@@ -1,15 +1,17 @@
#!/bin/sh #!/bin/sh
FILE=/home/$USER/.oh-my-zsh/oh-my-zsh.sh TARGET_USER=$1
FILE=/home/$TARGET_USER/.oh-my-zsh/oh-my-zsh.sh
if [ -f "$FILE" ]; then if [ -f "$FILE" ]; then
echo "$FILE exists and we not installing ohmyzsh" echo "$FILE exists and we not installing ohmyzsh"
exit 0 exit 0
else else
echo "$FILE does not exist and we install ohmyzsh" echo "$FILE does not exist and we install ohmyzsh"
cd /home/max cd /home/$TARGET_USER
wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh sudo -u $TARGET_USER wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh
chmod +x /home/max/install.sh chmod +x /home/$TARGET_USER/install.sh
timeout -s 15 -k 30s 20s /home/max/install.sh --unattendend --keep-zshrc || exit 0 sudo -u $TARGET_USER timeout -s 15 -k 30s 20s /home/$TARGET_USER/install.sh --unattendend --keep-zshrc || exit 0
exit 0 exit 0
fi fi
+15
View File
@@ -0,0 +1,15 @@
# PUT NEW BLOCKS STRICTLY BEFORE ANY MATCH BLOCK
# Private keys are NOT distributed via Ansible
# They must to be copied manually ONLY to those hosts that need access to others
# Most of the home major LAN hosts should be accessible with this key
Match Host 192.168.0.?
User max
IdentityFile ~/.ssh/max_regular_key
# This virtual network has the same hosts range
Match Host 10.9.2.?
User max
IdentityFile ~/.ssh/max_regular_key
+11 -3
View File
@@ -25,10 +25,9 @@
# WARNING: UNPRIVILEGED USER (not ansible) COMMANDS # WARNING: UNPRIVILEGED USER (not ansible) COMMANDS
- name: Install oh my zsh - name: Install oh my zsh
remote_user: "{{ human_admin_user }}" remote_user: ansible
ansible.builtin.command: "/home/{{ human_admin_user }}/install_omz.sh" ansible.builtin.command: "/home/{{ human_admin_user }}/install_omz.sh {{ human_admin_user }}"
changed_when: true changed_when: true
vars:
- 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
@@ -48,6 +47,15 @@
group: "{{ human_admin_user }}" group: "{{ human_admin_user }}"
mode: u=rw,g=r,o-rwx mode: u=rw,g=r,o-rwx
- name: Configure ssh client, by pushing the config
remote_user: ansible
ansible.builtin.copy:
src: "{{ role_path }}/files/ssh_config"
dest: "/home/{{ human_admin_user }}/.ssh/config"
owner: "{{ human_admin_user }}"
group: "{{ human_admin_user }}"
mode: u=rw,g=r,o-rwx
# WARNING: we've finished with the initial setup, drop ansible key # WARNING: we've finished with the initial setup, drop ansible key
# Push regular user key # Push regular user key
+23
View File
@@ -0,0 +1,23 @@
---
- name: Pull directory from remote host to control node
ansible.posix.synchronize:
mode: pull
src: /tmp/letsencrypt
dest: /tmp
recursive: true
delete: true
when: "inventory_hostname == 'cert-proxy'"
- name: Push loki.vmn.su certificate to the target
ansible.builtin.copy:
src: /tmp/letsencrypt/live/loki.vmn.su/fullchain.pem
dest: /etc/nginx/certs/loki_fullchain.pem
local_follow: true
when: "inventory_hostname == 'monitoring'"
- name: Push loki.vmn.su key to the target
ansible.builtin.copy:
src: /tmp/letsencrypt/live/loki.vmn.su/privkey.pem
dest: /etc/nginx/certs/loki_privkey.pem
local_follow: true
when: "inventory_hostname == 'monitoring'"
+23
View File
@@ -0,0 +1,23 @@
---
- name: Set default hostname
ansible.builtin.set_fact:
lxc_hostname: "new-lxc-test"
- name: Prompt for hostname with immediate validation
ansible.builtin.pause:
prompt: "Enter hostname (letters, digits, hyphens, dots; max 253 chars) [new-lxc-test]"
register: hostname_result
until: >
hostname_result.user_input | length == 0 or
(
hostname_result.user_input | length <= 253 and
hostname_result.user_input is regex('^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$')
)
retries: 2
delay: 0
- name: Use user input only if provided, otherwise keep the default
ansible.builtin.set_fact:
lxc_hostname: "{{ hostname_result.user_input }}"
when: hostname_result.user_input | length > 0
+22
View File
@@ -0,0 +1,22 @@
---
- name: Set default human admin user
ansible.builtin.set_fact:
lxc_human_admin_user: true
- name: Prompt for human admin user creation with immediate validation
ansible.builtin.pause:
prompt: "Create human admin user? (true/false) [true]"
register: human_admin_user_result
until: >
human_admin_user_result.user_input | length == 0 or
(
human_admin_user_result.user_input in ['true', 'false']
)
retries: 2
delay: 0
- name: Use user input only if provided, otherwise keep the default
ansible.builtin.set_fact:
lxc_human_admin_user: "{{ human_admin_user_result.user_input }}"
when: human_admin_user_result.user_input | length > 0
+29
View File
@@ -0,0 +1,29 @@
---
- name: Set default ip
ansible.builtin.set_fact:
lxc_ip_address: "192.168.0.90"
- name: Set default network mask
ansible.builtin.set_fact:
lxc_netmask: "24"
- name: Prompt for IP with immediate validation
ansible.builtin.pause:
prompt: "Enter ip in x.x.x.x/x format [192.168.0.90/24]"
register: ip_result
until: >
ip_result.user_input | length == 0 or
ip_result.user_input is regex('^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)/(3[0-2]|[12]?\\d)$')
retries: 2
delay: 0
- name: Use user input only if provided, otherwise keep the default (IP)
ansible.builtin.set_fact:
lxc_ip_address: "{{ ip_result.user_input.split('/') | first }}"
when: ip_result.user_input | length > 0
- name: Use user input only if provided, otherwise keep the default (netmask)
ansible.builtin.set_fact:
lxc_netmask: "{{ ip_result.user_input.split('/') | second }}"
when: ip_result.user_input | length > 0
+22
View File
@@ -0,0 +1,22 @@
---
- name: Set default privileged
ansible.builtin.set_fact:
lxc_privileged: false
- name: Prompt for privileged with immediate validation
ansible.builtin.pause:
prompt: "Privileged LXC? (true/false) [false]"
register: privileged_result
until: >
privileged_result.user_input | length == 0 or
(
privileged_result.user_input in ['true', 'false']
)
retries: 2
delay: 0
- name: Use user input only if provided, otherwise keep the default
ansible.builtin.set_fact:
lxc_privileged: "{{ privileged_result.user_input }}"
when: privileged_result.user_input | length > 0
+38
View File
@@ -0,0 +1,38 @@
---
- name: Set default password
ansible.builtin.set_fact:
lxc_root_password: "new-lxc-test"
- name: Prompt for password
ansible.builtin.pause:
prompt: "Enter password (letters, digits, hyphens, dots; max 253 chars) [new-lxc-test]"
echo: false
register: password_result_1
until: >
password_result_1.user_input | length == 0 or
(
password_result_1.user_input | length <= 253 and
password_result_1.user_input is regex('^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$')
)
retries: 3
delay: 0
- name: Prompt for password (confirmation)
ansible.builtin.pause:
prompt: "Confirm your new password"
echo: no
register: password_result_2
- name: Ensure passwords match
ansible.builtin.assert:
that:
- password_result_1.user_input == password_result_2.user_input
fail_msg: "Passwords do not match!"
success_msg: "Password confirmed."
- name: Use user input only if provided, otherwise keep the default
ansible.builtin.set_fact:
lxc_root_password: "{{ password_result_1.user_input }}"
when: password_result_1.user_input | length > 0