chore: ansible-lint
This commit is contained in:
parent
2c6da106b2
commit
2c421611ae
3
.ansible-lint
Normal file
3
.ansible-lint
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
skip_list:
|
||||||
|
- var-naming[no-role-prefix]
|
||||||
19
README.md
19
README.md
@ -1,13 +1,27 @@
|
|||||||
# Homelab Ansible Playbooks
|
# Homelab Ansible Playbooks
|
||||||
|
|
||||||
This repository contains Ansible playbooks and roles I use to manage my NAS and several VMs 👨💻.
|
This repository contains Ansible playbooks and roles I use to manage my NAS and some VMs 👨💻.
|
||||||
|
|
||||||
This project is designed for personal/familial scale maintenance, if you find this useful for your use, want to share advises or security concerns, feel free to drop me a line.
|
This project is designed for personal/familial scale maintenance, if you find this useful for your use, want to share advises or security concerns, feel free to drop me a line.
|
||||||
|
|
||||||
This is a good playground to learn and I encourage you to adapt these roles to your needs. While they might not be production-ready for all environments, I'm open to adapting them for [Ansible Galaxy]((https://galaxy.ansible.com)) if there's community interest!
|
This is a good playground to learn and I encourage you to adapt these roles to your needs. While they might not be production-ready for all environments, I'm open to adapting them for [Ansible Galaxy](<(https://galaxy.ansible.com)>) if there's community interest!
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
Base tools:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# linux
|
||||||
|
apt-get install ansible ansible-lint ansible-galaxy
|
||||||
|
pacman -Syu ansible ansible-lint ansible-galaxy
|
||||||
|
# macos
|
||||||
|
brew install ansible ansible-lint ansible-galaxy
|
||||||
|
# windows
|
||||||
|
choco install ansible ansible-lint ansible-galaxy
|
||||||
|
```
|
||||||
|
|
||||||
|
Other roles:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
ansible-galaxy collection install -r requirements.yml
|
ansible-galaxy collection install -r requirements.yml
|
||||||
```
|
```
|
||||||
@ -36,5 +50,6 @@ ssh-copy-id -i ~/.ssh/id_rsa.pub username@remote_host
|
|||||||
Linting:
|
Linting:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
ansible-lint
|
||||||
npx prettier --write .
|
npx prettier --write .
|
||||||
```
|
```
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
[defaults]
|
[defaults]
|
||||||
interpreter_python=/usr/bin/python3
|
interpreter_python=/usr/bin/python3
|
||||||
|
roles_path=./roles
|
||||||
|
|
||||||
[ssh_connection]
|
[ssh_connection]
|
||||||
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o ControlPath=/tmp/ansible-ssh-%h-%p-%r
|
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o ControlPath=/tmp/ansible-ssh-%h-%p-%r
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
# Network configuration
|
# Network configuration
|
||||||
# ---------------------
|
# ---------------------
|
||||||
network_interfaces:
|
network_interfaces:
|
||||||
|
|||||||
20
playbook.yml
20
playbook.yml
@ -1,10 +1,16 @@
|
|||||||
- hosts: all
|
---
|
||||||
|
# - hosts: all
|
||||||
|
# become: true
|
||||||
|
# roles:
|
||||||
|
# - role: networking
|
||||||
|
# - role: sshd
|
||||||
|
# - role: disks
|
||||||
|
# - role: wireguard
|
||||||
|
# - role: zsh
|
||||||
|
# - role: archlinux
|
||||||
|
# - role: podman
|
||||||
|
|
||||||
|
- hosts: pinwheel
|
||||||
become: true
|
become: true
|
||||||
roles:
|
roles:
|
||||||
- role: networking
|
|
||||||
- role: sshd
|
- role: sshd
|
||||||
- role: disks
|
|
||||||
- role: wireguard
|
|
||||||
- role: zsh
|
|
||||||
- role: archlinux
|
|
||||||
- role: podman
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
- hosts: marge
|
- hosts: marge
|
||||||
become: true
|
become: true
|
||||||
roles:
|
roles:
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
collections:
|
collections:
|
||||||
- name: ansible.netcommon
|
- name: ansible.netcommon
|
||||||
- name: community.general
|
- name: community.general
|
||||||
|
|||||||
7
roles/archlinux/README.md
Normal file
7
roles/archlinux/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Le classique quand on n'a pas mis à jour arch depuis un moment c'est d'avoir une clef PGP manquante.
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo pacman -Sy archlinux-keyring
|
||||||
|
```
|
||||||
|
|
||||||
|
Avant l'update soigne les petits chats blessés.
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
arch_locale: en_US.UTF-8
|
arch_locale: en_US.UTF-8
|
||||||
yay_src_path: /opt/yay
|
yay_src_path: /opt/yay
|
||||||
yay_git_repo: https://aur.archlinux.org/yay.git
|
yay_git_repo: https://aur.archlinux.org/yay.git
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
---
|
---
|
||||||
- name: Configure locales
|
- name: Configure locales
|
||||||
block:
|
block:
|
||||||
- name: activate locale
|
- name: Activate locale
|
||||||
command:
|
ansible.builtin.command:
|
||||||
cmd: localectl set-locale LANG={{ arch_locale }}
|
cmd: localectl set-locale LANG={{ arch_locale }}
|
||||||
- name: edit /etc/locale.gen
|
- name: Edit /etc/locale.gen
|
||||||
lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
dest: /etc/locale.gen
|
dest: /etc/locale.gen
|
||||||
state: present
|
state: present
|
||||||
regexp: "{{ arch_locale }}"
|
regexp: "{{ arch_locale }}"
|
||||||
line: "{{ arch_locale }} UTF-8"
|
line: "{{ arch_locale }} UTF-8"
|
||||||
- name: regenerate locales
|
- name: Regenerate locales
|
||||||
command:
|
ansible.builtin.command:
|
||||||
cmd: locale-gen
|
cmd: locale-gen
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
---
|
---
|
||||||
- name: Skip Archlinux installation
|
- name: Skip Archlinux installation
|
||||||
meta: end_play
|
ansible.builtin.meta: end_play
|
||||||
when: ansible_facts['os_family'] != 'Archlinux'
|
when: ansible_facts['os_family'] != 'Archlinux'
|
||||||
|
|
||||||
- name: Archlinux base setup
|
- name: Archlinux base setup
|
||||||
include_tasks: "{{ item }}"
|
ansible.builtin.include_tasks: "{{ item }}"
|
||||||
loop:
|
loop:
|
||||||
- pacman.yml
|
- pacman.yml
|
||||||
- locales.yml
|
- locales.yml
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
- name: Check if pacman is not locked
|
- name: Check if pacman is not locked
|
||||||
stat:
|
ansible.builtin.stat:
|
||||||
path: /var/lib/pacman/db.lck
|
path: /var/lib/pacman/db.lck
|
||||||
register: pacman_lock
|
register: pacman_lock
|
||||||
failed_when: pacman_lock.stat.exists
|
failed_when: pacman_lock.stat.exists
|
||||||
@ -13,32 +13,30 @@
|
|||||||
# state: absent
|
# state: absent
|
||||||
|
|
||||||
- name: Install reflector (looking for fastest mirror)
|
- name: Install reflector (looking for fastest mirror)
|
||||||
pacman:
|
community.general.pacman:
|
||||||
name: reflector
|
name: reflector
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
- name: Stat pacman mirrorlist
|
- name: Stat pacman mirrorlist
|
||||||
stat:
|
ansible.builtin.stat:
|
||||||
path: /etc/pacman.d/mirrorlist
|
path: /etc/pacman.d/mirrorlist
|
||||||
register: mirrorlist
|
register: mirrorlist
|
||||||
|
|
||||||
# Probably not here if it's a fresh install
|
# Probably not here if it's a fresh install
|
||||||
- name: Stat pacman mirrorlist.bak
|
- name: Stat pacman mirrorlist.bak
|
||||||
stat:
|
ansible.builtin.stat:
|
||||||
path: /etc/pacman.d/mirrorlist.bak
|
path: /etc/pacman.d/mirrorlist.bak
|
||||||
register: mirrorlist_bak
|
register: mirrorlist_bak
|
||||||
|
|
||||||
- name: Backup and update pacman mirrorlist if older than 7 days
|
- name: Backup and update pacman mirrorlist if older than 7 days
|
||||||
shell: >
|
ansible.builtin.shell: >
|
||||||
cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.bak &&
|
cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.bak &&
|
||||||
reflector --latest 20 --protocol https --sort rate
|
reflector --latest 20 --protocol https --sort rate
|
||||||
--save /etc/pacman.d/mirrorlist
|
--save /etc/pacman.d/mirrorlist
|
||||||
when: mirrorlist_bak.stat.exists is false or
|
when: mirrorlist_bak.stat.exists is false or (mirrorlist.stat.exists and (ansible_date_time.epoch | int - mirrorlist.stat.mtime) > 604800)
|
||||||
(mirrorlist.stat.exists and
|
|
||||||
(ansible_date_time.epoch | int - mirrorlist.stat.mtime) > 604800)
|
|
||||||
|
|
||||||
- name: Configure pacman to output colors
|
- name: Configure pacman to output colors
|
||||||
lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
dest: /etc/pacman.conf
|
dest: /etc/pacman.conf
|
||||||
state: present
|
state: present
|
||||||
regexp: "^(.*)Color"
|
regexp: "^(.*)Color"
|
||||||
|
|||||||
@ -1,10 +1,68 @@
|
|||||||
---
|
---
|
||||||
- name: Check if paru is already installed
|
- name: Check if paru is already installed
|
||||||
stat:
|
ansible.builtin.stat:
|
||||||
path: /usr/bin/paru
|
path: /usr/bin/paru
|
||||||
register: paru
|
register: paru
|
||||||
|
|
||||||
- name: Install paru
|
- name: Install paru
|
||||||
|
when: not paru.stat.exists
|
||||||
|
##
|
||||||
|
## Deprecated version with compilation
|
||||||
|
##
|
||||||
|
# - name: Install paru
|
||||||
|
# block:
|
||||||
|
# - name: Install build dependencies
|
||||||
|
# package:
|
||||||
|
# name:
|
||||||
|
# - base-devel
|
||||||
|
# - git
|
||||||
|
# state: present
|
||||||
|
|
||||||
|
# - name: Disable sudo password prompt (makepkg sudoers hack)
|
||||||
|
# lineinfile:
|
||||||
|
# dest: /etc/sudoers
|
||||||
|
# state: present
|
||||||
|
# regexp: "^#?%wheel"
|
||||||
|
# line: "%wheel ALL=(ALL) NOPASSWD: ALL"
|
||||||
|
# validate: /usr/sbin/visudo -cf %s
|
||||||
|
|
||||||
|
# - command:
|
||||||
|
# cmd: whoami
|
||||||
|
# no_log: true
|
||||||
|
# become: false
|
||||||
|
# register: main_user
|
||||||
|
|
||||||
|
# - set_fact:
|
||||||
|
# main_user: "{{ main_user.stdout }}"
|
||||||
|
# no_log: true
|
||||||
|
|
||||||
|
# - name: Create paru sources dir
|
||||||
|
# file:
|
||||||
|
# path: "{{ paru_src_path }}"
|
||||||
|
# state: directory
|
||||||
|
# owner: "{{ main_user }}"
|
||||||
|
|
||||||
|
# - name: Clone git sources
|
||||||
|
# become: false
|
||||||
|
# git:
|
||||||
|
# repo: "{{ paru_git_repo }}"
|
||||||
|
# dest: "{{ paru_src_path }}"
|
||||||
|
|
||||||
|
# # note: this only works because SUDOERS password prompt is disabled
|
||||||
|
# - name: Build and install
|
||||||
|
# become: false
|
||||||
|
# command:
|
||||||
|
# chdir: "{{ paru_src_path }}"
|
||||||
|
# cmd: "makepkg -si -f --noconfirm"
|
||||||
|
|
||||||
|
# - name: Restore sudo with password prompt
|
||||||
|
# lineinfile:
|
||||||
|
# dest: /etc/sudoers
|
||||||
|
# state: present
|
||||||
|
# regexp: "^#?%wheel"
|
||||||
|
# line: "%wheel ALL=(ALL:ALL) ALL"
|
||||||
|
# validate: /usr/sbin/visudo -cf %s
|
||||||
|
# when: not paru.stat.exists
|
||||||
block:
|
block:
|
||||||
- name: Get the last github release
|
- name: Get the last github release
|
||||||
ansible.builtin.uri:
|
ansible.builtin.uri:
|
||||||
@ -13,14 +71,14 @@
|
|||||||
register: paru_release
|
register: paru_release
|
||||||
|
|
||||||
- name: Extract tag_name
|
- name: Extract tag_name
|
||||||
set_fact:
|
ansible.builtin.set_fact:
|
||||||
paru_version: "{{ (paru_release.json.tag_name | regex_replace('^v', '')) }}"
|
paru_version: "{{ (paru_release.json.tag_name | regex_replace('^v', '')) }}"
|
||||||
|
|
||||||
- name: Get the binary URL ({{ os_arch }})
|
- name: Get the binary URL ({{ os_arch }})
|
||||||
set_fact:
|
ansible.builtin.set_fact:
|
||||||
paru_url: "{{ item.browser_download_url }}"
|
paru_url: "{{ item.browser_download_url }}"
|
||||||
loop: "{{ paru_release.json.assets }}"
|
loop: "{{ paru_release.json.assets }}"
|
||||||
when: "'{{ os_arch }}.tar.zst' in item.name"
|
when: "'os_arch.tar.zst' in item.name"
|
||||||
|
|
||||||
- name: Download
|
- name: Download
|
||||||
ansible.builtin.get_url:
|
ansible.builtin.get_url:
|
||||||
@ -45,61 +103,3 @@
|
|||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "/tmp/paru-{{ os_arch }}.tar.zst"
|
path: "/tmp/paru-{{ os_arch }}.tar.zst"
|
||||||
state: absent
|
state: absent
|
||||||
when: not paru.stat.exists
|
|
||||||
##
|
|
||||||
## Deprecated version with compilation
|
|
||||||
##
|
|
||||||
# - name: Install paru
|
|
||||||
# block:
|
|
||||||
# - name: Install build dependencies
|
|
||||||
# package:
|
|
||||||
# name:
|
|
||||||
# - base-devel
|
|
||||||
# - git
|
|
||||||
# state: present
|
|
||||||
|
|
||||||
# - name: Disable sudo password prompt (makepkg sudoers hack)
|
|
||||||
# lineinfile:
|
|
||||||
# dest: /etc/sudoers
|
|
||||||
# state: present
|
|
||||||
# regexp: "^#?%wheel"
|
|
||||||
# line: "%wheel ALL=(ALL) NOPASSWD: ALL"
|
|
||||||
# validate: /usr/sbin/visudo -cf %s
|
|
||||||
|
|
||||||
# - command:
|
|
||||||
# cmd: whoami
|
|
||||||
# no_log: true
|
|
||||||
# become: false
|
|
||||||
# register: main_user
|
|
||||||
|
|
||||||
# - set_fact:
|
|
||||||
# main_user: "{{ main_user.stdout }}"
|
|
||||||
# no_log: true
|
|
||||||
|
|
||||||
# - name: Create paru sources dir
|
|
||||||
# file:
|
|
||||||
# path: "{{ paru_src_path }}"
|
|
||||||
# state: directory
|
|
||||||
# owner: "{{ main_user }}"
|
|
||||||
|
|
||||||
# - name: Clone git sources
|
|
||||||
# become: false
|
|
||||||
# git:
|
|
||||||
# repo: "{{ paru_git_repo }}"
|
|
||||||
# dest: "{{ paru_src_path }}"
|
|
||||||
|
|
||||||
# # note: this only works because SUDOERS password prompt is disabled
|
|
||||||
# - name: Build and install
|
|
||||||
# become: false
|
|
||||||
# command:
|
|
||||||
# chdir: "{{ paru_src_path }}"
|
|
||||||
# cmd: "makepkg -si -f --noconfirm"
|
|
||||||
|
|
||||||
# - name: Restore sudo with password prompt
|
|
||||||
# lineinfile:
|
|
||||||
# dest: /etc/sudoers
|
|
||||||
# state: present
|
|
||||||
# regexp: "^#?%wheel"
|
|
||||||
# line: "%wheel ALL=(ALL:ALL) ALL"
|
|
||||||
# validate: /usr/sbin/visudo -cf %s
|
|
||||||
# when: not paru.stat.exists
|
|
||||||
|
|||||||
@ -1,60 +1,60 @@
|
|||||||
---
|
---
|
||||||
- name: Check if yay is already installed
|
- name: Check if yay is already installed
|
||||||
stat:
|
ansible.builtin.stat:
|
||||||
path: /usr/bin/yay
|
path: /usr/bin/yay
|
||||||
register: yay
|
register: yay
|
||||||
|
|
||||||
- name: Install yay
|
- name: Install yay
|
||||||
|
when: not yay.stat.exists
|
||||||
block:
|
block:
|
||||||
- name: Install build dependencies
|
- name: Install build dependencies
|
||||||
package:
|
ansible.builtin.package:
|
||||||
name:
|
name:
|
||||||
- base-devel
|
- base-devel
|
||||||
- git
|
- git
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
- name: Disable sudo password prompt (makepkg sudoers hack)
|
- name: Disable sudo password prompt (makepkg sudoers hack)
|
||||||
lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
dest: /etc/sudoers
|
dest: /etc/sudoers
|
||||||
state: present
|
state: present
|
||||||
regexp: "^#?%wheel"
|
regexp: "^#?%wheel"
|
||||||
line: "%wheel ALL=(ALL) NOPASSWD: ALL"
|
line: "%wheel ALL=(ALL) NOPASSWD: ALL"
|
||||||
validate: /usr/sbin/visudo -cf %s
|
validate: /usr/sbin/visudo -cf %s
|
||||||
|
|
||||||
- command:
|
- ansible.builtin.command:
|
||||||
cmd: whoami
|
cmd: whoami
|
||||||
no_log: true
|
no_log: true
|
||||||
become: false
|
become: false
|
||||||
register: main_user
|
register: main_user
|
||||||
|
|
||||||
- set_fact:
|
- ansible.builtin.set_fact:
|
||||||
main_user: "{{ main_user.stdout }}"
|
main_user: "{{ main_user.stdout }}"
|
||||||
no_log: true
|
no_log: true
|
||||||
|
|
||||||
- name: Create yay sources dir
|
- name: Create yay sources dir
|
||||||
file:
|
ansible.builtin.file:
|
||||||
path: "{{ yay_src_path }}"
|
path: "{{ yay_src_path }}"
|
||||||
state: directory
|
state: directory
|
||||||
owner: "{{ main_user }}"
|
owner: "{{ main_user }}"
|
||||||
|
|
||||||
- name: Clone git sources
|
- name: Clone git sources
|
||||||
become: false
|
become: false
|
||||||
git:
|
ansible.builtin.git:
|
||||||
repo: "{{ yay_git_repo }}"
|
repo: "{{ yay_git_repo }}"
|
||||||
dest: "{{ yay_src_path }}"
|
dest: "{{ yay_src_path }}"
|
||||||
|
|
||||||
# note: this only works because SUDOERS password prompt is disabled
|
# note: this only works because SUDOERS password prompt is disabled
|
||||||
- name: Build and install
|
- name: Build and install
|
||||||
become: false
|
become: false
|
||||||
command:
|
ansible.builtin.command:
|
||||||
chdir: "{{ yay_src_path }}"
|
chdir: "{{ yay_src_path }}"
|
||||||
cmd: "makepkg -si -f --noconfirm"
|
cmd: "makepkg -si -f --noconfirm"
|
||||||
|
|
||||||
- name: Restore sudo with password prompt
|
- name: Restore sudo with password prompt
|
||||||
lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
dest: /etc/sudoers
|
dest: /etc/sudoers
|
||||||
state: present
|
state: present
|
||||||
regexp: "^#?%wheel"
|
regexp: "^#?%wheel"
|
||||||
line: "%wheel ALL=(ALL:ALL) ALL"
|
line: "%wheel ALL=(ALL:ALL) ALL"
|
||||||
validate: /usr/sbin/visudo -cf %s
|
validate: /usr/sbin/visudo -cf %s
|
||||||
when: not yay.stat.exists
|
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
|
---
|
||||||
ssd_trim_periodicity: monthly
|
ssd_trim_periodicity: monthly
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
- name: Ensure disks are formatted correctly
|
- name: Ensure disks are formatted correctly
|
||||||
include_tasks: partitioning.yml
|
ansible.builtin.include_tasks: partitioning.yml
|
||||||
loop: "{{ disk_partitioning | default([]) }}"
|
loop: "{{ disk_partitioning | default([]) }}"
|
||||||
|
|
||||||
- name: Enable trim SSD if there is at least one
|
- name: Enable trim SSD if there is at least one
|
||||||
include_tasks: trim-ssd.yml
|
ansible.builtin.include_tasks: trim-ssd.yml
|
||||||
|
|||||||
@ -1,23 +1,23 @@
|
|||||||
---
|
---
|
||||||
- name: Install sfdisk
|
- name: Install sfdisk
|
||||||
package:
|
ansible.builtin.package:
|
||||||
name: util-linux
|
name: util-linux
|
||||||
state: present
|
state: present
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
- name: Install hdparm
|
- name: Install hdparm
|
||||||
package:
|
ansible.builtin.package:
|
||||||
name: hdparm
|
name: hdparm
|
||||||
state: present
|
state: present
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
- name: Load expected layout from file (controller side)
|
- name: Load expected layout from file (controller side)
|
||||||
set_fact:
|
ansible.builtin.set_fact:
|
||||||
expected_layout: "{{ lookup('file', item.layout_file) }}"
|
expected_layout: "{{ lookup('file', item.layout_file) }}"
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
- name: Get current layout from remote
|
- name: Get current layout from remote
|
||||||
command: "sfdisk --dump {{ item.device }}"
|
ansible.builtin.command: "sfdisk --dump {{ item.device }}"
|
||||||
register: current_layout
|
register: current_layout
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
@ -25,18 +25,18 @@
|
|||||||
vars:
|
vars:
|
||||||
current_clean: "{{ current_layout.stdout | trim | regex_replace('\\s+', ' ') }}"
|
current_clean: "{{ current_layout.stdout | trim | regex_replace('\\s+', ' ') }}"
|
||||||
expected_clean: "{{ expected_layout | trim | regex_replace('\\s+', ' ') }}"
|
expected_clean: "{{ expected_layout | trim | regex_replace('\\s+', ' ') }}"
|
||||||
set_fact:
|
ansible.builtin.set_fact:
|
||||||
layout_differs: "{{ current_clean != expected_clean }}"
|
layout_differs: "{{ current_clean != expected_clean }}"
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
- name: Copy layout file to remote (only if different)
|
- name: Copy layout file to remote (only if different)
|
||||||
copy:
|
ansible.builtin.copy:
|
||||||
content: "{{ expected_layout }}"
|
content: "{{ expected_layout }}"
|
||||||
dest: "/tmp/expected-{{ item.device | basename }}.sfdisk"
|
dest: "/tmp/expected-{{ item.device | basename }}.sfdisk"
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
when: layout_differs
|
when: layout_differs
|
||||||
|
|
||||||
- name: Apply partition table using sfdisk
|
- name: Apply partition table using sfdisk
|
||||||
command: >
|
ansible.builtin.command: >
|
||||||
sfdisk {{ item.device }} < {{ item.layout_file }}
|
sfdisk {{ item.device }} < {{ item.layout_file }}
|
||||||
when: layout_differs
|
when: layout_differs
|
||||||
|
|||||||
@ -1,22 +1,22 @@
|
|||||||
---
|
---
|
||||||
# see: https://wiki.archlinux.org/title/Solid_state_drive#Periodic_TRIM
|
# see: https://wiki.archlinux.org/title/Solid_state_drive#Periodic_TRIM
|
||||||
- name: Check if there is at least one SSD
|
- name: Check if there is at least one SSD
|
||||||
set_fact:
|
ansible.builtin.set_fact:
|
||||||
has_at_least_one_ssd: "{{ ansible_facts.devices | dict2items | selectattr('value.rotational', 'equalto', '0') | list | length > 0}}"
|
has_at_least_one_ssd: "{{ ansible_facts.devices | dict2items | selectattr('value.rotational', 'equalto', '0') | list | length > 0 }}"
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
- name: Skip trim role
|
- name: Skip trim role
|
||||||
meta: end_play
|
ansible.builtin.meta: end_play
|
||||||
when: not has_at_least_one_ssd
|
when: not has_at_least_one_ssd
|
||||||
|
|
||||||
- name: install trim tools
|
- name: Install trim tools
|
||||||
package:
|
ansible.builtin.package:
|
||||||
name: util-linux
|
name: util-linux
|
||||||
state: present
|
state: present
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
- name: edit trim periodicity if needed
|
- name: Edit trim periodicity if needed
|
||||||
template:
|
ansible.builtin.template:
|
||||||
src: templates/fstrim.timer.j2
|
src: templates/fstrim.timer.j2
|
||||||
dest: "/etc/systemd/system/fstrim.timer.d/override.conf"
|
dest: "/etc/systemd/system/fstrim.timer.d/override.conf"
|
||||||
owner: root
|
owner: root
|
||||||
@ -24,20 +24,20 @@
|
|||||||
mode: "0644"
|
mode: "0644"
|
||||||
register: timer_config
|
register: timer_config
|
||||||
|
|
||||||
- name: systemd daemon reload
|
- name: Systemd daemon reload
|
||||||
systemd:
|
ansible.builtin.systemd:
|
||||||
daemon_reload: yes
|
daemon_reload: true
|
||||||
when: timer_config.changed
|
when: timer_config.changed
|
||||||
|
|
||||||
- name: enable periodic trim
|
- name: Enable periodic trim
|
||||||
systemd:
|
ansible.builtin.systemd:
|
||||||
name: fstrim.timer
|
name: fstrim.timer
|
||||||
enabled: yes
|
enabled: true
|
||||||
state: started
|
state: started
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
- name: install nvme-cli
|
- name: Install nvme-cli
|
||||||
package:
|
ansible.builtin.package:
|
||||||
name: nvme-cli
|
name: nvme-cli
|
||||||
state: present
|
state: present
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
|
---
|
||||||
docker_projects_dir: /opt/docker
|
docker_projects_dir: /opt/docker
|
||||||
|
|||||||
@ -5,49 +5,49 @@
|
|||||||
# Archlinux: only if your target is meant to frequently build docker images
|
# Archlinux: only if your target is meant to frequently build docker images
|
||||||
# see: https://stackoverflow.com/a/78352698
|
# see: https://stackoverflow.com/a/78352698
|
||||||
|
|
||||||
- name: uninstall docker
|
- name: Uninstall docker
|
||||||
block:
|
|
||||||
- name: Include uninstall tasks
|
|
||||||
include_tasks: uninstall.yml
|
|
||||||
- name: Skip docker installation
|
|
||||||
meta: end_play
|
|
||||||
when: uninstall_docker | lower in ['yes', 'y']
|
when: uninstall_docker | lower in ['yes', 'y']
|
||||||
|
|
||||||
- name: install docker
|
block:
|
||||||
package:
|
- name: Include uninstall tasks
|
||||||
|
ansible.builtin.include_tasks: uninstall.yml
|
||||||
|
- name: Skip docker installation
|
||||||
|
ansible.builtin.meta: end_play
|
||||||
|
- name: Install docker
|
||||||
|
ansible.builtin.package:
|
||||||
name: docker
|
name: docker
|
||||||
|
|
||||||
- name: enable the service
|
- name: Enable the service
|
||||||
service:
|
ansible.builtin.service:
|
||||||
name: "docker"
|
name: "docker"
|
||||||
enabled: true
|
enabled: true
|
||||||
state: started
|
state: started
|
||||||
|
|
||||||
- command:
|
- ansible.builtin.command:
|
||||||
cmd: whoami
|
cmd: whoami
|
||||||
no_log: true
|
no_log: true
|
||||||
become: false
|
become: false
|
||||||
register: main_user
|
register: main_user
|
||||||
|
|
||||||
- set_fact:
|
- ansible.builtin.set_fact:
|
||||||
main_user: "{{ main_user.stdout }}"
|
main_user: "{{ main_user.stdout }}"
|
||||||
no_log: true
|
no_log: true
|
||||||
|
|
||||||
- name: create projects directory
|
- name: Create projects directory
|
||||||
file:
|
ansible.builtin.file:
|
||||||
path: "{{ docker_projects_dir }}"
|
path: "{{ docker_projects_dir }}"
|
||||||
state: directory
|
state: directory
|
||||||
owner: "{{ main_user }}"
|
owner: "{{ main_user }}"
|
||||||
group: "{{ main_user }}"
|
group: "{{ main_user }}"
|
||||||
|
|
||||||
- name: allow user to use docker
|
- name: Allow user to use docker
|
||||||
user:
|
ansible.builtin.user:
|
||||||
name: "{{ main_user }}"
|
name: "{{ main_user }}"
|
||||||
groups: docker
|
groups: docker
|
||||||
append: yes
|
append: true
|
||||||
register: docker_group
|
register: docker_group
|
||||||
|
|
||||||
- name: inform the user that user needs to logout and login again
|
- name: Inform the user that user needs to logout and login again
|
||||||
debug:
|
ansible.builtin.debug:
|
||||||
msg: "Please logout and login again to make sure the user is added to the docker group"
|
msg: "Please logout and login again to make sure the user is added to the docker group"
|
||||||
when: docker_group.changed
|
when: docker_group.changed
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
---
|
---
|
||||||
- name: uninstall docker
|
- name: Uninstall docker
|
||||||
package:
|
ansible.builtin.package:
|
||||||
name: docker
|
name: docker
|
||||||
state: absent
|
state: absent
|
||||||
|
|
||||||
- name: prompt the user for confirmation
|
- name: Prompt the user for confirmation
|
||||||
ansible.builtin.pause:
|
ansible.builtin.pause:
|
||||||
prompt: "[IRREVERSIBLE] Are you sure you want to delete {{ docker_projects_dir }}?"
|
prompt: "[IRREVERSIBLE] Are you sure you want to delete {{ docker_projects_dir }}?"
|
||||||
echo: yes
|
echo: true
|
||||||
register: confirmation
|
register: confirmation
|
||||||
|
|
||||||
- name: remote projects directory
|
- name: Remote projects directory
|
||||||
file:
|
ansible.builtin.file:
|
||||||
path: "{{ docker_projects_dir }}"
|
path: "{{ docker_projects_dir }}"
|
||||||
state: absent
|
state: absent
|
||||||
owner: "{{ main_user }}"
|
owner: "{{ main_user }}"
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
|
---
|
||||||
fail2ban_firewall: ufw
|
fail2ban_firewall: ufw
|
||||||
fail2ban_backend: systemd
|
fail2ban_backend: systemd
|
||||||
|
|||||||
@ -1,27 +1,27 @@
|
|||||||
---
|
---
|
||||||
# see: https://wiki.archlinux.org/title/Fail2ban
|
# see: https://wiki.archlinux.org/title/Fail2ban
|
||||||
- name: Install fail2ban
|
- name: Install fail2ban
|
||||||
package:
|
ansible.builtin.package:
|
||||||
name: fail2ban
|
name: fail2ban
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
- name: Ensure fail2ban configuration is only owned by root
|
- name: Ensure fail2ban configuration is only owned by root
|
||||||
file:
|
ansible.builtin.file:
|
||||||
path: /etc/fail2ban
|
path: /etc/fail2ban
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
mode: 0700
|
mode: "0700"
|
||||||
recurse: yes
|
recurse: true
|
||||||
|
|
||||||
- name: Install Fail2ban Config
|
- name: Install Fail2ban Config
|
||||||
block:
|
block:
|
||||||
- name: General configuration
|
- name: General configuration
|
||||||
template:
|
ansible.builtin.template:
|
||||||
src: jail.local.j2
|
src: jail.local.j2
|
||||||
dest: /etc/fail2ban/jail.local
|
dest: /etc/fail2ban/jail.local
|
||||||
mode: "0600"
|
mode: "0600"
|
||||||
- name: Service custom jail
|
- name: Service custom jail
|
||||||
template:
|
ansible.builtin.template:
|
||||||
src: "{{ item.src }}"
|
src: "{{ item.src }}"
|
||||||
dest: "{{ item.dest }}"
|
dest: "{{ item.dest }}"
|
||||||
mode: "0600"
|
mode: "0600"
|
||||||
@ -32,28 +32,28 @@
|
|||||||
- name: Service hardening (read-only root rights)
|
- name: Service hardening (read-only root rights)
|
||||||
block:
|
block:
|
||||||
- name: Check if hardening configuration is already applied
|
- name: Check if hardening configuration is already applied
|
||||||
stat:
|
ansible.builtin.stat:
|
||||||
path: /etc/systemd/system/fail2ban.service.d/override.conf
|
path: /etc/systemd/system/fail2ban.service.d/override.conf
|
||||||
register: override_conf
|
register: override_conf
|
||||||
- name: Create configuration directory
|
- name: Create configuration directory
|
||||||
file:
|
ansible.builtin.file:
|
||||||
path: /etc/systemd/system/fail2ban.service.d
|
path: /etc/systemd/system/fail2ban.service.d
|
||||||
state: directory
|
state: directory
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
mode: 0700
|
mode: "0700"
|
||||||
- name: Apply hardening configuration
|
- name: Apply hardening configuration
|
||||||
template:
|
ansible.builtin.template:
|
||||||
src: hardened.fail2ban.conf.j2
|
src: hardened.fail2ban.conf.j2
|
||||||
dest: /etc/systemd/system/fail2ban.service.d/override.conf
|
dest: /etc/systemd/system/fail2ban.service.d/override.conf
|
||||||
when: not override_conf.stat.exists
|
when: not override_conf.stat.exists
|
||||||
- name: Reload systemd
|
- name: Reload systemd
|
||||||
systemd:
|
ansible.builtin.systemd:
|
||||||
daemon_reload: yes
|
daemon_reload: true
|
||||||
when: not override_conf.stat.exists
|
when: not override_conf.stat.exists
|
||||||
|
|
||||||
- name: Start and enable fail2ban
|
- name: Start and enable fail2ban
|
||||||
service:
|
ansible.builtin.service:
|
||||||
name: fail2ban
|
name: fail2ban
|
||||||
state: started
|
state: started
|
||||||
enabled: yes
|
enabled: true
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
- name: install oryx
|
- name: install oryx
|
||||||
cmd: paru -S oryx
|
cmd: paru -S oryx
|
||||||
when: ansible_facts['os_family'] == 'Archlinux'
|
when: ansible_facts['os_family'] == 'Archlinux'
|
||||||
|
|||||||
@ -1,19 +1,19 @@
|
|||||||
---
|
---
|
||||||
- name: Check if the interface ipv4 address is defined
|
- name: Check if the interface ipv4 address is defined
|
||||||
block:
|
|
||||||
- debug:
|
|
||||||
msg: "Warning: iface {{ interface.name }} has no defined ipv4 address, skipping configuration"
|
|
||||||
- name: Skip net-config role for {{ interface.name }}
|
|
||||||
meta: end_play
|
|
||||||
when: interface.ipv4.address is not defined
|
when: interface.ipv4.address is not defined
|
||||||
|
|
||||||
|
block:
|
||||||
|
- ansible.builtin.debug:
|
||||||
|
msg: "Warning: iface {{ interface.name }} has no defined ipv4 address, skipping configuration"
|
||||||
|
- name: Skip net-config role for {{ interface.name }}
|
||||||
|
ansible.builtin.meta: end_play
|
||||||
- name: Check if the interface is already configured
|
- name: Check if the interface is already configured
|
||||||
stat:
|
ansible.builtin.stat:
|
||||||
path: /etc/systemd/network/20-{{ interface.name }}.network
|
path: /etc/systemd/network/20-{{ interface.name }}.network
|
||||||
register: network_file
|
register: network_file
|
||||||
|
|
||||||
- name: What patch is needed
|
- name: What patch is needed
|
||||||
debug:
|
ansible.builtin.debug:
|
||||||
msg: >-
|
msg: >-
|
||||||
{%- if network_file.stat.exists == true -%}
|
{%- if network_file.stat.exists == true -%}
|
||||||
iface {{ interface.name }} is already configured, no action needed.
|
iface {{ interface.name }} is already configured, no action needed.
|
||||||
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
- name: Create systemd-network link file
|
- name: Create systemd-network link file
|
||||||
when: network_file.stat.exists != true
|
when: network_file.stat.exists != true
|
||||||
template:
|
ansible.builtin.template:
|
||||||
src: systemd.network.j2
|
src: systemd.network.j2
|
||||||
dest: /etc/systemd/network/20-{{ interface.name }}.network
|
dest: /etc/systemd/network/20-{{ interface.name }}.network
|
||||||
owner: root
|
owner: root
|
||||||
@ -31,6 +31,6 @@
|
|||||||
mode: "0644"
|
mode: "0644"
|
||||||
|
|
||||||
- name: Notify a reload is required
|
- name: Notify a reload is required
|
||||||
set_fact:
|
ansible.builtin.set_fact:
|
||||||
network_reload_required: true
|
network_reload_required: true
|
||||||
when: network_file.stat.exists != true
|
when: network_file.stat.exists != true
|
||||||
|
|||||||
@ -1,17 +1,11 @@
|
|||||||
---
|
---
|
||||||
- name: "Check {{ interface.name }} ({{ interface.mac_address }}) rule"
|
- name: "Check {{ interface.name }} ({{ interface.mac_address }}) rule"
|
||||||
set_fact:
|
ansible.builtin.set_fact:
|
||||||
interface_original_name: "{{ ansible_facts.interfaces
|
interface_original_name: "{{ ansible_facts.interfaces | select('in', ansible_facts) | map('extract', ansible_facts) | selectattr('pciid', 'defined') | selectattr('macaddress',
|
||||||
| select('in', ansible_facts)
|
'equalto', interface.mac_address) | map(attribute='device') | first }}"
|
||||||
| map('extract', ansible_facts)
|
|
||||||
| selectattr('pciid', 'defined')
|
|
||||||
| selectattr('macaddress', 'equalto', interface.mac_address)
|
|
||||||
| map(attribute='device')
|
|
||||||
| first
|
|
||||||
}}"
|
|
||||||
|
|
||||||
- name: What patch is needed
|
- name: What patch is needed
|
||||||
debug:
|
ansible.builtin.debug:
|
||||||
msg: >-
|
msg: >-
|
||||||
{%- if interface_original_name != interface.name -%}
|
{%- if interface_original_name != interface.name -%}
|
||||||
iface {{ interface_original_name }} ({{ interface.mac_address }}) will be patched to {{ interface.name }}.
|
iface {{ interface_original_name }} ({{ interface.mac_address }}) will be patched to {{ interface.name }}.
|
||||||
@ -21,7 +15,7 @@
|
|||||||
|
|
||||||
- name: Create persistent-net link file
|
- name: Create persistent-net link file
|
||||||
when: interface_original_name != interface.name
|
when: interface_original_name != interface.name
|
||||||
template:
|
ansible.builtin.template:
|
||||||
src: persistent-net.link.j2
|
src: persistent-net.link.j2
|
||||||
dest: /etc/systemd/network/10-persistent-net-{{ interface.name }}.link
|
dest: /etc/systemd/network/10-persistent-net-{{ interface.name }}.link
|
||||||
owner: root
|
owner: root
|
||||||
@ -29,6 +23,6 @@
|
|||||||
mode: "0644"
|
mode: "0644"
|
||||||
|
|
||||||
- name: Notify a reboot is required
|
- name: Notify a reboot is required
|
||||||
set_fact:
|
ansible.builtin.set_fact:
|
||||||
reboot_required: true
|
reboot_required: true
|
||||||
when: interface_original_name != interface.name
|
when: interface_original_name != interface.name
|
||||||
|
|||||||
@ -1,25 +1,25 @@
|
|||||||
---
|
---
|
||||||
- name: Setup persistent network interface(s)
|
- name: Setup persistent network interface(s)
|
||||||
include_role:
|
ansible.builtin.include_role:
|
||||||
name: net-persist
|
name: net-persist
|
||||||
public: yes
|
public: true
|
||||||
vars:
|
vars:
|
||||||
interface: "{{ item }}"
|
interface: "{{ item }}"
|
||||||
loop: "{{ hostvars[inventory_hostname].network_interfaces | default([]) }}"
|
loop: "{{ hostvars[inventory_hostname].network_interfaces | default([]) }}"
|
||||||
|
|
||||||
- name: Configure network interface(s)
|
- name: Configure network interface(s)
|
||||||
include_role:
|
ansible.builtin.include_role:
|
||||||
name: net-config
|
name: net-config
|
||||||
public: yes
|
public: true
|
||||||
vars:
|
vars:
|
||||||
interface: "{{ item }}"
|
interface: "{{ item }}"
|
||||||
loop: "{{ hostvars[inventory_hostname].network_interfaces | default([]) }}"
|
loop: "{{ hostvars[inventory_hostname].network_interfaces | default([]) }}"
|
||||||
|
|
||||||
- name: Reload networkd and resolved
|
- name: Reload networkd and resolved
|
||||||
systemd:
|
ansible.builtin.systemd:
|
||||||
name: "{{ item }}"
|
name: "{{ item }}"
|
||||||
state: reloaded
|
state: reloaded
|
||||||
daemon_reload: yes
|
daemon_reload: true
|
||||||
loop:
|
loop:
|
||||||
- systemd-networkd
|
- systemd-networkd
|
||||||
- systemd-resolved
|
- systemd-resolved
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
# - host: "192.168.1.0/24" # readonly access for other lan clients
|
# - host: "192.168.1.0/24" # readonly access for other lan clients
|
||||||
# options: "ro,sync,no_subtree_check"
|
# options: "ro,sync,no_subtree_check"
|
||||||
nfs_shares: []
|
nfs_shares: []
|
||||||
|
|
||||||
nfs_configuration_file: "/etc/nfs.conf"
|
nfs_configuration_file: "/etc/nfs.conf"
|
||||||
|
|
||||||
nfs_exports_file: "/etc/exports"
|
nfs_exports_file: "/etc/exports"
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
name: "nfsv4-server"
|
name: "nfsv4-server"
|
||||||
state: restarted
|
state: restarted
|
||||||
daemon_reload: yes
|
daemon_reload: true
|
||||||
|
|
||||||
- name: "Update exportfs"
|
- name: "Update exportfs"
|
||||||
ansible.builtin.command: exportfs -ra
|
ansible.builtin.command: exportfs -ra
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
---
|
---
|
||||||
- name: install nfs-server
|
- name: Install nfs-server
|
||||||
package:
|
ansible.builtin.package:
|
||||||
name: "{{ (ansible_facts['os_family'] == 'Archlinux') | ternary('nfs-utils', 'nfs-kernel-server') }}"
|
name: "{{ (ansible_facts['os_family'] == 'Archlinux') | ternary('nfs-utils', 'nfs-kernel-server') }}"
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
- name: configure nfs configuration
|
- name: Configure nfs configuration
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: templates/nfs.conf.j2
|
src: templates/nfs.conf.j2
|
||||||
dest: "{{ nfs_configuration_file }}"
|
dest: "{{ nfs_configuration_file }}"
|
||||||
@ -13,7 +13,7 @@
|
|||||||
mode: "0644"
|
mode: "0644"
|
||||||
notify: Reload systemd and restart nfs-server
|
notify: Reload systemd and restart nfs-server
|
||||||
|
|
||||||
- name: configure nfs-server exports
|
- name: Configure nfs-server exports
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: templates/exports.j2
|
src: templates/exports.j2
|
||||||
dest: "{{ nfs_exports_file }}"
|
dest: "{{ nfs_exports_file }}"
|
||||||
@ -22,13 +22,13 @@
|
|||||||
mode: "0644"
|
mode: "0644"
|
||||||
notify: Update exportfs
|
notify: Update exportfs
|
||||||
|
|
||||||
- name: systemd service for nfs-server is started and enabled
|
- name: Systemd service for nfs-server is started and enabled
|
||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
name: nfsv4-server
|
name: nfsv4-server
|
||||||
state: started
|
state: started
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
- name: setup firewall rules for nfs on port
|
- name: Setup firewall rules for nfs on port
|
||||||
community.general.ufw:
|
community.general.ufw:
|
||||||
rule: allow
|
rule: allow
|
||||||
src: "{{ item }}"
|
src: "{{ item }}"
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
|
---
|
||||||
# NTP configuration file
|
# NTP configuration file
|
||||||
ntp_config_file: "/etc/ntp.conf"
|
ntp_config_file: "/etc/ntp.conf"
|
||||||
|
|
||||||
# NTP servers to use.
|
# NTP servers to use.
|
||||||
ntp_pools: -" 0.uk.pool.ntp.org"
|
ntp_pools: -" 0.uk.pool.ntp.org" -" 1.uk.pool.ntp.org" -" 2.uk.pool.ntp.org" -" 3.uk.pool.ntp.org"
|
||||||
-" 1.uk.pool.ntp.org"
|
|
||||||
-" 2.uk.pool.ntp.org"
|
|
||||||
-" 3.uk.pool.ntp.org"
|
|
||||||
|
|
||||||
# System timezone
|
# System timezone
|
||||||
ntp_timezone: "Europe/London"
|
ntp_timezone: "Europe/London"
|
||||||
|
|||||||
@ -3,4 +3,4 @@
|
|||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
name: ntpd
|
name: ntpd
|
||||||
state: restarted
|
state: restarted
|
||||||
daemon_reload: yes
|
daemon_reload: true
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
---
|
---
|
||||||
- name: install NTP package
|
- name: Install NTP package
|
||||||
package:
|
ansible.builtin.package:
|
||||||
name: "ntp"
|
name: "ntp"
|
||||||
state: present
|
state: present
|
||||||
update_cache: yes
|
update_cache: true
|
||||||
|
|
||||||
- name: set system timezone to {{ ntp_timezone }}"
|
- name: Set system timezone to {{ ntp_timezone }}"
|
||||||
community.general.timezone:
|
community.general.timezone:
|
||||||
name: "{{ ntp_timezone }}"
|
name: "{{ ntp_timezone }}"
|
||||||
notify: "Restart ntpd service"
|
notify: "Restart ntpd service"
|
||||||
|
|
||||||
- name: ensure NTP drift file directory exists
|
- name: Ensure NTP drift file directory exists
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "{{ ntp_drift_file | dirname }}"
|
path: "{{ ntp_drift_file | dirname }}"
|
||||||
state: directory
|
state: directory
|
||||||
@ -18,12 +18,12 @@
|
|||||||
group: "ntp"
|
group: "ntp"
|
||||||
mode: "0750"
|
mode: "0750"
|
||||||
|
|
||||||
- name: setup systems timezone
|
- name: Setup systems timezone
|
||||||
community.general.timezone:
|
community.general.timezone:
|
||||||
name: "{{ ntp_timezone }}"
|
name: "{{ ntp_timezone }}"
|
||||||
notify: Restart chronyd # Redémarrer chrony peut être utile après un changement de TZ pour qu'il la prenne bien en compte dans ses logs/opérations
|
notify: Restart chronyd # Redémarrer chrony peut être utile après un changement de TZ pour qu'il la prenne bien en compte dans ses logs/opérations
|
||||||
|
|
||||||
- name: "configure {{ ntp_config_file }}"
|
- name: "Configure {{ ntp_config_file }}"
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: "ntp.conf.j2"
|
src: "ntp.conf.j2"
|
||||||
dest: "{{ ntp_config_file }}"
|
dest: "{{ ntp_config_file }}"
|
||||||
@ -32,13 +32,13 @@
|
|||||||
mode: "0644"
|
mode: "0644"
|
||||||
notify: "Restart ntpd service"
|
notify: "Restart ntpd service"
|
||||||
|
|
||||||
- name: "ensure ntpd service is started and enabled"
|
- name: "Ensure ntpd service is started and enabled"
|
||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
name: "ntpd"
|
name: "ntpd"
|
||||||
state: started
|
state: started
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
- name: "configure ufw firewall"
|
- name: "Configure ufw firewall"
|
||||||
community.general.ufw:
|
community.general.ufw:
|
||||||
rule: allow
|
rule: allow
|
||||||
port: "{{ ntp_port }}"
|
port: "{{ ntp_port }}"
|
||||||
|
|||||||
14
roles/sshd/README.md
Normal file
14
roles/sshd/README.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# SSH server
|
||||||
|
|
||||||
|
## Enable authorized_keys fallback
|
||||||
|
|
||||||
|
When you encrypt your home data, you cannot allow hardened remote SSH connection.
|
||||||
|
To make this still possible, here is the trick: a fallback authorized_key file: /etc/ssh/authorized_keys/myuser
|
||||||
|
|
||||||
|
Simply enable this setting to get this working:
|
||||||
|
|
||||||
|
```
|
||||||
|
ssh_authorized_keys_fallback_enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
And you're set.
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
ssh_port: 22
|
ssh_port: 22
|
||||||
ssh_allowed_network: "192.168.1.0/24"
|
ssh_allowed_network: "192.168.1.0/24"
|
||||||
ssh_allowed_vpn_network: "192.168.27.0/27"
|
ssh_allowed_vpn_network: "192.168.27.0/27"
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
- name: Enable SSH
|
- name: Enable SSH
|
||||||
service:
|
service:
|
||||||
name: "{{ ssh_service_name }}"
|
name: "{{ ssh_service_name }}"
|
||||||
enabled: yes
|
enabled: true
|
||||||
|
|
||||||
- name: Allow local network incoming connection
|
- name: Allow local network incoming connection
|
||||||
ufw:
|
ufw:
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
|
---
|
||||||
ssh_package_name: "openssh"
|
ssh_package_name: "openssh"
|
||||||
ssh_service_name: "sshd"
|
ssh_service_name: "sshd"
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
|
---
|
||||||
ssh_package_name: "openssh-server"
|
ssh_package_name: "openssh-server"
|
||||||
ssh_service_name: "ssh"
|
ssh_service_name: "ssh"
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
unbound_config_base_path: /etc/unbound
|
unbound_config_base_path: /etc/unbound
|
||||||
unbound_config_path: "{{ unbound_config_base_path }}/unbound.conf"
|
unbound_config_path: "{{ unbound_config_base_path }}/unbound.conf"
|
||||||
unbound_root_hints_path: "{{ unbound_config_base_path }}/root.hints"
|
unbound_root_hints_path: "{{ unbound_config_base_path }}/root.hints"
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
name: unbound
|
name: unbound
|
||||||
state: restarted
|
state: restarted
|
||||||
daemon_reload: yes
|
daemon_reload: true
|
||||||
|
|
||||||
- name: Reload AppArmor profile
|
- name: Reload AppArmor profile
|
||||||
ansible.builtin.command: apparmor_parser -r {{ unbound_apparmor_profile_path }}
|
ansible.builtin.command: apparmor_parser -r {{ unbound_apparmor_profile_path }}
|
||||||
|
|||||||
@ -1,19 +1,19 @@
|
|||||||
---
|
---
|
||||||
# see: https://calomel.org/unbound_dns.html
|
# see: https://calomel.org/unbound_dns.html
|
||||||
# see: https://wiki.archlinux.org/title/Unbound
|
# see: https://wiki.archlinux.org/title/Unbound
|
||||||
- name: install unbound
|
- name: Install unbound
|
||||||
package:
|
ansible.builtin.package:
|
||||||
name: unbound
|
name: unbound
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
# Note: on archlinux this is already shipped within unbound
|
# Note: on archlinux this is already shipped within unbound
|
||||||
- name: install unbound-anchor on debian/ubuntu
|
- name: Install unbound-anchor on debian/ubuntu
|
||||||
package:
|
ansible.builtin.package:
|
||||||
name: unbound-anchor
|
name: unbound-anchor
|
||||||
state: present
|
state: present
|
||||||
when: ansible_facts['os_family'] == 'Debian'
|
when: ansible_facts['os_family'] == 'Debian'
|
||||||
|
|
||||||
- name: ensure unbound configuration is owned by unbound
|
- name: Ensure unbound configuration is owned by unbound
|
||||||
ansible.builtin.shell: |
|
ansible.builtin.shell: |
|
||||||
find "{{ unbound_config_base_path }}" -type d -exec chmod 755 {} \;
|
find "{{ unbound_config_base_path }}" -type d -exec chmod 755 {} \;
|
||||||
find "{{ unbound_config_base_path }}" -type f -exec chmod 644 {} \;
|
find "{{ unbound_config_base_path }}" -type f -exec chmod 644 {} \;
|
||||||
@ -21,7 +21,7 @@
|
|||||||
args:
|
args:
|
||||||
executable: /bin/bash
|
executable: /bin/bash
|
||||||
|
|
||||||
- name: ensure apparmor profile for unbound exists
|
- name: Ensure apparmor profile for unbound exists
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: /etc/apparmor.d/usr.sbin.unbound
|
dest: /etc/apparmor.d/usr.sbin.unbound
|
||||||
content: |
|
content: |
|
||||||
@ -34,59 +34,59 @@
|
|||||||
notify:
|
notify:
|
||||||
- Reload AppArmor profile
|
- Reload AppArmor profile
|
||||||
|
|
||||||
- name: check if root.hints exists
|
- name: Check if root.hints exists
|
||||||
stat:
|
ansible.builtin.stat:
|
||||||
path: "{{ unbound_root_hints_path }}"
|
path: "{{ unbound_root_hints_path }}"
|
||||||
register: root_hints
|
register: root_hints
|
||||||
|
|
||||||
- name: update root.hints (if older than 6 months or missing)
|
- name: Update root.hints (if older than 6 months or missing)
|
||||||
|
when: >
|
||||||
|
(not root_hints.stat.exists) or
|
||||||
|
(ansible_date_time.epoch | int - root_hints.stat.mtime > 15552000)
|
||||||
|
|
||||||
block:
|
block:
|
||||||
- name: download latest root hints from internic
|
- name: Download latest root hints from internic
|
||||||
ansible.builtin.get_url:
|
ansible.builtin.get_url:
|
||||||
url: https://www.internic.net/domain/named.root
|
url: https://www.internic.net/domain/named.root
|
||||||
dest: "{{ unbound_root_hints_path }}"
|
dest: "{{ unbound_root_hints_path }}"
|
||||||
owner: unbound
|
owner: unbound
|
||||||
group: unbound
|
group: unbound
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
when: >
|
- name: Check if unbound ad_servers configuration exists
|
||||||
(not root_hints.stat.exists) or
|
ansible.builtin.stat:
|
||||||
(ansible_date_time.epoch | int - root_hints.stat.mtime > 15552000)
|
|
||||||
|
|
||||||
- name: check if unbound ad_servers configuration exists
|
|
||||||
stat:
|
|
||||||
path: "{{ unbound_ad_servers_config_path }}"
|
path: "{{ unbound_ad_servers_config_path }}"
|
||||||
register: ad_servers
|
register: ad_servers
|
||||||
|
|
||||||
- name: update the ad_servers list if older than 2 weeks or missing
|
- name: Update the ad_servers list if older than 2 weeks or missing
|
||||||
|
when: >
|
||||||
|
(not ad_servers.stat.exists) or
|
||||||
|
(ansible_date_time.epoch | int - ad_servers.stat.mtime > 1209600)
|
||||||
|
|
||||||
block:
|
block:
|
||||||
- name: download stevenblack's hosts file
|
- name: Download stevenblack's hosts file
|
||||||
ansible.builtin.get_url:
|
ansible.builtin.get_url:
|
||||||
url: https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
|
url: https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
|
||||||
dest: /tmp/hosts.txt
|
dest: /tmp/hosts.txt
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
|
|
||||||
- name: convert hosts file to unbound format
|
- name: Convert hosts file to unbound format
|
||||||
ansible.builtin.shell: |
|
ansible.builtin.shell: |
|
||||||
grep '^0\.0\.0\.0' /tmp/hosts.txt | awk '{print "local-zone: \""$2"\" always_nxdomain"}' > "{{ unbound_ad_servers_config_path }}" &&
|
grep '^0\.0\.0\.0' /tmp/hosts.txt | awk '{print "local-zone: \""$2"\" always_nxdomain"}' > "{{ unbound_ad_servers_config_path }}" &&
|
||||||
chown unbound:unbound "{{ unbound_ad_servers_config_path }}"
|
chown unbound:unbound "{{ unbound_ad_servers_config_path }}"
|
||||||
args:
|
args:
|
||||||
executable: /bin/bash
|
executable: /bin/bash
|
||||||
|
|
||||||
- name: clean up temporary file
|
- name: Clean up temporary file
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: /tmp/hosts.txt
|
path: /tmp/hosts.txt
|
||||||
state: absent
|
state: absent
|
||||||
when: >
|
- name: Initialize dnssec trust anchor if missing
|
||||||
(not ad_servers.stat.exists) or
|
|
||||||
(ansible_date_time.epoch | int - ad_servers.stat.mtime > 1209600)
|
|
||||||
|
|
||||||
- name: initialize dnssec trust anchor if missing
|
|
||||||
ansible.builtin.command: unbound-anchor -a {{ unbound_anchor_root_key }}
|
ansible.builtin.command: unbound-anchor -a {{ unbound_anchor_root_key }}
|
||||||
args:
|
args:
|
||||||
creates: "{{ unbound_anchor_root_key }}"
|
creates: "{{ unbound_anchor_root_key }}"
|
||||||
|
|
||||||
- name: install unbound config
|
- name: Install unbound config
|
||||||
template:
|
ansible.builtin.template:
|
||||||
src: "{{ item.src }}"
|
src: "{{ item.src }}"
|
||||||
dest: "{{ item.dest }}"
|
dest: "{{ item.dest }}"
|
||||||
owner: unbound
|
owner: unbound
|
||||||
@ -99,14 +99,14 @@
|
|||||||
- Check Unbound config syntax
|
- Check Unbound config syntax
|
||||||
- Reload systemd and restart unbound
|
- Reload systemd and restart unbound
|
||||||
|
|
||||||
- name: make sure unbound starts after wg-quick@wg0
|
- name: Make sure unbound starts after wg-quick@wg0
|
||||||
block:
|
block:
|
||||||
- name: ensure unbound.service.d directory exists
|
- name: Ensure unbound.service.d directory exists
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: /etc/systemd/system/unbound.service.d
|
path: /etc/systemd/system/unbound.service.d
|
||||||
state: directory
|
state: directory
|
||||||
mode: "0755"
|
mode: "0755"
|
||||||
- name: configure unbound systemd service
|
- name: Configure unbound systemd service
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: /etc/systemd/system/unbound.service.d/override.conf
|
dest: /etc/systemd/system/unbound.service.d/override.conf
|
||||||
content: |
|
content: |
|
||||||
@ -115,13 +115,13 @@
|
|||||||
Requires=wg-quick@wg0.service
|
Requires=wg-quick@wg0.service
|
||||||
notify: Reload systemd and restart unbound
|
notify: Reload systemd and restart unbound
|
||||||
|
|
||||||
- name: enables unbound service
|
- name: Enables unbound service
|
||||||
ansible.builtin.service:
|
ansible.builtin.service:
|
||||||
name: unbound
|
name: unbound
|
||||||
enabled: yes
|
enabled: true
|
||||||
state: started
|
state: started
|
||||||
|
|
||||||
- name: firewall ufw rules for unbound
|
- name: Firewall ufw rules for unbound
|
||||||
community.general.ufw:
|
community.general.ufw:
|
||||||
rule: allow
|
rule: allow
|
||||||
port: "{{ unbound_port }}"
|
port: "{{ unbound_port }}"
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
wireguard_primary_interface: "{{ network_interfaces.0.name }}"
|
wireguard_primary_interface: "{{ network_interfaces.0.name }}"
|
||||||
wireguard_port: 51820 # static port to receive input connections
|
wireguard_port: 51820 # static port to receive input connections
|
||||||
wireguard_server_mode: true # enables NAT and open port
|
wireguard_server_mode: true # enables NAT and open port
|
||||||
|
|||||||
@ -1,58 +1,59 @@
|
|||||||
- name: install wireguard
|
---
|
||||||
package:
|
- name: Install wireguard
|
||||||
|
ansible.builtin.package:
|
||||||
name: "{{ (ansible_facts['os_family'] == 'Archlinux') | ternary('wireguard-tools', 'wireguard') }}"
|
name: "{{ (ansible_facts['os_family'] == 'Archlinux') | ternary('wireguard-tools', 'wireguard') }}"
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
# to support "DNS=" if used in a "client way"
|
# to support "DNS=" if used in a "client way"
|
||||||
- name: install openresolv/resolveconf
|
- name: Install openresolv/resolveconf
|
||||||
package:
|
ansible.builtin.package:
|
||||||
name: "{{ (ansible_facts['os_family'] == 'Archlinux') | ternary('openresolv', 'resolvconf') }}"
|
name: "{{ (ansible_facts['os_family'] == 'Archlinux') | ternary('openresolv', 'resolvconf') }}"
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
- name: ensure wireguard configuration is only owned by root
|
- name: Ensure wireguard configuration is only owned by root
|
||||||
file:
|
ansible.builtin.file:
|
||||||
path: "{{ wireguard_config_base_path }}"
|
path: "{{ wireguard_config_base_path }}"
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
mode: 0700
|
mode: "0700"
|
||||||
recurse: yes
|
recurse: true
|
||||||
|
|
||||||
- name: check if private key exists
|
- name: Check if private key exists
|
||||||
stat:
|
ansible.builtin.stat:
|
||||||
path: "{{ wireguard_config_base_path }}/privatekey"
|
path: "{{ wireguard_config_base_path }}/privatekey"
|
||||||
register: pkey_file
|
register: pkey_file
|
||||||
|
|
||||||
- name: generate wireguard keys if not present
|
- name: Generate wireguard keys if not present
|
||||||
shell: wg genkey | tee {{ wireguard_config_base_path }}/privatekey | wg pubkey > {{ wireguard_config_base_path }}/publickey
|
ansible.builtin.shell: wg genkey | tee {{ wireguard_config_base_path }}/privatekey | wg pubkey > {{ wireguard_config_base_path }}/publickey
|
||||||
when: not pkey_file.stat.exists
|
when: not pkey_file.stat.exists
|
||||||
|
|
||||||
- name: retrieve wireguard private key from file
|
- name: Retrieve wireguard private key from file
|
||||||
slurp:
|
ansible.builtin.slurp:
|
||||||
src: "{{ wireguard_config_base_path }}/privatekey"
|
src: "{{ wireguard_config_base_path }}/privatekey"
|
||||||
register: private_key
|
register: private_key
|
||||||
|
|
||||||
- name: set wireguard private key
|
- name: Set wireguard private key
|
||||||
set_fact:
|
ansible.builtin.set_fact:
|
||||||
wireguard_private_key: "{{ private_key['content'] | b64decode }}"
|
wireguard_private_key: "{{ private_key['content'] | b64decode }}"
|
||||||
|
|
||||||
- name: disable "dns=" instruction if unbound is used to avoid race conditions at startup
|
- name: Disable "dns=" instruction if unbound is used to avoid race conditions at startup
|
||||||
set_fact:
|
ansible.builtin.set_fact:
|
||||||
wireguard_dns:
|
wireguard_dns:
|
||||||
when: unbound_custom_lan_records is defined
|
when: unbound_custom_lan_records is defined
|
||||||
|
|
||||||
- name: install wireguard config
|
- name: Install wireguard config
|
||||||
template:
|
ansible.builtin.template:
|
||||||
src: wireguard.conf.j2
|
src: wireguard.conf.j2
|
||||||
dest: /etc/wireguard/{{ wireguard_interface }}.conf
|
dest: /etc/wireguard/{{ wireguard_interface }}.conf
|
||||||
|
|
||||||
- name: start and enable service
|
- name: Start and enable service
|
||||||
service:
|
ansible.builtin.service:
|
||||||
name: wg-quick@{{ wireguard_interface }}
|
name: wg-quick@{{ wireguard_interface }}
|
||||||
state: started
|
state: started
|
||||||
enabled: yes
|
enabled: true
|
||||||
daemon_reload: yes
|
daemon_reload: true
|
||||||
|
|
||||||
- name: configure the firewall for wireguard
|
- name: Configure the firewall for wireguard
|
||||||
community.general.ufw:
|
community.general.ufw:
|
||||||
rule: allow
|
rule: allow
|
||||||
port: "{{ wireguard_port }}"
|
port: "{{ wireguard_port }}"
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
---
|
---
|
||||||
# due to Ansible limitations, we cannot loop over a block, so we loop over a distinct tasks file...
|
# due to Ansible limitations, we cannot loop over a block, so we loop over a distinct tasks file...
|
||||||
# @see https://stackoverflow.com/a/58911694
|
# @see https://stackoverflow.com/a/58911694
|
||||||
- name: set ownership on dataset mountpoint
|
- name: Set ownership on dataset mountpoint
|
||||||
block:
|
block:
|
||||||
- name: get the mountpoint
|
- name: Get the mountpoint
|
||||||
ansible.builtin.shell: "zfs get -H -o value mountpoint {{ dataset.name }}"
|
ansible.builtin.command: "zfs get -H -o value mountpoint {{ dataset.name }}"
|
||||||
register: mountpoint
|
register: mountpoint
|
||||||
changed_when: false
|
changed_when: false
|
||||||
- name: set owner of mountpoints
|
- name: Set owner of mountpoints
|
||||||
file:
|
ansible.builtin.file:
|
||||||
path: "{{ mountpoint.stdout }}"
|
path: "{{ mountpoint.stdout }}"
|
||||||
owner: "{{ dataset.user | default(main_user) }}"
|
owner: "{{ dataset.user | default(main_user) }}"
|
||||||
group: "{{ dataset.group | default(main_user) }}"
|
group: "{{ dataset.group | default(main_user) }}"
|
||||||
|
|||||||
@ -1,25 +1,25 @@
|
|||||||
---
|
---
|
||||||
# see: https://docs.ansible.com/ansible/latest/collections/community/general/zfs_module.html
|
# see: https://docs.ansible.com/ansible/latest/collections/community/general/zfs_module.html
|
||||||
- name: managing filesystems, volumes, snapshots
|
- name: Managing filesystems, volumes, snapshots
|
||||||
zfs:
|
community.general.zfs:
|
||||||
name: "{{ item.name }}"
|
name: "{{ item.name }}"
|
||||||
state: "{{ item.state }}"
|
state: "{{ item.state }}"
|
||||||
extra_zfs_properties: "{{ item.extra_zfs_properties|default(omit) }}"
|
extra_zfs_properties: "{{ item.extra_zfs_properties | default(omit) }}"
|
||||||
origin: "{{ item.origin|default(omit) }}"
|
origin: "{{ item.origin | default(omit) }}"
|
||||||
with_items: "{{ zfs_datasets }}"
|
with_items: "{{ zfs_datasets }}"
|
||||||
|
|
||||||
- command:
|
- ansible.builtin.command:
|
||||||
cmd: whoami
|
cmd: whoami
|
||||||
no_log: true
|
no_log: true
|
||||||
become: false
|
become: false
|
||||||
register: main_user
|
register: main_user
|
||||||
|
|
||||||
- set_fact:
|
- ansible.builtin.set_fact:
|
||||||
main_user: "{{ main_user.stdout }}"
|
main_user: "{{ main_user.stdout }}"
|
||||||
no_log: true
|
no_log: true
|
||||||
|
|
||||||
- name: set dataset ownership
|
- name: Set dataset ownership
|
||||||
include_tasks: "./dataset-ownership.yml"
|
ansible.builtin.include_tasks: "./dataset-ownership.yml"
|
||||||
loop: "{{ zfs_datasets }}"
|
loop: "{{ zfs_datasets }}"
|
||||||
loop_control:
|
loop_control:
|
||||||
loop_var: dataset
|
loop_var: dataset
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
---
|
---
|
||||||
# due to Ansible limitations, we cannot loop over a block, so we loop over a distinct tasks file...
|
# due to Ansible limitations, we cannot loop over a block, so we loop over a distinct tasks file...
|
||||||
# @see https://stackoverflow.com/a/58911694
|
# @see https://stackoverflow.com/a/58911694
|
||||||
- name: prompt the user for confirmation
|
- name: Prompt the user for confirmation
|
||||||
ansible.builtin.pause:
|
ansible.builtin.pause:
|
||||||
prompt: "[IRREVERSIBLE] Are you sure you want to delete zpool {{ zpool.name }}?"
|
prompt: "[IRREVERSIBLE] Are you sure you want to delete zpool {{ zpool.name }}?"
|
||||||
echo: yes
|
echo: true
|
||||||
register: confirmation
|
register: confirmation
|
||||||
|
|
||||||
- name: deleting zpool
|
- name: Deleting zpool
|
||||||
ansible.builtin.command: "zpool destroy {{ zpool.name }}"
|
ansible.builtin.command: "zpool destroy {{ zpool.name }}"
|
||||||
when: confirmation.user_input | lower in ['yes', 'y']
|
when: confirmation.user_input | lower in ['yes', 'y']
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
- name: Check if zfs-linux-lts is installed
|
- name: Check if zfs-linux-lts is installed
|
||||||
command: pacman -Qi zfs-dkms
|
ansible.builtin.command: pacman -Qi zfs-dkms
|
||||||
register: zfs_dkms_installed
|
register: zfs_dkms_installed
|
||||||
changed_when: false
|
changed_when: false
|
||||||
failed_when: false
|
failed_when: false
|
||||||
@ -8,9 +8,9 @@
|
|||||||
- name: Install zfs
|
- name: Install zfs
|
||||||
when: zfs_dkms_installed.stderr
|
when: zfs_dkms_installed.stderr
|
||||||
block:
|
block:
|
||||||
- name: disable SUDOERS password prompt for makepkg
|
- name: Disable SUDOERS password prompt for makepkg
|
||||||
no_log: true
|
no_log: true
|
||||||
lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
dest: /etc/sudoers
|
dest: /etc/sudoers
|
||||||
state: present
|
state: present
|
||||||
regexp: "^#?%wheel"
|
regexp: "^#?%wheel"
|
||||||
@ -22,30 +22,29 @@
|
|||||||
# Using dkms with the lts linux kernel is a better approach IMO.
|
# Using dkms with the lts linux kernel is a better approach IMO.
|
||||||
- name: Install zfs
|
- name: Install zfs
|
||||||
become: false
|
become: false
|
||||||
command:
|
ansible.builtin.command:
|
||||||
cmd: "paru -S --noconfirm zfs-dkms zfs-utils"
|
cmd: "paru -S --noconfirm zfs-dkms zfs-utils"
|
||||||
|
|
||||||
- name: Restore SUDOERS password prompt after yay
|
- name: Restore SUDOERS password prompt after yay
|
||||||
no_log: true
|
no_log: true
|
||||||
lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
dest: /etc/sudoers
|
dest: /etc/sudoers
|
||||||
state: present
|
state: present
|
||||||
regexp: "^#?%wheel"
|
regexp: "^#?%wheel"
|
||||||
line: "%wheel ALL=(ALL:ALL) ALL"
|
line: "%wheel ALL=(ALL:ALL) ALL"
|
||||||
validate: /usr/sbin/visudo -cf %s
|
validate: /usr/sbin/visudo -cf %s
|
||||||
|
|
||||||
- name: check if /etc/hostid is present
|
- name: Check if /etc/hostid is present
|
||||||
stat:
|
ansible.builtin.stat:
|
||||||
path: /etc/hostid
|
path: /etc/hostid
|
||||||
register: hostid
|
register: hostid
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
- name: generate /etc/hostid if not present
|
- name: Generate /etc/hostid if not present
|
||||||
when: not hostid.stat.exists
|
when: not hostid.stat.exists
|
||||||
command: zgenhostid $(hostid)
|
ansible.builtin.command: zgenhostid $(hostid)
|
||||||
|
|
||||||
- name: Check if zrepl is installed
|
- name: Check if zrepl is installed
|
||||||
command: pacman -Qi zrepl
|
ansible.builtin.command: pacman -Qi zrepl
|
||||||
register: zrepl_installed
|
register: zrepl_installed
|
||||||
changed_when: false
|
changed_when: false
|
||||||
failed_when: false
|
failed_when: false
|
||||||
@ -53,9 +52,9 @@
|
|||||||
- name: Install zrepl
|
- name: Install zrepl
|
||||||
when: zrepl_installed.stderr
|
when: zrepl_installed.stderr
|
||||||
block:
|
block:
|
||||||
- name: disable SUDOERS password prompt for makepkg
|
- name: Disable SUDOERS password prompt for makepkg
|
||||||
no_log: true
|
no_log: true
|
||||||
lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
dest: /etc/sudoers
|
dest: /etc/sudoers
|
||||||
state: present
|
state: present
|
||||||
regexp: "^#?%wheel"
|
regexp: "^#?%wheel"
|
||||||
@ -64,12 +63,12 @@
|
|||||||
|
|
||||||
- name: Install zrepl
|
- name: Install zrepl
|
||||||
become: false
|
become: false
|
||||||
command:
|
ansible.builtin.command:
|
||||||
cmd: "paru -S --noconfirm zrepl"
|
cmd: "paru -S --noconfirm zrepl"
|
||||||
|
|
||||||
- name: Restore SUDOERS password prompt after paru
|
- name: Restore SUDOERS password prompt after paru
|
||||||
no_log: true
|
no_log: true
|
||||||
lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
dest: /etc/sudoers
|
dest: /etc/sudoers
|
||||||
state: present
|
state: present
|
||||||
regexp: "^#?%wheel"
|
regexp: "^#?%wheel"
|
||||||
@ -77,7 +76,7 @@
|
|||||||
validate: /usr/sbin/visudo -cf %s
|
validate: /usr/sbin/visudo -cf %s
|
||||||
|
|
||||||
- name: Enable zfs services
|
- name: Enable zfs services
|
||||||
service:
|
ansible.builtin.service:
|
||||||
name: "{{ item }}"
|
name: "{{ item }}"
|
||||||
enabled: true
|
enabled: true
|
||||||
state: started
|
state: started
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
---
|
---
|
||||||
- name: Install ZFS
|
- name: Install ZFS
|
||||||
include_tasks: install.yml
|
ansible.builtin.include_tasks: install.yml
|
||||||
|
|
||||||
- name: Configure Zpools
|
- name: Configure Zpools
|
||||||
include_tasks: pools.yml
|
ansible.builtin.include_tasks: pools.yml
|
||||||
|
|
||||||
- name: "Setup ZFS datasets: filesystems, snapshots, volumes"
|
- name: "Setup ZFS datasets: filesystems, snapshots, volumes"
|
||||||
include_tasks: datasets.yml
|
ansible.builtin.include_tasks: datasets.yml
|
||||||
|
|||||||
@ -3,21 +3,22 @@
|
|||||||
# Based on: https://github.com/mrlesmithjr/ansible-zfs/blob/master/tasks/manage_zfs.yml
|
# Based on: https://github.com/mrlesmithjr/ansible-zfs/blob/master/tasks/manage_zfs.yml
|
||||||
# Expected variables in your inventory: zfs_pools.
|
# Expected variables in your inventory: zfs_pools.
|
||||||
|
|
||||||
- name: checking existing zpool(s)
|
- name: Checking existing zpool(s)
|
||||||
ansible.builtin.shell: "zpool list -H -o name"
|
ansible.builtin.command: "zpool list -H -o name"
|
||||||
changed_when: false
|
changed_when: false
|
||||||
register: current_zp_state
|
register: current_zp_state
|
||||||
check_mode: no
|
check_mode: false
|
||||||
when: zfs_pools is defined
|
when: zfs_pools is defined
|
||||||
|
|
||||||
- name: gather zpool status
|
- name: Gather zpool status
|
||||||
ansible.builtin.shell: zpool status
|
ansible.builtin.command: zpool status
|
||||||
changed_when: false
|
changed_when: false
|
||||||
register: zpool_devices
|
register: zpool_devices
|
||||||
when: zfs_pools is defined
|
when: zfs_pools is defined
|
||||||
|
|
||||||
- name: creating basic zpool(s)
|
- name: Creating basic zpool(s)
|
||||||
ansible.builtin.command: "zpool create {{ '-o '+ item.options.items() |map('join', '=') | join (' -o ') if item.options is defined else '' }} {{ item.name }} {{ item.devices|join (' ') }}"
|
ansible.builtin.command: "zpool create {{ '-o '+ item.options.items() |map('join', '=') | join (' -o ') if item.options is defined else '' }} {{ item.name }} {{
|
||||||
|
item.devices|join (' ') }}"
|
||||||
with_items: "{{ zfs_pools }}"
|
with_items: "{{ zfs_pools }}"
|
||||||
when:
|
when:
|
||||||
- zfs_pools is defined
|
- zfs_pools is defined
|
||||||
@ -26,8 +27,9 @@
|
|||||||
- item.state == "present"
|
- item.state == "present"
|
||||||
- item.devices[0] not in zpool_devices.stdout
|
- item.devices[0] not in zpool_devices.stdout
|
||||||
|
|
||||||
- name: creating mirror/zraid zpool(s)
|
- name: Creating mirror/zraid zpool(s)
|
||||||
ansible.builtin.command: "zpool create {{ '-o '+ item.options.items() |map('join', '=') | join (' -o ') if item.options is defined else '' }} {{ item.name }} {{ item.type }} {{ item.devices|join (' ') }}"
|
ansible.builtin.command: "zpool create {{ '-o '+ item.options.items() |map('join', '=') | join (' -o ') if item.options is defined else '' }} {{ item.name }} {{
|
||||||
|
item.type }} {{ item.devices|join (' ') }}"
|
||||||
with_items: "{{ zfs_pools }}"
|
with_items: "{{ zfs_pools }}"
|
||||||
when:
|
when:
|
||||||
- zfs_pools is defined
|
- zfs_pools is defined
|
||||||
@ -36,8 +38,8 @@
|
|||||||
- item.state == "present"
|
- item.state == "present"
|
||||||
- item.devices[0] not in zpool_devices.stdout
|
- item.devices[0] not in zpool_devices.stdout
|
||||||
|
|
||||||
- name: deleting zpool(s) with care
|
- name: Deleting zpool(s) with care
|
||||||
include_tasks: "./delete-pool.yml"
|
ansible.builtin.include_tasks: "./delete-pool.yml"
|
||||||
when:
|
when:
|
||||||
- zfs_pools is defined
|
- zfs_pools is defined
|
||||||
- zpool.name in current_zp_state.stdout_lines
|
- zpool.name in current_zp_state.stdout_lines
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
zsh_home: "{{ '/root' if zsh_user == 'root' else '/home/' + zsh_user }}"
|
zsh_home: "{{ '/root' if zsh_user == 'root' else '/home/' + zsh_user }}"
|
||||||
zsh_base_config: "{{ zsh_home }}/.zshrc"
|
zsh_base_config: "{{ zsh_home }}/.zshrc"
|
||||||
zsh_config_path: "{{ zsh_home }}/.config/zsh"
|
zsh_config_path: "{{ zsh_home }}/.config/zsh"
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
---
|
---
|
||||||
- name: install zsh
|
- name: Install zsh
|
||||||
package:
|
ansible.builtin.package:
|
||||||
name: zsh
|
name: zsh
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
- name: install zsh plugins
|
- name: Install zsh plugins
|
||||||
include_tasks: plugins.yml
|
ansible.builtin.include_tasks: plugins.yml
|
||||||
|
- name: Setup zsh for the user(s)
|
||||||
- name: setup zsh for the user(s)
|
ansible.builtin.include_tasks: user-setup.yml
|
||||||
include_tasks: user-setup.yml
|
|
||||||
vars:
|
vars:
|
||||||
zsh_user: "{{ item }}"
|
zsh_user: "{{ item }}"
|
||||||
loop: "{{ zsh_users | default([]) }}"
|
loop: "{{ zsh_users | default([]) }}"
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
- name: ensure plugins directory exists
|
- name: Ensure plugins directory exists
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "{{ zsh_plugins_path }}"
|
path: "{{ zsh_plugins_path }}"
|
||||||
state: directory
|
state: directory
|
||||||
@ -7,7 +7,7 @@
|
|||||||
group: users
|
group: users
|
||||||
mode: "0755"
|
mode: "0755"
|
||||||
|
|
||||||
- name: add a readme file to advice from where this comes
|
- name: Add a readme file to advice from where this comes
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: "{{ zsh_plugins_path }}/README.md"
|
dest: "{{ zsh_plugins_path }}/README.md"
|
||||||
content: |
|
content: |
|
||||||
@ -17,27 +17,18 @@
|
|||||||
group: users
|
group: users
|
||||||
owner: root
|
owner: root
|
||||||
|
|
||||||
- name: "git clone plugins"
|
- name: "Git clone plugins"
|
||||||
git:
|
ansible.builtin.git:
|
||||||
repo: "{{ item.repo }}"
|
repo: "{{ item.repo }}"
|
||||||
dest: "{{ item.dest }}"
|
dest: "{{ item.dest }}"
|
||||||
update: yes
|
update: true
|
||||||
version: master
|
version: master
|
||||||
loop:
|
loop:
|
||||||
- {
|
- { repo: https://github.com/zsh-users/zsh-syntax-highlighting.git, dest: "{{ zsh_plugins_path }}/zsh-syntax-highlighting" }
|
||||||
repo: https://github.com/zsh-users/zsh-syntax-highlighting.git,
|
- { repo: https://github.com/zsh-users/zsh-autosuggestions.git, dest: "{{ zsh_plugins_path }}/zsh-autosuggestions" }
|
||||||
dest: "{{ zsh_plugins_path }}/zsh-syntax-highlighting",
|
- { repo: https://github.com/romkatv/powerlevel10k.git, dest: "{{ zsh_plugins_path }}/powerlevel10k" }
|
||||||
}
|
|
||||||
- {
|
|
||||||
repo: https://github.com/zsh-users/zsh-autosuggestions.git,
|
|
||||||
dest: "{{ zsh_plugins_path }}/zsh-autosuggestions",
|
|
||||||
}
|
|
||||||
- {
|
|
||||||
repo: https://github.com/romkatv/powerlevel10k.git,
|
|
||||||
dest: "{{ zsh_plugins_path }}/powerlevel10k",
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: assert plugins are available for any user
|
- name: Assert plugins are available for any user
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "{{ item }}"
|
path: "{{ item }}"
|
||||||
owner: root
|
owner: root
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
- name: setup zsh base config
|
---
|
||||||
|
- name: Setup zsh base config
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: main.zshrc.j2
|
src: main.zshrc.j2
|
||||||
dest: "{{ zsh_base_config }}"
|
dest: "{{ zsh_base_config }}"
|
||||||
@ -6,7 +7,7 @@
|
|||||||
group: "{{ zsh_user }}"
|
group: "{{ zsh_user }}"
|
||||||
mode: "0600"
|
mode: "0600"
|
||||||
|
|
||||||
- name: setup .config/zsh directory
|
- name: Setup .config/zsh directory
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "{{ zsh_config_path }}"
|
path: "{{ zsh_config_path }}"
|
||||||
state: directory
|
state: directory
|
||||||
@ -14,7 +15,7 @@
|
|||||||
group: "{{ zsh_user }}"
|
group: "{{ zsh_user }}"
|
||||||
mode: "0700"
|
mode: "0700"
|
||||||
|
|
||||||
- name: configure zsh config
|
- name: Configure zsh config
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: zshrc.j2
|
src: zshrc.j2
|
||||||
dest: "{{ zsh_config_file }}"
|
dest: "{{ zsh_config_file }}"
|
||||||
@ -22,7 +23,7 @@
|
|||||||
group: "{{ zsh_user }}"
|
group: "{{ zsh_user }}"
|
||||||
mode: "0600"
|
mode: "0600"
|
||||||
|
|
||||||
- name: copy aliases
|
- name: Copy aliases
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
src: ./templates/aliases
|
src: ./templates/aliases
|
||||||
dest: "{{ zsh_config_path }}/aliases"
|
dest: "{{ zsh_config_path }}/aliases"
|
||||||
@ -30,12 +31,12 @@
|
|||||||
group: "{{ zsh_user }}"
|
group: "{{ zsh_user }}"
|
||||||
mode: "0600"
|
mode: "0600"
|
||||||
|
|
||||||
- name: change default shell to zsh
|
- name: Change default shell to zsh
|
||||||
user:
|
ansible.builtin.user:
|
||||||
name: "{{ zsh_user }}"
|
name: "{{ zsh_user }}"
|
||||||
shell: /bin/zsh
|
shell: /bin/zsh
|
||||||
|
|
||||||
- name: configure powerlevel10k theme
|
- name: Configure powerlevel10k theme
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
src: "./templates/{{ 'root.p10k.zsh' if zsh_user == 'root' else 'user.p10k.zsh' }}"
|
src: "./templates/{{ 'root.p10k.zsh' if zsh_user == 'root' else 'user.p10k.zsh' }}"
|
||||||
dest: "{{ zsh_p10k_theme_config }}"
|
dest: "{{ zsh_p10k_theme_config }}"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user