1.0.0 Release IaaS
This commit is contained in:
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
data/bin/*
|
||||||
|
data/volumes/*
|
||||||
|
data/images/*
|
||||||
|
docs/archives/textfiles/
|
||||||
|
docs/notes/*
|
||||||
|
*.sql
|
||||||
|
!.gitkeep
|
||||||
26
README.md
Normal file
26
README.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# ilnmors homelab README
|
||||||
|
|
||||||
|
This homelab project implements single-node On-premise IaaS system. The homelab contains virtual machines which are divided by their roles, such as private firewall, DNS, PKI, LDAP and database, SSO\(OIDC\). The standard domain is used to implement this system without specific vendors. All components are defined as code and initiated by IaC \(Ansible\) except hypervisor initial configuration.
|
||||||
|
|
||||||
|
## RTO times
|
||||||
|
- Feb/25/2026 - Reprovisioning Hypervisor and vms
|
||||||
|
- RTO: 1 hour 30 min - verified
|
||||||
|
- Manual install and set vmm: 20 min
|
||||||
|
- Create and reprovision fw including services: 15 min
|
||||||
|
- Create and reprovision infra including services: 20 min
|
||||||
|
- Create and reprovision auth including services: 10 min
|
||||||
|
- Create and reprovision app except services: 10 min
|
||||||
|
- Intermediate tasks (ACME issuance, DNS propagation, etc.): 15 min
|
||||||
|
|
||||||
|
- Mar/5/2026 - Reprovisioning Hardware and Hypervisor and vms
|
||||||
|
- RTO: 2 hour 20 min
|
||||||
|
- console: 15min - verified
|
||||||
|
- certificate: 0 min \(When it needs to be created, RTO will be 20 min) - not verified
|
||||||
|
- wireguard: 0 min \(When it needs to be created, RTO will be 1 min) - not verified
|
||||||
|
- hypervisor\(+fw\): 45 min - verified
|
||||||
|
- switch: 1 min - verified
|
||||||
|
- dsm: 30 min - verified
|
||||||
|
- kopia: 0 min \(When it needs to be created, RTO will be 10 min) - verified
|
||||||
|
- Extra vms: 30 min - verified
|
||||||
|
- Etc: 30 min
|
||||||
|
|
||||||
57
ansible/ansible.cfg
Normal file
57
ansible/ansible.cfg
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
[defaults]
|
||||||
|
|
||||||
|
# (boolean) This controls whether an Ansible playbook should prompt for a login password. If using SSH keys for authentication, you probably do not need to change this setting.
|
||||||
|
ask_pass=False
|
||||||
|
|
||||||
|
# (boolean) This controls whether an Ansible playbook should prompt for a vault password.
|
||||||
|
ask_vault_pass=True
|
||||||
|
|
||||||
|
# (pathlist) Comma-separated list of Ansible inventory sources
|
||||||
|
inventory=./inventory
|
||||||
|
|
||||||
|
# (pathspec) Colon-separated paths in which Ansible will search for Roles.
|
||||||
|
roles_path=./roles
|
||||||
|
|
||||||
|
# (string) Set the main callback used to display Ansible output. You can only have one at a time.
|
||||||
|
# You can have many other callbacks, but just one can be in charge of stdout.
|
||||||
|
# See :ref:`callback_plugins` for a list of available options.
|
||||||
|
stdout_callback=default
|
||||||
|
|
||||||
|
# (boolean) Set this to "False" if you want to avoid host key checking by the underlying connection plugin Ansible uses to connect to the host.
|
||||||
|
# Please read the documentation of the specific connection plugin used for details.
|
||||||
|
host_key_checking=True
|
||||||
|
|
||||||
|
# (string) Path to the Python interpreter to be used for module execution on remote targets, or an automatic discovery mode. Supported discovery modes are ``auto`` (the default), ``auto_silent``, ``auto_legacy``, and ``auto_legacy_silent``. All discovery modes match against an ordered list of well-known Python interpreter locations. The fallback behavior will issue a warning that the interpreter should be set explicitly (since interpreters installed later may change which one is used). This warning behavior can be disabled by setting ``auto_silent``. The ``auto_legacy`` modes are deprecated and behave the same as their respective ``auto`` modes. They exist for backward-compatibility with older Ansible releases that always defaulted to ``/usr/bin/python3``, which will use that interpreter if present.
|
||||||
|
interpreter_python=auto_silent
|
||||||
|
|
||||||
|
# (path) A number of non-playbook CLIs have a ``--playbook-dir`` argument; this sets the default value for it.
|
||||||
|
playbook_dir=./playbooks
|
||||||
|
|
||||||
|
# (bool) This controls whether a failed Ansible playbook should create a .retry file.
|
||||||
|
retry_files_enabled=False
|
||||||
|
|
||||||
|
# (boolean) This option controls if notified handlers run on a host even if a failure occurs on that host.
|
||||||
|
# When false, the handlers will not run if a failure has occurred on a host.
|
||||||
|
# This can also be set per play or on the command line. See Handlers and Failure for more details.
|
||||||
|
force_handlers=True
|
||||||
|
|
||||||
|
[privilege_escalation]
|
||||||
|
# (boolean) Toggles the use of privilege escalation, allowing you to 'become' another user after login.
|
||||||
|
become=True
|
||||||
|
|
||||||
|
# (boolean) Toggle to prompt for privilege escalation password.
|
||||||
|
become_ask_pass=False
|
||||||
|
|
||||||
|
# (string) Privilege escalation method to use when `become` is enabled.;
|
||||||
|
become_method=sudo
|
||||||
|
|
||||||
|
# (string) The user your login/remote user 'becomes' when using privilege escalation, most systems will use 'root' when no user is specified.;
|
||||||
|
become_user=root
|
||||||
|
|
||||||
|
[connection]
|
||||||
|
# (boolean) This is a global option, each connection plugin can override either by having more specific options or not supporting pipelining at all.
|
||||||
|
# Pipelining, if supported by the connection plugin, reduces the number of network operations required to execute a module on the remote server, by executing many Ansible modules without actual file transfer.
|
||||||
|
# It can result in a very significant performance improvement when enabled.
|
||||||
|
# However this conflicts with privilege escalation (become). For example, when using 'sudo:' operations you must first disable 'requiretty' in /etc/sudoers on all managed hosts, which is why it is disabled by default.
|
||||||
|
# This setting will be disabled if ``ANSIBLE_KEEP_REMOTE_FILES`` is enabled.
|
||||||
|
pipelining=True
|
||||||
39
ansible/convention.yaml
Normal file
39
ansible/convention.yaml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
# `""` should be used for every string values
|
||||||
|
# except name, boolean, varible(environment) name, number (only for decimal)
|
||||||
|
- name: Convention task
|
||||||
|
delegate_to: "host"
|
||||||
|
delegate_facts: true
|
||||||
|
environment:
|
||||||
|
env: "environment"
|
||||||
|
ansible.builtin.file:
|
||||||
|
# Identifier: name:, src, dest, url
|
||||||
|
path: "/path/of/example"
|
||||||
|
# State
|
||||||
|
state: "directory"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0640"
|
||||||
|
# optional data
|
||||||
|
recurse: true
|
||||||
|
loop:
|
||||||
|
- "list"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item }}"
|
||||||
|
become: true
|
||||||
|
# become_user: "root"
|
||||||
|
when: condition.stat.exists
|
||||||
|
changed_when: condition.rc != 0
|
||||||
|
failed_when: condition.rc == 0
|
||||||
|
register: "convention_task"
|
||||||
|
notify: "notification_example"
|
||||||
|
listen: "notification_example"
|
||||||
|
no_log: true
|
||||||
|
run_once: true
|
||||||
|
tags:
|
||||||
|
- "always"
|
||||||
|
- "init"
|
||||||
|
- "upgrade"
|
||||||
|
- "update"
|
||||||
|
|
||||||
|
# when: "'tags' is not in ansible_run_tags"
|
||||||
74
ansible/inventory/group_vars/all.yaml
Normal file
74
ansible/inventory/group_vars/all.yaml
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
---
|
||||||
|
# Global vars
|
||||||
|
ansible_ssh_private_key_file: "/etc/secrets/{{ hostvars['console']['node']['uid'] }}/id_console"
|
||||||
|
|
||||||
|
# URL infromation, you can use {{ infra_uri['services'] | split(':') | first|last }} to seperate domain and ports
|
||||||
|
infra_uri:
|
||||||
|
crowdsec:
|
||||||
|
domain: "crowdsec.ilnmors.internal"
|
||||||
|
ports:
|
||||||
|
https: "8080"
|
||||||
|
bind:
|
||||||
|
domain: "bind.ilnmors.internal"
|
||||||
|
ports:
|
||||||
|
dns: "53"
|
||||||
|
blocky:
|
||||||
|
domain: "blocky.ilnmors.internal"
|
||||||
|
ports:
|
||||||
|
https: "443"
|
||||||
|
dns: "53"
|
||||||
|
postgresql:
|
||||||
|
domain: "postgresql.ilnmors.internal"
|
||||||
|
ports:
|
||||||
|
tcp: "5432" # postgresql db connection port
|
||||||
|
ldap:
|
||||||
|
domain: "ldap.ilnmors.internal"
|
||||||
|
ports:
|
||||||
|
http: "17170"
|
||||||
|
ldaps: "636"
|
||||||
|
ca:
|
||||||
|
domain: "ca.ilnmors.internal"
|
||||||
|
ports:
|
||||||
|
https: "9000"
|
||||||
|
prometheus:
|
||||||
|
domain: "prometheus.ilnmors.internal"
|
||||||
|
ports:
|
||||||
|
https: "9090"
|
||||||
|
loki:
|
||||||
|
domain: "loki.ilnmors.internal"
|
||||||
|
ports:
|
||||||
|
https: "3100"
|
||||||
|
nas:
|
||||||
|
domain: "nas.ilnmors.internal"
|
||||||
|
ports:
|
||||||
|
https: "5001"
|
||||||
|
kopia:
|
||||||
|
domain: "nas.ilnmors.internal"
|
||||||
|
ports:
|
||||||
|
https: "51515"
|
||||||
|
|
||||||
|
version:
|
||||||
|
packages:
|
||||||
|
sops: "3.12.1"
|
||||||
|
step: "0.29.0"
|
||||||
|
kopia: "0.22.3"
|
||||||
|
blocky: "0.28.2"
|
||||||
|
alloy: "1.13.0"
|
||||||
|
# telegraf: "1.37.1"
|
||||||
|
containers:
|
||||||
|
# common
|
||||||
|
caddy: "2.10.2"
|
||||||
|
# infra
|
||||||
|
step: "0.29.0"
|
||||||
|
ldap: "v0.6.2"
|
||||||
|
x509-exporter: "3.19.1"
|
||||||
|
prometheus: "v3.9.1"
|
||||||
|
loki: "3.6.5"
|
||||||
|
grafana: "12.3.3"
|
||||||
|
## Postgresql
|
||||||
|
postgresql: "18.2"
|
||||||
|
# For immich - https://github.com/immich-app/base-images/blob/main/postgres/versions.yaml
|
||||||
|
# pgvector: "v0.8.1"
|
||||||
|
vectorchord: "0.5.3"
|
||||||
|
# Auth
|
||||||
|
authelia: "4.39.15"
|
||||||
7
ansible/inventory/group_vars/hypervisor.yaml
Normal file
7
ansible/inventory/group_vars/hypervisor.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
node:
|
||||||
|
name: "vmm"
|
||||||
|
uid: 2000
|
||||||
|
home_path: "/home/vmm"
|
||||||
|
ssh_san: "vmm,vmm_init,vmm.ilnmors.internal,init.vmm.ilnmors.internal"
|
||||||
|
local_san: "localhost vmm.ilnmors.internal"
|
||||||
41
ansible/inventory/host_vars/app.yaml
Normal file
41
ansible/inventory/host_vars/app.yaml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
# Node Factors
|
||||||
|
node:
|
||||||
|
name: "app"
|
||||||
|
uid: 2004
|
||||||
|
home_path: "/home/app"
|
||||||
|
ssh_san: "app,app.ilnmors.internal"
|
||||||
|
local_san: "localhost app.ilnmors.internal"
|
||||||
|
# VM Factors
|
||||||
|
vm:
|
||||||
|
name: "app"
|
||||||
|
cpu: 4
|
||||||
|
shares: 1024
|
||||||
|
memory: 16
|
||||||
|
storage: 256
|
||||||
|
lan_mac: "0a:49:6e:4d:03:00"
|
||||||
|
lan_net: "lan-net"
|
||||||
|
lan_group: "vlan10-access"
|
||||||
|
# PCIe passthrough address
|
||||||
|
# result of `lspci | grep -i -e "sata controller" -e "vga"` and parse it.
|
||||||
|
# Ex) 04:00.0 > domain: "0x0000", bus: "0x04", slot: "0x00", function: "0x0"
|
||||||
|
pass_through:
|
||||||
|
igpu:
|
||||||
|
address: "0000:00:02.0"
|
||||||
|
domain: "0x0000"
|
||||||
|
bus: "0x00"
|
||||||
|
slot: "0x02"
|
||||||
|
function: "0x0"
|
||||||
|
sata_controller: # Additional SATA Controller
|
||||||
|
address: "0000:04:00.0"
|
||||||
|
domain: "0x0000"
|
||||||
|
bus: "0x04"
|
||||||
|
slot: "0x00"
|
||||||
|
function: "0x0"
|
||||||
|
|
||||||
|
# BTRFS configuration for hdd which is passthroughed
|
||||||
|
storage:
|
||||||
|
btrfs:
|
||||||
|
label: "APP_DATA"
|
||||||
|
level: "raid10"
|
||||||
|
mount_point: "/home/app/data"
|
||||||
18
ansible/inventory/host_vars/auth.yaml
Normal file
18
ansible/inventory/host_vars/auth.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
# Node Factors
|
||||||
|
node:
|
||||||
|
name: "auth"
|
||||||
|
uid: 2003
|
||||||
|
home_path: "/home/auth"
|
||||||
|
ssh_san: "auth,auth.ilnmors.internal"
|
||||||
|
local_san: "localhost auth.ilnmors.internal"
|
||||||
|
# VM Factors
|
||||||
|
vm:
|
||||||
|
name: "auth"
|
||||||
|
cpu: 2
|
||||||
|
shares: 512
|
||||||
|
memory: 2
|
||||||
|
storage: 64
|
||||||
|
lan_mac: "0a:49:6e:4d:02:00"
|
||||||
|
lan_net: "lan-net"
|
||||||
|
lan_group: "vlan10-access"
|
||||||
25
ansible/inventory/host_vars/console.yaml
Normal file
25
ansible/inventory/host_vars/console.yaml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
# Secret management
|
||||||
|
age_key: !vault |
|
||||||
|
$ANSIBLE_VAULT;1.1;AES256
|
||||||
|
32343637656262323931313061323861393737663736626538396165613563323531316639346637
|
||||||
|
3766363134663963396634353764323166353936626633300a356338363036373165363335333665
|
||||||
|
38316638386661623265306538303739616638316565373864316364623539383736343366646463
|
||||||
|
3464613666663836310a666531386136326439616637393035333534303661373433343830323665
|
||||||
|
66613736613133616439393163653166306261376231646163323266616431623531313964326132
|
||||||
|
33653638373537323363316363646534323362353836373665636265663939353862663532313230
|
||||||
|
30643038313138626464626161373835646665326334393834616234643931656536343130316238
|
||||||
|
61656264643830616639
|
||||||
|
# Node Factors
|
||||||
|
node:
|
||||||
|
name: "console"
|
||||||
|
uid: 2999
|
||||||
|
home_path: "/home/console"
|
||||||
|
workspace_path: "{{ node.home_path }}/workspace"
|
||||||
|
homelab_path: "{{ node.home_path }}/workspace/homelab"
|
||||||
|
data_path: "{{ node.homelab_path }}/data"
|
||||||
|
config_path: "{{ node.homelab_path }}/config"
|
||||||
|
ssh_san: "console,console.ilnmors.internal"
|
||||||
|
ssh_users: "vmm,fw,infra,auth,app"
|
||||||
|
local_san: "localhost console.ilnmors.internal"
|
||||||
|
# ansible_python_interpreter: "{{ ansible_playbook_python }}"
|
||||||
98
ansible/inventory/host_vars/fw.yaml
Normal file
98
ansible/inventory/host_vars/fw.yaml
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
---
|
||||||
|
# Node Factors
|
||||||
|
node:
|
||||||
|
name: "fw"
|
||||||
|
uid: 2001
|
||||||
|
home_path: "/home/fw"
|
||||||
|
ssh_san: "fw,fw.ilnmors.internal"
|
||||||
|
local_san: "localhost fw.ilnmors.internal"
|
||||||
|
|
||||||
|
# VM Factors
|
||||||
|
vm:
|
||||||
|
name: "fw"
|
||||||
|
cpu: 2
|
||||||
|
shares: 2048
|
||||||
|
memory: 4
|
||||||
|
storage: 64
|
||||||
|
wan_mac: "0a:49:6e:4d:00:00"
|
||||||
|
lan_mac: "0a:49:6e:4d:00:01"
|
||||||
|
wan_net: "wan-net"
|
||||||
|
lan_net: "lan-net"
|
||||||
|
lan_group: "vlan-trunk"
|
||||||
|
|
||||||
|
# Network Factors
|
||||||
|
# LLA is like MAC address for L3 (Network layer). Usually, subnet is used to seperate network.
|
||||||
|
network4:
|
||||||
|
subnet:
|
||||||
|
client: "192.168.1.0/24"
|
||||||
|
server: "192.168.10.0/24"
|
||||||
|
user: "192.168.20.0/24"
|
||||||
|
wg: "192.168.99.0/24"
|
||||||
|
lla: "169.254.0.0/16"
|
||||||
|
# You can use "{{ hostvars['fw']['network4']['firewall'].values() | join(', ') }}" for all
|
||||||
|
firewall:
|
||||||
|
client: "192.168.1.1"
|
||||||
|
server: "192.168.10.1"
|
||||||
|
user: "192.168.20.1"
|
||||||
|
wg: "192.168.99.1"
|
||||||
|
blocky:
|
||||||
|
server: "192.168.10.2"
|
||||||
|
bind:
|
||||||
|
server: "192.168.10.3"
|
||||||
|
console:
|
||||||
|
client: "192.168.1.20"
|
||||||
|
wg: "192.168.99.20"
|
||||||
|
vmm:
|
||||||
|
client: "192.168.1.10"
|
||||||
|
server: "192.168.10.10"
|
||||||
|
infra:
|
||||||
|
server: "192.168.10.11"
|
||||||
|
auth:
|
||||||
|
server: "192.168.10.12"
|
||||||
|
app:
|
||||||
|
server: "192.168.10.13"
|
||||||
|
switch:
|
||||||
|
client: "192.168.1.2"
|
||||||
|
nas:
|
||||||
|
client: "192.168.1.11"
|
||||||
|
printer:
|
||||||
|
client: "192.168.1.101"
|
||||||
|
|
||||||
|
network6:
|
||||||
|
subnet:
|
||||||
|
client: "fd00:1::/64"
|
||||||
|
server: "fd00:10::/64"
|
||||||
|
wg: "fd00:99::/64"
|
||||||
|
lla: "fe80::/10"
|
||||||
|
firewall:
|
||||||
|
client: "fd00:1::1"
|
||||||
|
server: "fd00:10::1"
|
||||||
|
wg: "fd00:99::1"
|
||||||
|
blocky:
|
||||||
|
server: "fd00:10::2"
|
||||||
|
bind:
|
||||||
|
server: "fd00:10::3"
|
||||||
|
console:
|
||||||
|
client: "fd00:1::20"
|
||||||
|
wg: "fd00:99::20"
|
||||||
|
vmm:
|
||||||
|
client: "fd00:1::10"
|
||||||
|
server: "fd00:10::10"
|
||||||
|
infra:
|
||||||
|
server: "fd00:10::11"
|
||||||
|
auth:
|
||||||
|
server: "fd00:10::12"
|
||||||
|
app:
|
||||||
|
server: "fd00:10::13"
|
||||||
|
switch:
|
||||||
|
client: "fd00:1::2"
|
||||||
|
nas:
|
||||||
|
client: "fd00:1::11"
|
||||||
|
printer:
|
||||||
|
client: "fd00:1::101"
|
||||||
|
|
||||||
|
# Suricata Factors
|
||||||
|
# suricata_home_net: '[10.0.0.0/8,172.16.0.0/12,192.168.0.0/16]'
|
||||||
|
suricata:
|
||||||
|
home_net: '[10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fd00::/8,fe80::/8]'
|
||||||
|
interfaces: ["wan", "client", "server", "user"]
|
||||||
19
ansible/inventory/host_vars/infra.yaml
Normal file
19
ansible/inventory/host_vars/infra.yaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
# Node Factors
|
||||||
|
node:
|
||||||
|
name: "infra"
|
||||||
|
uid: 2002
|
||||||
|
home_path: "/home/infra"
|
||||||
|
ssh_san: "infra,infra.ilnmors.internal"
|
||||||
|
local_san: "localhost infra.ilnmors.internal"
|
||||||
|
|
||||||
|
# VM Factors
|
||||||
|
vm:
|
||||||
|
name: "infra"
|
||||||
|
cpu: 2
|
||||||
|
shares: 1024
|
||||||
|
memory: 6
|
||||||
|
storage: 256
|
||||||
|
lan_mac: "0a:49:6e:4d:01:00"
|
||||||
|
lan_net: "lan-net"
|
||||||
|
lan_group: "vlan10-access"
|
||||||
14
ansible/inventory/hosts.ini
Normal file
14
ansible/inventory/hosts.ini
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# --- console ---
|
||||||
|
console ansible_connection=local ansible_user=console
|
||||||
|
|
||||||
|
# --- Hypervisor ---
|
||||||
|
[hypervisor]
|
||||||
|
vmm_init ansible_host=init.vmm.ilnmors.internal ansible_user=vmm
|
||||||
|
vmm ansible_host=vmm.ilnmors.internal ansible_user=vmm
|
||||||
|
|
||||||
|
# --- Virtual Machines ---
|
||||||
|
[vms]
|
||||||
|
fw ansible_host=fw.ilnmors.internal ansible_user=fw
|
||||||
|
infra ansible_host=infra.ilnmors.internal ansible_user=infra
|
||||||
|
auth ansible_host=auth.ilnmors.internal ansible_user=auth
|
||||||
|
app ansible_host=app.ilnmors.internal ansible_user=app
|
||||||
185
ansible/playbooks/app/site.yaml
Normal file
185
ansible/playbooks/app/site.yaml
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
---
|
||||||
|
- name: Load secret values
|
||||||
|
hosts: "console"
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
tasks:
|
||||||
|
- name: Load secret from secrets.yaml
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "console"
|
||||||
|
tasks_from: "node/load_secret_vars"
|
||||||
|
apply:
|
||||||
|
tags: ["always"]
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
- name: Site app
|
||||||
|
hosts: "app"
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
pre_tasks:
|
||||||
|
- name: Set become password
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['app'] }}"
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Set timezone to Asia/Seoul
|
||||||
|
community.general.timezone:
|
||||||
|
name: Asia/Seoul
|
||||||
|
become: true
|
||||||
|
tags: ["init", "timezone"]
|
||||||
|
|
||||||
|
- name: Deploy root_ca certificate
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/deploy_root_ca"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "root_crt"]
|
||||||
|
tags: ["init", "root_crt"]
|
||||||
|
|
||||||
|
- name: Deploy hosts file
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/deploy_hosts"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "hosts"]
|
||||||
|
tags: ["init", "hosts"]
|
||||||
|
|
||||||
|
- name: Create default directory
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/create_default_dir"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "default_dir"]
|
||||||
|
tags: ["init", "default_dir"]
|
||||||
|
|
||||||
|
- name: Set ssh host
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_ssh_host"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "ssh_host"]
|
||||||
|
tags: ["init", "ssh_host"]
|
||||||
|
|
||||||
|
- name: Set networkd
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_networkd"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "networkd"]
|
||||||
|
tags: ["init", "networkd"]
|
||||||
|
|
||||||
|
- name: Set resolved
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_resolved"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "resolved"]
|
||||||
|
tags: ["init", "resolved"]
|
||||||
|
|
||||||
|
- name: Update and upgrade apt
|
||||||
|
ansible.builtin.apt:
|
||||||
|
upgrade: "dist"
|
||||||
|
update_cache: true
|
||||||
|
cache_valid_time: 3600
|
||||||
|
become: true
|
||||||
|
tags: ["init", "site", "upgrade-packages"]
|
||||||
|
|
||||||
|
- name: Install common packages
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- "acl"
|
||||||
|
- "curl"
|
||||||
|
- "jq"
|
||||||
|
- "netcat-openbsd"
|
||||||
|
- "dbus-user-session"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
tags: ["init", "install-packages"]
|
||||||
|
|
||||||
|
- name: Set raid
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "app"
|
||||||
|
tasks_from: "node/set_raid"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "raid"]
|
||||||
|
tags: ["init", "raid"]
|
||||||
|
|
||||||
|
- name: Set linger
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_linger"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "linger"]
|
||||||
|
tags: ["init", "linger"]
|
||||||
|
|
||||||
|
- name: Set podman
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_podman"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "podman"]
|
||||||
|
tags: ["init", "podman"]
|
||||||
|
|
||||||
|
- name: Set nftables
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_nftables"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "nftables"]
|
||||||
|
tags: ["init", "nftables"]
|
||||||
|
|
||||||
|
- name: Set crowdsec
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_crowdsec"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "crowdsec"]
|
||||||
|
tags: ["site", "crowdsec"]
|
||||||
|
|
||||||
|
- name: Set alloy
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_alloy"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "update", "alloy"]
|
||||||
|
tags: ["init", "update", "alloy"]
|
||||||
|
|
||||||
|
- name: Set kopia
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_kopia"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "kopia"]
|
||||||
|
tags: ["site", "kopia"]
|
||||||
|
|
||||||
|
- name: Flush handlers right now
|
||||||
|
ansible.builtin.meta: "flush_handlers"
|
||||||
|
|
||||||
|
# Only update iGPU firmware
|
||||||
|
- name: Install iGPU Firmware
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- "firmware-intel-graphics"
|
||||||
|
- "intel-media-va-driver-non-free"
|
||||||
|
update_cache: true
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
notify:
|
||||||
|
- "notification_update_initramfs"
|
||||||
|
- "notification_reboot_app"
|
||||||
|
tags: ["init"]
|
||||||
|
handlers:
|
||||||
|
- name: Update initramfs
|
||||||
|
ansible.builtin.command:
|
||||||
|
update-initramfs -u
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_update_initramfs"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
- name: Reboot app vm
|
||||||
|
ansible.builtin.reboot:
|
||||||
|
reboot_timeout: 300
|
||||||
|
become: true
|
||||||
|
listen: "notification_reboot_app"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
154
ansible/playbooks/auth/site.yaml
Normal file
154
ansible/playbooks/auth/site.yaml
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
---
|
||||||
|
- name: Load secret values
|
||||||
|
hosts: "console"
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
tasks:
|
||||||
|
- name: Load secret from secrets.yaml
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "console"
|
||||||
|
tasks_from: "node/load_secret_vars"
|
||||||
|
apply:
|
||||||
|
tags: ["always"]
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
- name: Site auth
|
||||||
|
hosts: "auth"
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
pre_tasks:
|
||||||
|
- name: Set become password
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['auth'] }}"
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Set timezone to Asia/Seoul
|
||||||
|
community.general.timezone:
|
||||||
|
name: Asia/Seoul
|
||||||
|
become: true
|
||||||
|
tags: ["init", "timezone"]
|
||||||
|
|
||||||
|
- name: Deploy root_ca certificate
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/deploy_root_ca"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "root_crt"]
|
||||||
|
tags: ["init", "root_crt"]
|
||||||
|
|
||||||
|
- name: Deploy hosts file
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/deploy_hosts"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "hosts"]
|
||||||
|
tags: ["init", "hosts"]
|
||||||
|
|
||||||
|
- name: Create default directory
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/create_default_dir"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "default_dir"]
|
||||||
|
tags: ["init", "default_dir"]
|
||||||
|
|
||||||
|
- name: Set ssh host
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_ssh_host"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "ssh_host"]
|
||||||
|
tags: ["init", "ssh_host"]
|
||||||
|
|
||||||
|
- name: Set networkd
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_networkd"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "networkd"]
|
||||||
|
tags: ["init", "networkd"]
|
||||||
|
|
||||||
|
- name: Set resolved
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_resolved"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "resolved"]
|
||||||
|
tags: ["init", "resolved"]
|
||||||
|
|
||||||
|
- name: Update and upgrade apt
|
||||||
|
ansible.builtin.apt:
|
||||||
|
upgrade: "dist"
|
||||||
|
update_cache: true
|
||||||
|
cache_valid_time: 3600
|
||||||
|
become: true
|
||||||
|
tags: ["init", "site", "upgrade-packages"]
|
||||||
|
|
||||||
|
- name: Install common packages
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- "acl"
|
||||||
|
- "curl"
|
||||||
|
- "jq"
|
||||||
|
- "netcat-openbsd"
|
||||||
|
- "dbus-user-session"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
tags: ["init", "site", "install-packages"]
|
||||||
|
|
||||||
|
- name: Set linger
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_linger"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "linger"]
|
||||||
|
tags: ["init", "linger"]
|
||||||
|
|
||||||
|
- name: Set podman
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_podman"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "podman"]
|
||||||
|
tags: ["init", "podman"]
|
||||||
|
|
||||||
|
- name: Set nftables
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_nftables"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "nftables"]
|
||||||
|
tags: ["init", "nftables"]
|
||||||
|
|
||||||
|
- name: Set crowdsec
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_crowdsec"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "crowdsec"]
|
||||||
|
tags: ["site", "crowdsec"]
|
||||||
|
|
||||||
|
- name: Set caddy
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_caddy"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "caddy"]
|
||||||
|
tags: ["site", "caddy"]
|
||||||
|
|
||||||
|
- name: Set authelia
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "auth"
|
||||||
|
tasks_from: "services/set_authelia"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "authelia"]
|
||||||
|
tags: ["site", "authelia"]
|
||||||
|
|
||||||
|
- name: Set alloy
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_alloy"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "alloy"]
|
||||||
|
tags: ["site", "alloy"]
|
||||||
132
ansible/playbooks/console/site.yaml
Normal file
132
ansible/playbooks/console/site.yaml
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
---
|
||||||
|
- name: Load secret values
|
||||||
|
hosts: "console"
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
tasks:
|
||||||
|
- name: Load secret from secrets.yaml
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "console"
|
||||||
|
tasks_from: "node/load_secret_vars"
|
||||||
|
apply:
|
||||||
|
tags: ["always"]
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
- name: Site console
|
||||||
|
hosts: "console"
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
pre_tasks:
|
||||||
|
- name: Set become password
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['console'] }}"
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
# init
|
||||||
|
- name: Set timezone to Asia/Seoul
|
||||||
|
community.general.timezone:
|
||||||
|
name: Asia/Seoul
|
||||||
|
become: true
|
||||||
|
tags: ["init", "timezone"]
|
||||||
|
|
||||||
|
- name: Deploy root_ca certificate
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/deploy_root_ca"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "root_crt"]
|
||||||
|
tags: ["init", "root_crt"]
|
||||||
|
|
||||||
|
- name: Deploy hosts file
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/deploy_hosts"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "hosts"]
|
||||||
|
tags: ["init", "hosts"]
|
||||||
|
|
||||||
|
- name: Create default directory
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/create_default_dir"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "default_dir"]
|
||||||
|
tags: ["init", "default_dir"]
|
||||||
|
|
||||||
|
- name: Update and upgrade apt
|
||||||
|
ansible.builtin.apt:
|
||||||
|
upgrade: "dist"
|
||||||
|
update_cache: true
|
||||||
|
cache_valid_time: 3600
|
||||||
|
become: true
|
||||||
|
tags: ["init", "site", "upgrade-packages"]
|
||||||
|
|
||||||
|
- name: Set ssh client
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "console"
|
||||||
|
tasks_from: "node/set_ssh_client"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "ssh_client"]
|
||||||
|
tags: ["init", "ssh_client"]
|
||||||
|
|
||||||
|
- name: Check file permissions
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['workspace_path'] }}/{{ item }}"
|
||||||
|
state: "directory"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "u=rwX,g=,o="
|
||||||
|
recurse: true
|
||||||
|
loop:
|
||||||
|
- "homelab/ansible"
|
||||||
|
- "homelab/config"
|
||||||
|
- "homelab/docs"
|
||||||
|
- "university"
|
||||||
|
tags: ["init", "site", "file_permission"]
|
||||||
|
# kopia snashot is mounted on homelab/data/volumes.
|
||||||
|
# NEVER CHANGE permission and owners
|
||||||
|
|
||||||
|
- name: Download vm cloud-init
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: "https://cdimage.debian.org/images/cloud/trixie/latest/debian-13-generic-amd64.qcow2"
|
||||||
|
dest: "{{ node['data_path'] }}/images/debian-13-generic-amd64.qcow2"
|
||||||
|
owner: "console"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
tags: ["init", "site", "cloud-init-image"]
|
||||||
|
|
||||||
|
- name: Install packages
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- "git"
|
||||||
|
- "gnupg"
|
||||||
|
- "acl"
|
||||||
|
- "curl"
|
||||||
|
- "jq"
|
||||||
|
- "cloud-image-utils"
|
||||||
|
- "logrotate"
|
||||||
|
- "nftables"
|
||||||
|
- "build-essential"
|
||||||
|
- "g++"
|
||||||
|
- "gcc"
|
||||||
|
- "fuse3"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
tags: ["init", "site", "install-packages"]
|
||||||
|
|
||||||
|
- name: Install CLI tools
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "console"
|
||||||
|
tasks_from: "services/set_cli_tools"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "site", "tools"]
|
||||||
|
tags: ["init", "site", "tools"]
|
||||||
|
|
||||||
|
- name: Install chromium with font
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "console"
|
||||||
|
tasks_from: "services/set_chromium"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "site", "chromium"]
|
||||||
|
tags: ["init", "site", "chromium"]
|
||||||
190
ansible/playbooks/fw/site.yaml
Normal file
190
ansible/playbooks/fw/site.yaml
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
---
|
||||||
|
- name: Load secret values
|
||||||
|
hosts: "console"
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
tasks:
|
||||||
|
- name: Load secret from secrets.yaml
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "console"
|
||||||
|
tasks_from: "node/load_secret_vars"
|
||||||
|
apply:
|
||||||
|
tags: ["always"]
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
- name: Site fw
|
||||||
|
hosts: "fw"
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
pre_tasks:
|
||||||
|
- name: Set become password
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['fw'] }}"
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Set timezone to Asia/Seoul
|
||||||
|
community.general.timezone:
|
||||||
|
name: Asia/Seoul
|
||||||
|
become: true
|
||||||
|
tags: ["init", "timezone"]
|
||||||
|
|
||||||
|
- name: Deploy root_ca certificate
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/deploy_root_ca"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "root_crt"]
|
||||||
|
tags: ["init", "root_crt"]
|
||||||
|
|
||||||
|
- name: Deploy hosts file
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/deploy_hosts"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "hosts"]
|
||||||
|
tags: ["init", "hosts"]
|
||||||
|
|
||||||
|
- name: Create default directory
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/create_default_dir"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "default_dir"]
|
||||||
|
tags: ["init", "default_dir"]
|
||||||
|
|
||||||
|
- name: Set ssh host
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_ssh_host"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "ssh_host"]
|
||||||
|
tags: ["init", "ssh_host"]
|
||||||
|
|
||||||
|
- name: Set networkd
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_networkd"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "networkd"]
|
||||||
|
tags: ["init", "networkd"]
|
||||||
|
|
||||||
|
- name: Set wireguard
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_wireguard"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "wireguard"]
|
||||||
|
tags: ["init", "wireguard"]
|
||||||
|
|
||||||
|
- name: Set resolved
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_resolved"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "resolved"]
|
||||||
|
tags: ["init", "resolved"]
|
||||||
|
|
||||||
|
- name: Update and upgrade apt
|
||||||
|
ansible.builtin.apt:
|
||||||
|
upgrade: "dist"
|
||||||
|
update_cache: true
|
||||||
|
cache_valid_time: 3600
|
||||||
|
become: true
|
||||||
|
tags: ["init", "site", "upgrade-packages"]
|
||||||
|
|
||||||
|
- name: Install common packages
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- "acl"
|
||||||
|
- "curl"
|
||||||
|
- "jq"
|
||||||
|
- "wireguard-tools"
|
||||||
|
- "dnsutils"
|
||||||
|
- "conntrack"
|
||||||
|
- "logrotate"
|
||||||
|
- "netcat-openbsd"
|
||||||
|
- "dbus-user-session"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
tags: ["init", "site", "install-packages"]
|
||||||
|
|
||||||
|
- name: Set linger
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_linger"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "linger"]
|
||||||
|
tags: ["init", "linger"]
|
||||||
|
|
||||||
|
- name: Set chrony
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "fw"
|
||||||
|
tasks_from: "services/set_chrony"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "chrony"]
|
||||||
|
tags: ["init", "chrony"]
|
||||||
|
|
||||||
|
- name: Set ddns
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "fw"
|
||||||
|
tasks_from: "services/set_ddns"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "ddns"]
|
||||||
|
tags: ["init", "ddns"]
|
||||||
|
|
||||||
|
- name: Set nftables
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_nftables"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "site", "nftables"]
|
||||||
|
tags: ["init", "site", "nftables"]
|
||||||
|
|
||||||
|
- name: Set suricata
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "fw"
|
||||||
|
tasks_from: "services/set_suricata"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "suricata"]
|
||||||
|
tags: ["site", "suricata"]
|
||||||
|
|
||||||
|
- name: Set crowdsec
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_crowdsec"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "crowdsec"]
|
||||||
|
tags: ["site", "crowdsec"]
|
||||||
|
|
||||||
|
- name: Set bind
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "fw"
|
||||||
|
tasks_from: "services/set_bind"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "update", "bind"]
|
||||||
|
tags: ["init", "update", "bind"]
|
||||||
|
|
||||||
|
- name: Set blocky
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "fw"
|
||||||
|
tasks_from: "services/set_blocky"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "blocky"]
|
||||||
|
tags: ["site", "blocky"]
|
||||||
|
|
||||||
|
- name: Set kea
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "fw"
|
||||||
|
tasks_from: "services/set_kea"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "kea"]
|
||||||
|
tags: ["site", "kea"]
|
||||||
|
|
||||||
|
- name: Set alloy
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_alloy"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "alloy"]
|
||||||
|
tags: ["site", "alloy"]
|
||||||
210
ansible/playbooks/infra/site.yaml
Normal file
210
ansible/playbooks/infra/site.yaml
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
---
|
||||||
|
- name: Load secret values
|
||||||
|
hosts: "console"
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
tasks:
|
||||||
|
- name: Load secret from secrets.yaml
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "console"
|
||||||
|
tasks_from: "node/load_secret_vars"
|
||||||
|
apply:
|
||||||
|
tags: ["always"]
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
- name: Site infra
|
||||||
|
hosts: infra
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
pre_tasks:
|
||||||
|
- name: Set become password
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['infra'] }}"
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Set timezone to Asia/Seoul
|
||||||
|
community.general.timezone:
|
||||||
|
name: Asia/Seoul
|
||||||
|
become: true
|
||||||
|
tags: ["init", "timezone"]
|
||||||
|
|
||||||
|
- name: Deploy root_ca certificate
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/deploy_root_ca"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "root_crt"]
|
||||||
|
tags: ["init", "root_crt"]
|
||||||
|
|
||||||
|
- name: Deploy hosts file
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/deploy_hosts"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "hosts"]
|
||||||
|
tags: ["init", "hosts"]
|
||||||
|
|
||||||
|
- name: Create default directory
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/create_default_dir"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "default_dir"]
|
||||||
|
tags: ["init", "default_dir"]
|
||||||
|
|
||||||
|
- name: Set ssh host
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_ssh_host"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "ssh_host"]
|
||||||
|
tags: ["init", "ssh_host"]
|
||||||
|
|
||||||
|
- name: Set networkd
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_networkd"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "networkd"]
|
||||||
|
tags: ["init", "networkd"]
|
||||||
|
|
||||||
|
- name: Set resolved
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_resolved"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "resolved"]
|
||||||
|
tags: ["init", "resolved"]
|
||||||
|
|
||||||
|
- name: Update and upgrade apt
|
||||||
|
ansible.builtin.apt:
|
||||||
|
upgrade: "dist"
|
||||||
|
update_cache: true
|
||||||
|
cache_valid_time: 3600
|
||||||
|
become: true
|
||||||
|
tags: ["init", "site", "upgrade-packages"]
|
||||||
|
|
||||||
|
- name: Install common packages
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- "acl"
|
||||||
|
- "curl"
|
||||||
|
- "jq"
|
||||||
|
- "netcat-openbsd"
|
||||||
|
- "dbus-user-session"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
tags: ["init", "site", "install-packages"]
|
||||||
|
|
||||||
|
- name: Set linger
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_linger"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "linger"]
|
||||||
|
tags: ["init", "linger"]
|
||||||
|
|
||||||
|
- name: Set podman
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_podman"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "podman"]
|
||||||
|
tags: ["init", "podman"]
|
||||||
|
|
||||||
|
- name: Set nftables
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_nftables"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "nftables"]
|
||||||
|
tags: ["init", "nftables"]
|
||||||
|
|
||||||
|
- name: Set crowdsec
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_crowdsec"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "crowdsec"]
|
||||||
|
tags: ["site", "crowdsec"]
|
||||||
|
|
||||||
|
- name: Set ca
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "infra"
|
||||||
|
tasks_from: "services/set_ca_server"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "ca"]
|
||||||
|
tags: ["site", "ca"]
|
||||||
|
|
||||||
|
- name: Set postgresql
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "infra"
|
||||||
|
tasks_from: "services/set_postgresql"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "postgresql"]
|
||||||
|
tags: ["site", "postgresql"]
|
||||||
|
|
||||||
|
- name: Set caddy
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_caddy"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "caddy"]
|
||||||
|
tags: ["site", "caddy"]
|
||||||
|
|
||||||
|
- name: Set ldap
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "infra"
|
||||||
|
tasks_from: "services/set_ldap"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "ldap"]
|
||||||
|
tags: ["site", "ldap"]
|
||||||
|
|
||||||
|
- name: Set x509 exporter
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "infra"
|
||||||
|
tasks_from: "services/set_x509-exporter"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "x509-exporter"]
|
||||||
|
tags: ["site", "x509-exporter"]
|
||||||
|
|
||||||
|
- name: Set prometheus
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "infra"
|
||||||
|
tasks_from: "services/set_prometheus"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "prometheus"]
|
||||||
|
tags: ["site", "prometheus"]
|
||||||
|
|
||||||
|
- name: Set loki
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "infra"
|
||||||
|
tasks_from: "services/set_loki"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "loki"]
|
||||||
|
tags: ["site", "loki"]
|
||||||
|
|
||||||
|
- name: Set alloy
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_alloy"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "alloy"]
|
||||||
|
tags: ["site", "alloy"]
|
||||||
|
|
||||||
|
- name: Set grafana
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "infra"
|
||||||
|
tasks_from: "services/set_grafana"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "grafana"]
|
||||||
|
tags: ["site", "grafana"]
|
||||||
|
|
||||||
|
- name: Set kopia
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_kopia"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "kopia"]
|
||||||
|
tags: ["site", "kopia"]
|
||||||
61
ansible/playbooks/vmm/create_vm.yaml
Normal file
61
ansible/playbooks/vmm/create_vm.yaml
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
---
|
||||||
|
- name: Load secret values
|
||||||
|
hosts: "console"
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
tasks:
|
||||||
|
- name: Load secret from secrets.yaml
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "console"
|
||||||
|
tasks_from: "node/load_secret_vars"
|
||||||
|
apply:
|
||||||
|
tags: ["always"]
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
- name: Create vm
|
||||||
|
hosts: vmm_init
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
vars:
|
||||||
|
valid_vm_names:
|
||||||
|
- "fw"
|
||||||
|
- "infra"
|
||||||
|
- "auth"
|
||||||
|
- "app"
|
||||||
|
tasks:
|
||||||
|
- name: Set vm name depends on tags
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
target_vm: "{{ ansible_run_tags[0] }}"
|
||||||
|
when: (ansible_run_tags | length) == 1
|
||||||
|
|
||||||
|
- name: Check VM name
|
||||||
|
ansible.builtin.fail:
|
||||||
|
msg: "invalid vm name. vm name should be included in \"{{ valid_vm_names | join(', ') }}\""
|
||||||
|
when: (target_vm | default("none")) not in valid_vm_names
|
||||||
|
|
||||||
|
- name: Set become password
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['vmm'] }}"
|
||||||
|
|
||||||
|
- name: Create seed file
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "vmm"
|
||||||
|
tasks_from: "vm/create_seed"
|
||||||
|
apply:
|
||||||
|
delegate_to: "console"
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
- name: Deploy vm init files
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "vmm"
|
||||||
|
tasks_from: "vm/deploy_vm_init"
|
||||||
|
apply:
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
- name: Register vm
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "vmm"
|
||||||
|
tasks_from: "vm/register_vm"
|
||||||
|
apply:
|
||||||
|
tags: ["always"]
|
||||||
|
tags: ["always"]
|
||||||
165
ansible/playbooks/vmm/site.yaml
Normal file
165
ansible/playbooks/vmm/site.yaml
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
---
|
||||||
|
- name: Set host and load secret values
|
||||||
|
hosts: "console"
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
tasks:
|
||||||
|
- name: Set host as vmm
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
vmm_host: "vmm"
|
||||||
|
when: "'init' is not in ansible_run_tags"
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
- name: Load secret from secrets.yaml
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "console"
|
||||||
|
tasks_from: "node/load_secret_vars"
|
||||||
|
apply:
|
||||||
|
tags: ["always"]
|
||||||
|
tags: ["always"]
|
||||||
|
|
||||||
|
|
||||||
|
- name: Site vmm
|
||||||
|
hosts: "{{ hostvars['console']['vmm_host'] | default('vmm_init') }}"
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
pre_tasks:
|
||||||
|
- name: Set become password
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['vmm'] }}"
|
||||||
|
tags: ["always"]
|
||||||
|
tasks:
|
||||||
|
# init
|
||||||
|
- name: Set timezone to Asia/Seoul
|
||||||
|
community.general.timezone:
|
||||||
|
name: Asia/Seoul
|
||||||
|
become: true
|
||||||
|
tags: ["init", "timezone"]
|
||||||
|
|
||||||
|
- name: Deploy root_ca certificate
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/deploy_root_ca"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "root_crt"]
|
||||||
|
tags: ["init", "root_crt"]
|
||||||
|
|
||||||
|
- name: Deploy hosts file
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/deploy_hosts"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "hosts"]
|
||||||
|
tags: ["init", "hosts"]
|
||||||
|
|
||||||
|
- name: Create default directory
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/create_default_dir"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "default_dir"]
|
||||||
|
tags: ["init", "default_dir"]
|
||||||
|
|
||||||
|
- name: Set ssh host
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_ssh_host"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "ssh_host"]
|
||||||
|
tags: ["init", "ssh_host"]
|
||||||
|
|
||||||
|
- name: Set networkd
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_networkd"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "networkd"]
|
||||||
|
tags: ["init", "networkd"]
|
||||||
|
|
||||||
|
- name: Set resolved
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_resolved"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "resolved"]
|
||||||
|
tags: ["init", "resolved"]
|
||||||
|
|
||||||
|
- name: Set timesyncd
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_timesyncd"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "timesyncd"]
|
||||||
|
tags: ["init", "timesyncd"]
|
||||||
|
|
||||||
|
- name: Set linger # vmm has dbus-user-session in it
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_linger"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "linger"]
|
||||||
|
tags: ["init", "linger"]
|
||||||
|
|
||||||
|
- name: Set libvirt
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "vmm"
|
||||||
|
tasks_from: "node/set_libvirt"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "libvirt"]
|
||||||
|
tags: ["init", "libvirt"]
|
||||||
|
|
||||||
|
- name: Set nftables
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "node/set_nftables"
|
||||||
|
apply:
|
||||||
|
tags: ["init", "site", "nftables"]
|
||||||
|
tags: ["init", "site", "nftables"]
|
||||||
|
|
||||||
|
- name: Update and upgrade apt # init roles has no internet (airgap statement)
|
||||||
|
ansible.builtin.apt:
|
||||||
|
update_cache: true
|
||||||
|
upgrade: "dist"
|
||||||
|
cache_valid_time: 3600
|
||||||
|
when: inventory_hostname != "vmm_init"
|
||||||
|
become: true
|
||||||
|
tags: ["site", "upgrade-packages"]
|
||||||
|
|
||||||
|
- name: Set crowdsec
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_crowdsec"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "crowdsec"]
|
||||||
|
when: inventory_hostname != "vmm_init"
|
||||||
|
tags: ["site", "crowdsec"]
|
||||||
|
|
||||||
|
- name: Set alloy
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "common"
|
||||||
|
tasks_from: "services/set_alloy"
|
||||||
|
apply:
|
||||||
|
tags: ["site", "alloy"]
|
||||||
|
when: inventory_hostname != "vmm_init"
|
||||||
|
tags: ["site", "alloy"]
|
||||||
|
|
||||||
|
- name: Install packages # they are already installed in prerequisite step
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- acl
|
||||||
|
- curl
|
||||||
|
- jq
|
||||||
|
- crowdsec
|
||||||
|
- systemd-resolved
|
||||||
|
- qemu-system-x86
|
||||||
|
- ksmtuned
|
||||||
|
- libvirt-daemon-system
|
||||||
|
- virt-top
|
||||||
|
- python3
|
||||||
|
- python3-apt
|
||||||
|
- python3-libvirt
|
||||||
|
- python3-lxml
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
when: "'init' is not in ansible_run_tags"
|
||||||
|
tags: ["never", "install-packages"]
|
||||||
70
ansible/roles/app/tasks/node/set_raid.yaml
Normal file
70
ansible/roles/app/tasks/node/set_raid.yaml
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
---
|
||||||
|
- name: Check btrfs installation
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
command -v btrfs
|
||||||
|
become: true # btrfs is located in /usr/sbin, which means root permission is needed.
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: "is_btrfs_installed"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Install btrfs
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: "btrfs-progs"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
when: is_btrfs_installed.rc != 0
|
||||||
|
|
||||||
|
- name: Set hard disk path
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
set -o pipefail
|
||||||
|
ls -1 /dev/disk/by-path/*{{ vm['pass_through']['sata_controller']['address'] }}* | \
|
||||||
|
grep -v '\.0$' | \
|
||||||
|
sort
|
||||||
|
changed_when: false
|
||||||
|
register: "hdd_path_list"
|
||||||
|
|
||||||
|
- name: Check app_hdd filesystem already exists
|
||||||
|
ansible.builtin.command: |
|
||||||
|
blkid -L {{ storage['btrfs']['label'] }}
|
||||||
|
register: is_app_data
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Check disk number
|
||||||
|
ansible.builtin.fail:
|
||||||
|
msg: "Below 4 disks for RAID10, found {{ hdd_path_list.stdout_lines | length }}"
|
||||||
|
when: (hdd_path_list.stdout_lines | length) < 4
|
||||||
|
|
||||||
|
- name: Set btrfs raid10 volume
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
mkfs.btrfs -f \
|
||||||
|
-L {{ storage['btrfs']['label'] }} \
|
||||||
|
-d {{ storage['btrfs']['level'] }} \
|
||||||
|
-m {{ storage['btrfs']['level'] }} \
|
||||||
|
{{ hdd_path_list.stdout_lines | join(' ') }}
|
||||||
|
become: true
|
||||||
|
when:
|
||||||
|
- is_app_data.rc != 0
|
||||||
|
- (hdd_path_list.stdout_lines | length) >= 4
|
||||||
|
changed_when: is_mkfs.rc == 0
|
||||||
|
register: "is_mkfs"
|
||||||
|
|
||||||
|
- name: Mount btrfs raid10 volume
|
||||||
|
ansible.posix.mount:
|
||||||
|
path: "{{ storage['btrfs']['mount_point'] }}"
|
||||||
|
src: "LABEL={{ storage['btrfs']['label'] }}"
|
||||||
|
state: "mounted"
|
||||||
|
fstype: "btrfs"
|
||||||
|
opts: "defaults,noatime,compress=zstd:3,autodefrag,degraded,nofail"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Set hard disk path permissions
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ storage['btrfs']['mount_point'] }}"
|
||||||
|
state: "directory"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0770"
|
||||||
|
become: true
|
||||||
11
ansible/roles/auth/handlers/main.yaml
Normal file
11
ansible/roles/auth/handlers/main.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
- name: Restart authelia
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "authelia.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
scope: "user"
|
||||||
|
daemon_reload: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_authelia"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
78
ansible/roles/auth/tasks/services/set_authelia.yaml
Normal file
78
ansible/roles/auth/tasks/services/set_authelia.yaml
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
---
|
||||||
|
- name: Create authelia directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['home_path'] }}/containers/{{ item }}"
|
||||||
|
state: "directory"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0770"
|
||||||
|
loop:
|
||||||
|
- "authelia"
|
||||||
|
- "authelia/config"
|
||||||
|
- "authelia/certs"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy authelia configuration file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/auth/authelia/config/authelia.yaml.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/containers/authelia/config/authelia.yaml"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_authelia"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy certificates
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ hostvars['console']['ca']['root']['crt'] }}
|
||||||
|
dest: "{{ node['home_path'] }}/containers/authelia/certs/ilnmors_root_ca.crt"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0440"
|
||||||
|
become: true
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Register secret value to podman secret
|
||||||
|
containers.podman.podman_secret:
|
||||||
|
name: "{{ item.name }}"
|
||||||
|
data: "{{ item.value }}"
|
||||||
|
state: "present"
|
||||||
|
force: true
|
||||||
|
loop:
|
||||||
|
- name: "AUTHELIA_JWT_SECRET"
|
||||||
|
value: "{{ hostvars['console']['authelia']['jwt_secret'] }}"
|
||||||
|
- name: "AUTHELIA_SESSION_SECRET"
|
||||||
|
value: "{{ hostvars['console']['authelia']['session_secret'] }}"
|
||||||
|
- name: "AUTHELIA_STORAGE_SECRET"
|
||||||
|
value: "{{ hostvars['console']['authelia']['storage_secret'] }}"
|
||||||
|
- name: "AUTHELIA_HMAC_SECRET"
|
||||||
|
value: "{{ hostvars['console']['authelia']['hmac_secret'] }}"
|
||||||
|
- name: "AUTHELIA_JWKS_RS256"
|
||||||
|
value: "{{ hostvars['console']['authelia']['jwk_rs256'] }}"
|
||||||
|
- name: "AUTHELIA_JWKS_ES256"
|
||||||
|
value: "{{ hostvars['console']['authelia']['jwk_es256'] }}"
|
||||||
|
- name: "AUTHELIA_LDAP_PASSWORD"
|
||||||
|
value: "{{ hostvars['console']['ldap']['password']['authelia'] }}"
|
||||||
|
- name: "POSTGRES_AUTHELIA_PASSWORD"
|
||||||
|
value: "{{ hostvars['console']['postgresql']['password']['authelia'] }}"
|
||||||
|
notify: "notification_restart_authelia"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy container file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/auth/authelia/authelia.container.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/.config/containers/systemd/authelia.container"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0644"
|
||||||
|
notify: "notification_restart_authelia"
|
||||||
|
|
||||||
|
- name: Enable authelia.service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "authelia.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
101
ansible/roles/common/handlers/main.yaml
Normal file
101
ansible/roles/common/handlers/main.yaml
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
---
|
||||||
|
- name: Restart ca certificate
|
||||||
|
ansible.builtin.command: |
|
||||||
|
update-ca-certificates
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_update_ca"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart sshd
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "sshd.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_sshd"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Reload systemd-networkd
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "systemd-networkd.service"
|
||||||
|
state: "reloaded"
|
||||||
|
enabled: true
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_reload_networkctl"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Reload systemd-resolved.service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "systemd-resolved.service"
|
||||||
|
state: "reloaded"
|
||||||
|
enabled: true
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_reload_resolved"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart systemd-timesyncd
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "systemd-timesyncd.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_timesyncd"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Update nftables
|
||||||
|
ansible.builtin.command: |
|
||||||
|
nft -f /etc/nftables.conf
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_update_nftables"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart crowdsec
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "crowdsec.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_crowdsec"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart crowdsec bouncer
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "crowdsec-firewall-bouncer.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
|
when: node['name'] == 'fw'
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_crowdsec_bouncer"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart caddy
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "caddy.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
scope: "user"
|
||||||
|
daemon_reload: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_caddy"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart alloy
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "alloy.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_alloy"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
34
ansible/roles/common/tasks/node/create_default_dir.yaml
Normal file
34
ansible/roles/common/tasks/node/create_default_dir.yaml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
- name: Create common secret directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/secrets"
|
||||||
|
state: "directory"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0711"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Create user secret directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/secrets/{{ node['uid'] }}"
|
||||||
|
state: "directory"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "root"
|
||||||
|
mode: "0500"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Create user systemd directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['home_path'] }}/.config/systemd/user"
|
||||||
|
state: "directory"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0700"
|
||||||
|
|
||||||
|
- name: Create quadlet directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['home_path'] }}/.config/containers/systemd"
|
||||||
|
state: "directory"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0700"
|
||||||
9
ansible/roles/common/tasks/node/deploy_hosts.yaml
Normal file
9
ansible/roles/common/tasks/node/deploy_hosts.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
- name: Deploy /etc/hosts
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/node/common/hosts.j2"
|
||||||
|
dest: "/etc/hosts"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
10
ansible/roles/common/tasks/node/deploy_root_ca.yaml
Normal file
10
ansible/roles/common/tasks/node/deploy_root_ca.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Deploy root_ca.crt
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: "{{ hostvars['console']['ca']['root']['crt'] }}"
|
||||||
|
dest: "/usr/local/share/ca-certificates/ilnmors_root_ca.crt"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify: "notification_update_ca"
|
||||||
20
ansible/roles/common/tasks/node/set_linger.yaml
Normal file
20
ansible/roles/common/tasks/node/set_linger.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
- name: Checking linger
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "/var/lib/systemd/linger/{{ ansible_user }}"
|
||||||
|
register: "is_linger_file"
|
||||||
|
|
||||||
|
- name: Activate linger
|
||||||
|
when: not is_linger_file.stat.exists
|
||||||
|
block:
|
||||||
|
- name: Enable linger
|
||||||
|
ansible.builtin.command: |
|
||||||
|
loginctl enable-linger {{ ansible_user }}
|
||||||
|
become: true
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Reboot system to ensure DBUS socket activation
|
||||||
|
ansible.builtin.reboot:
|
||||||
|
reboot_timeout: 300
|
||||||
|
post_reboot_delay: 3
|
||||||
|
become: true
|
||||||
23
ansible/roles/common/tasks/node/set_networkd.yaml
Normal file
23
ansible/roles/common/tasks/node/set_networkd.yaml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
- name: Set network files directory
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
directory_name: "{{ node['name'] }}"
|
||||||
|
when: node['name'] in ["vmm", "fw"]
|
||||||
|
|
||||||
|
- name: Set target vm
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
target_vm: "{{ node['name'] }}"
|
||||||
|
|
||||||
|
- name: Deploy networkd files
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ item }}"
|
||||||
|
dest: "/etc/systemd/network/{{ item | basename }}"
|
||||||
|
owner: "root"
|
||||||
|
group: "systemd-network"
|
||||||
|
mode: "0640"
|
||||||
|
loop: "{{ query('fileglob', hostvars['console']['node']['config_path'] + '/node/' + (directory_name | default('common')) + '/networkd/*') | sort }}"
|
||||||
|
become: true
|
||||||
|
notify:
|
||||||
|
- "notification_reload_networkctl"
|
||||||
|
- "notification_restart_crowdsec"
|
||||||
|
no_log: true
|
||||||
36
ansible/roles/common/tasks/node/set_nftables.yaml
Normal file
36
ansible/roles/common/tasks/node/set_nftables.yaml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
- name: Check nftables installation
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
command -v nft
|
||||||
|
become: true # nftables is located in /usr/sbin, which means root permission is needed.
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: "is_nftables_installed"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Install nftables
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: "nftables"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
when: is_nftables_installed.rc != 0
|
||||||
|
|
||||||
|
- name: Enable nftables.service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "nftables.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy nftables.conf
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/node/{{ node['name'] }}/nftables.conf.j2"
|
||||||
|
dest: "/etc/nftables.conf"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0700"
|
||||||
|
validate: "/usr/sbin/nft -c -f %s"
|
||||||
|
become: true
|
||||||
|
notify:
|
||||||
|
- "notification_update_nftables"
|
||||||
|
- "notification_restart_crowdsec_bouncer"
|
||||||
39
ansible/roles/common/tasks/node/set_resolved.yaml
Normal file
39
ansible/roles/common/tasks/node/set_resolved.yaml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
- name: Enable systemd-resolved.service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "systemd-resolved.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Check global.conf
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "/etc/systemd/resolved.conf.d/global.conf"
|
||||||
|
register: "is_global_conf"
|
||||||
|
|
||||||
|
- name: Create resolved directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/systemd/resolved.conf.d"
|
||||||
|
state: "directory"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0755"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy global conf file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/node/common/resolved/global.conf.j2"
|
||||||
|
dest: "/etc/systemd/resolved.conf.d/global.conf"
|
||||||
|
owner: "root"
|
||||||
|
group: "systemd-resolve"
|
||||||
|
mode: "0640"
|
||||||
|
become: true
|
||||||
|
notify: "notification_reload_resolved"
|
||||||
|
|
||||||
|
- name: Restart systemd-resolved.service when it is initiated
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "systemd-resolved.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
become: true
|
||||||
|
when: not is_global_conf.stat.exists
|
||||||
119
ansible/roles/common/tasks/node/set_ssh_host.yaml
Normal file
119
ansible/roles/common/tasks/node/set_ssh_host.yaml
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
---
|
||||||
|
- name: Deploy /etc/ssh/local_ssh_ca.pub
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ hostvars['console']['ssh']['ca']['pub'] }}
|
||||||
|
dest: "/etc/ssh/local_ssh_ca.pub"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Check ssh_host_key-cert.pub
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "/etc/ssh/ssh_host_ed25519_key-cert.pub"
|
||||||
|
register: "is_signed_ca_key"
|
||||||
|
|
||||||
|
- name: Get current ssh_host_key-cert.pub Key ID
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
set -o pipefail
|
||||||
|
ssh-keygen -L -f /etc/ssh/ssh_host_ed25519_key-cert.pub | \
|
||||||
|
grep "Key ID" | \
|
||||||
|
sed -E 's/.*Key ID: "(.*)"/\1/'
|
||||||
|
when: is_signed_ca_key.stat.exists
|
||||||
|
changed_when: false
|
||||||
|
register: "current_key_id"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Get current ssh_host_key-cert.pub san
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
set -o pipefail
|
||||||
|
ssh-keygen -L -f /etc/ssh/ssh_host_ed25519_key-cert.pub | \
|
||||||
|
sed -n '/Principals:/,/Critical Options:/p' | \
|
||||||
|
sed '1d;$d' | \
|
||||||
|
sed 's/^[[:space:]]*//'
|
||||||
|
when: is_signed_ca_key.stat.exists
|
||||||
|
changed_when: false
|
||||||
|
register: "current_san_id"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Set current key informations
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
current_id_key: "{{ current_key_id.stdout }}"
|
||||||
|
current_san_list: "{{ current_san_id.stdout_lines }}"
|
||||||
|
when: is_signed_ca_key.stat.exists
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Compare key values between current information and defined information
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
is_certificate_info_different: true
|
||||||
|
when: (current_id_key | default("")) != node['name'] or (current_san_list | default([])) != (node['ssh_san'].split(',') | map('trim') | list)
|
||||||
|
|
||||||
|
- name: Get SSH CA and signing
|
||||||
|
when: not is_signed_ca_key.stat.exists or (is_certificate_info_different | default(false))
|
||||||
|
block:
|
||||||
|
- name: Get ssh_host_key.pub from remote server
|
||||||
|
ansible.builtin.fetch:
|
||||||
|
src: "/etc/ssh/ssh_host_ed25519_key.pub"
|
||||||
|
dest: "/run/user/{{ hostvars['console']['node']['uid'] }}/{{ node['name'] }}_ssh_host_ed25519_key.pub"
|
||||||
|
flat: true
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Get SSH CA
|
||||||
|
delegate_to: "console"
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ hostvars['console']['ssh']['ca']['key'] }}
|
||||||
|
dest: "/run/user/{{ hostvars['console']['node']['uid'] }}/local_ssh_ca_private_key"
|
||||||
|
owner: "console"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0400"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Sign on ssh host keys (pub file)
|
||||||
|
delegate_to: "console"
|
||||||
|
ansible.builtin.command: |
|
||||||
|
ssh-keygen -s /run/user/{{ hostvars['console']['node']['uid'] }}/local_ssh_ca_private_key \
|
||||||
|
-h \
|
||||||
|
-I "{{ node['name'] }}" \
|
||||||
|
-n "{{ node['ssh_san'] }}" \
|
||||||
|
/run/user/{{ hostvars['console']['node']['uid'] }}/{{ node['name'] }}_ssh_host_ed25519_key.pub
|
||||||
|
changed_when: not is_signed_ca_key.stat.exists or (is_certificate_info_different | default(false))
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy signed pub file
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "/run/user/{{ hostvars['console']['node']['uid'] }}/{{ node['name'] }}_ssh_host_ed25519_key-cert.pub"
|
||||||
|
dest: "/etc/ssh/ssh_host_ed25519_key-cert.pub"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_sshd"
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: Clean temporary files
|
||||||
|
delegate_to: "console"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/run/user/{{ hostvars['console']['node']['uid'] }}/{{ item }}"
|
||||||
|
state: "absent"
|
||||||
|
loop:
|
||||||
|
- "{{ node['name'] }}_ssh_host_ed25519_key.pub"
|
||||||
|
- "{{ node['name'] }}_ssh_host_ed25519_key-cert.pub"
|
||||||
|
- "local_ssh_ca_private_key"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Set sshd_config.d files
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/node/common/ssh/{{ item }}"
|
||||||
|
dest: "/etc/ssh/sshd_config.d/{{ item }}"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
loop:
|
||||||
|
- "prohibit_root.conf"
|
||||||
|
- "ssh_ca.conf"
|
||||||
|
- "host_certificate.conf"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_sshd"
|
||||||
20
ansible/roles/common/tasks/node/set_timesyncd.yaml
Normal file
20
ansible/roles/common/tasks/node/set_timesyncd.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
- name: Create timesyncd.conf.d
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/systemd/timesyncd.conf.d"
|
||||||
|
state: "directory"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0755"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy timesyncd.conf.d/local-ntp.conf
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/node/common/timesyncd/local-ntp.conf"
|
||||||
|
dest: "/etc/systemd/timesyncd.conf.d/local-ntp.conf"
|
||||||
|
owner: "root"
|
||||||
|
group: "systemd-timesync"
|
||||||
|
mode: "0640"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_timesyncd"
|
||||||
|
no_log: true
|
||||||
15
ansible/roles/common/tasks/node/set_wireguard.yaml
Normal file
15
ansible/roles/common/tasks/node/set_wireguard.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
- name: Create wg0 files
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/node/fw/wireguard/{{ item }}"
|
||||||
|
dest: "/etc/systemd/network/{{ item }}"
|
||||||
|
owner: "root"
|
||||||
|
group: "systemd-network"
|
||||||
|
mode: "0640"
|
||||||
|
loop:
|
||||||
|
- "30-fw-wg0.netdev"
|
||||||
|
- "31-fw-wg0.network"
|
||||||
|
become: true
|
||||||
|
when: node['name'] == 'fw'
|
||||||
|
notify: "notification_reload_networkctl"
|
||||||
|
no_log: true
|
||||||
73
ansible/roles/common/tasks/services/set_alloy.yaml
Normal file
73
ansible/roles/common/tasks/services/set_alloy.yaml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
---
|
||||||
|
- name: Gather system facts (hardware)
|
||||||
|
ansible.builtin.setup:
|
||||||
|
gather_subset:
|
||||||
|
- hardware
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy alloy deb file (x86_64)
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['data_path'] }}/bin/alloy-{{ version['packages']['alloy'] }}-amd64.deb"
|
||||||
|
dest: "/var/cache/apt/archives/alloy-{{ version['packages']['alloy'] }}.deb"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
when: ansible_facts['architecture'] == "x86_64"
|
||||||
|
|
||||||
|
- name: Deploy alloy deb file (aarch64)
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['data_path'] }}/bin/alloy-{{ version['packages']['alloy'] }}-arm64.deb"
|
||||||
|
dest: "/var/cache/apt/archives/alloy-{{ version['packages']['alloy'] }}.deb"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
when: ansible_facts['architecture'] == "aarch64"
|
||||||
|
|
||||||
|
- name: Install alloy
|
||||||
|
ansible.builtin.apt:
|
||||||
|
deb: "/var/cache/apt/archives/alloy-{{ version['packages']['alloy'] }}.deb"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy alloy config
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/alloy/config.alloy.j2"
|
||||||
|
dest: "/etc/alloy/config.alloy"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_alloy"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Create alloy.service.d
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/systemd/system/alloy.service.d"
|
||||||
|
state: "directory"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0755"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Set alloy.service.d/override.conf
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "/etc/systemd/system/alloy.service.d/override.conf"
|
||||||
|
content: |
|
||||||
|
[Service]
|
||||||
|
Restart=always
|
||||||
|
RestartSec=60
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_alloy"
|
||||||
|
|
||||||
|
- name: Enable alloy service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "alloy.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
99
ansible/roles/common/tasks/services/set_caddy.yaml
Normal file
99
ansible/roles/common/tasks/services/set_caddy.yaml
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
---
|
||||||
|
# infra, auth, app (vmm, fw has no podman in it)
|
||||||
|
- name: Create caddy directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['home_path'] }}/containers/{{ item }}"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
state: "directory"
|
||||||
|
mode: "0770"
|
||||||
|
loop:
|
||||||
|
- "caddy"
|
||||||
|
- "caddy/etc"
|
||||||
|
- "caddy/data"
|
||||||
|
- "caddy/build"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Create caddy log directory for auth
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /var/log/caddy
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
state: "directory"
|
||||||
|
mode: "0755"
|
||||||
|
become: true
|
||||||
|
when: node['name'] == "auth"
|
||||||
|
|
||||||
|
- name: Register acme key to podman secret
|
||||||
|
containers.podman.podman_secret:
|
||||||
|
name: "CADDY_ACME_KEY"
|
||||||
|
data: "{{ hostvars['console']['ca']['acme_key'] }}"
|
||||||
|
state: "present"
|
||||||
|
force: true
|
||||||
|
notify: "notification_restart_caddy"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Register crowdsec bouncer key to podman secret
|
||||||
|
containers.podman.podman_secret:
|
||||||
|
name: "CADDY_CROWDSEC_KEY"
|
||||||
|
data: "{{ hostvars['console']['crowdsec']['bouncer']['caddy'] }}"
|
||||||
|
state: "present"
|
||||||
|
force: true
|
||||||
|
when: node['name'] == "auth"
|
||||||
|
notify: "notification_restart_caddy"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy containerfile for build
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/common/caddy/build/caddy.containerfile.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/containers/caddy/build/Containerfile"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0640"
|
||||||
|
|
||||||
|
- name: Deploy root crt for build
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: "{{ hostvars['console']['ca']['root']['crt'] }}"
|
||||||
|
dest: "{{ node['home_path'] }}/containers/caddy/build/ilnmors_root_ca.crt"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0640"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Build caddy container image
|
||||||
|
containers.podman.podman_image:
|
||||||
|
name: "ilnmors.internal/{{ node['name'] }}/caddy"
|
||||||
|
# check tags from container file
|
||||||
|
tag: "{{ version['containers']['caddy'] }}"
|
||||||
|
state: "build"
|
||||||
|
path: "{{ node['home_path'] }}/containers/caddy/build"
|
||||||
|
|
||||||
|
- name: Prune caddy dangling images
|
||||||
|
containers.podman.podman_prune:
|
||||||
|
image: true
|
||||||
|
|
||||||
|
- name: Deploy caddyfile
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/common/caddy/etc/{{ node['name'] }}/Caddyfile.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/containers/caddy/etc/Caddyfile"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
notify: "notification_restart_caddy"
|
||||||
|
|
||||||
|
- name: Deploy container file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/common/caddy/caddy.container.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/.config/containers/systemd/caddy.container"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0644"
|
||||||
|
notify: "notification_restart_caddy"
|
||||||
|
|
||||||
|
- name: Enable caddy
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "caddy.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
304
ansible/roles/common/tasks/services/set_crowdsec.yaml
Normal file
304
ansible/roles/common/tasks/services/set_crowdsec.yaml
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
---
|
||||||
|
- name: Check crowdsec installed
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
command -v crowdsec
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: "is_crowdsec_installed"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Check crowdsec bouncer installed
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
command -v crowdsec-firewall-bouncer
|
||||||
|
when: node['name'] == "fw"
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: "is_crowdsec_bouncer_installed"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Install crowdsec
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: "crowdsec"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
when: is_crowdsec_installed.rc != 0
|
||||||
|
|
||||||
|
- name: Install crowdsec bouncers
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: "crowdsec-firewall-bouncer"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
when:
|
||||||
|
- node['name'] == "fw"
|
||||||
|
- is_crowdsec_bouncer_installed.rc != 0
|
||||||
|
|
||||||
|
- name: Set acquis.d list for bouncer
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
acquisd_list:
|
||||||
|
fw:
|
||||||
|
collection: "crowdsecurity/suricata"
|
||||||
|
config: "suricata.yaml"
|
||||||
|
auth:
|
||||||
|
collection: "crowdsecurity/caddy"
|
||||||
|
config: "caddy.yaml"
|
||||||
|
|
||||||
|
- name: Deploy crowdsec-update service files
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/crowdsec/{{ item }}"
|
||||||
|
dest: "/etc/systemd/system/{{ item }}"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
validate: "/usr/bin/systemd-analyze verify %s"
|
||||||
|
loop:
|
||||||
|
- "crowdsec-update.service"
|
||||||
|
- "crowdsec-update.timer"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy crowdsec config.yaml
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/crowdsec/etc/config.yaml.j2"
|
||||||
|
dest: "/etc/crowdsec/config.yaml"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_crowdsec"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy crowdsec local_api_credentials.yaml
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/crowdsec/etc/local_api_credentials.yaml.j2"
|
||||||
|
dest: "/etc/crowdsec/local_api_credentials.yaml"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0600"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_crowdsec"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Set Crowdsec LAPI configuration
|
||||||
|
when: node['name'] == "fw"
|
||||||
|
block:
|
||||||
|
- name: Create crowdsec ssl directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/crowdsec/ssl"
|
||||||
|
state: "directory"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0700"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy crowdsec lapi ssl certificate
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ hostvars['console']['crowdsec']['crt'] | trim }}
|
||||||
|
{{ hostvars['console']['ca']['intermediate']['crt'] }}
|
||||||
|
dest: "/etc/crowdsec/ssl/crowdsec.crt"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_crowdsec"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy crowdsec lapi ssl key
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ hostvars['console']['crowdsec']['key'] }}
|
||||||
|
dest: "/etc/crowdsec/ssl/crowdsec.key"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0400"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_crowdsec"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Get existing machines list
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "cscli machines list -o json"
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
register: "existing_crowdsec_machines_list"
|
||||||
|
|
||||||
|
- name: Set existing machines' name
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
existing_machines_name: "{{ existing_crowdsec_machines_list.stdout | from_json | map(attribute='machineId') | list }}"
|
||||||
|
|
||||||
|
- name: Set goal machines' name
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
machines_name: ["fw", "vmm", "infra", "auth", "app"]
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Prune unknown (random) machines
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "cscli machines delete {{ item }}"
|
||||||
|
loop: "{{ existing_machines_name | difference(machines_name) }}"
|
||||||
|
become: true
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Register crowdsec machines to LAPI server
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "cscli machines add {{ item }} --password {{ hostvars['console']['crowdsec']['machine'][item] }} --force -f /dev/null"
|
||||||
|
loop: "{{ machines_name }}"
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Get existing bouncers list
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "cscli bouncers list -o json"
|
||||||
|
become: true
|
||||||
|
register: "existing_crowdsec_bouncers_list"
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Set existing bouncers' name
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
existing_bouncers_name: "{{ existing_crowdsec_bouncers_list.stdout | from_json | map(attribute='name') | list }}"
|
||||||
|
|
||||||
|
- name: Flush bouncers
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "cscli bouncers delete {{ item }}"
|
||||||
|
loop: "{{ existing_bouncers_name }}"
|
||||||
|
become: true
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Set bouncers' name
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
bouncers_name: ["fw", "caddy"]
|
||||||
|
|
||||||
|
- name: Register Firewall Bouncer to LAPI
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "cscli bouncers add {{ item }}-bouncer -k {{ hostvars['console']['crowdsec']['bouncer'][item] }}"
|
||||||
|
loop: "{{ bouncers_name }}"
|
||||||
|
become: true
|
||||||
|
changed_when: true
|
||||||
|
notify: "notification_restart_crowdsec_bouncer"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Set crowdsec bouncer
|
||||||
|
when: node['name'] in acquisd_list
|
||||||
|
block:
|
||||||
|
- name: Install crowdsec collection
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "cscli collections install {{ acquisd_list[node['name']]['collection'] }}"
|
||||||
|
become: true
|
||||||
|
changed_when: "'overwrite' not in is_collection_installed.stderr"
|
||||||
|
failed_when:
|
||||||
|
- is_collection_installed.rc != 0
|
||||||
|
- "'already installed' not in is_collection_installed.stderr"
|
||||||
|
register: "is_collection_installed"
|
||||||
|
|
||||||
|
- name: Create crowdsec acquis.d directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/crowdsec/acquis.d"
|
||||||
|
state: "directory"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0755"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Create whitelists.yaml
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/crowdsec/bouncers/whitelists.yaml.j2"
|
||||||
|
dest: "/etc/crowdsec/parsers/s02-enrich/whitelists.yaml"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify:
|
||||||
|
- "notification_restart_crowdsec"
|
||||||
|
- "notification_restart_crowdsec_bouncer"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy acquis.d file
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/crowdsec/acquis.d/{{ acquisd_list[node['name']]['config'] }}"
|
||||||
|
dest: "/etc/crowdsec/acquis.d/{{ acquisd_list[node['name']]['config'] }}"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_crowdsec"
|
||||||
|
|
||||||
|
- name: Set Crowdsec-Firewall-Bouncer
|
||||||
|
when: node['name'] == "fw"
|
||||||
|
block:
|
||||||
|
- name: Deploy crowdsec-firewall-bouncer.yaml
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml.j2"
|
||||||
|
dest: "/etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0600"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_crowdsec_bouncer"
|
||||||
|
|
||||||
|
- name: Delete crowdsec-firewall-bouncer.yaml subfiles (.id, .local)
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml.{{ item }}"
|
||||||
|
state: "absent"
|
||||||
|
loop:
|
||||||
|
- "local"
|
||||||
|
- "id"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_crowdsec_bouncer"
|
||||||
|
|
||||||
|
- name: Create crowdsec-firewall-bouncer.service.d
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/systemd/system/crowdsec-firewall-bouncer.service.d"
|
||||||
|
state: "directory"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0755"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Set crowdsec-firewall-bouncer.service.d/override.conf
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "/etc/systemd/system/crowdsec-firewall-bouncer.service.d/override.conf"
|
||||||
|
content: |
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
TimeoutStartSec=600
|
||||||
|
Restart=always
|
||||||
|
RestartSec=60
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_crowdsec_bouncer"
|
||||||
|
|
||||||
|
|
||||||
|
- name: Create crowdsec.service.d
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/systemd/system/crowdsec.service.d"
|
||||||
|
state: "directory"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0755"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Set crowdsec.service.d/override.conf
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "/etc/systemd/system/crowdsec.service.d/override.conf"
|
||||||
|
content: |
|
||||||
|
[Service]
|
||||||
|
Restart=always
|
||||||
|
RestartSec=60
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_crowdsec"
|
||||||
|
|
||||||
|
- name: Enable auto crowdsec rules update
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "crowdsec-update.timer"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
|
|
||||||
|
# cscli bouncers list
|
||||||
|
# cscli machines list
|
||||||
|
# cscli metrics
|
||||||
137
ansible/roles/common/tasks/services/set_kopia.yaml
Normal file
137
ansible/roles/common/tasks/services/set_kopia.yaml
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
---
|
||||||
|
- name: Gather system facts (hardware)
|
||||||
|
ansible.builtin.setup:
|
||||||
|
gather_subset:
|
||||||
|
- hardware
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Check kopia installation
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
command -v kopia
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: "is_kopia_installed"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Set console kopia
|
||||||
|
when: node['name'] == 'console'
|
||||||
|
block:
|
||||||
|
- name: Apply cli tools (x86_64)
|
||||||
|
ansible.builtin.apt:
|
||||||
|
deb: "{{ node['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-amd64.deb"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
when:
|
||||||
|
- ansible_facts['architecture'] == "x86_64"
|
||||||
|
- is_kopia_installed.rc != 0
|
||||||
|
- name: Apply cli tools (aarch64)
|
||||||
|
ansible.builtin.apt:
|
||||||
|
deb: "{{ node['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-arm64.deb"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
when:
|
||||||
|
- ansible_facts['architecture'] == "aarch64"
|
||||||
|
- is_kopia_installed.rc != 0
|
||||||
|
- name: Connect kopia server
|
||||||
|
environment:
|
||||||
|
KOPIA_PASSWORD: "{{ hostvars['console']['kopia']['user']['console'] }}"
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
/usr/bin/kopia repository connect server \
|
||||||
|
--url=https://{{ infra_uri['kopia']['domain'] }}:{{ infra_uri['kopia']['ports']['https'] }} \
|
||||||
|
--override-username=console \
|
||||||
|
--override-hostname=console.ilnmors.internal
|
||||||
|
changed_when: false
|
||||||
|
failed_when: is_kopia_connected.rc != 0
|
||||||
|
register: "is_kopia_connected"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Set infra/app kopia
|
||||||
|
when: node['name'] in ['infra', 'app']
|
||||||
|
block:
|
||||||
|
- name: Set kopia uid
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
kopia_uid: 951
|
||||||
|
- name: Deploy kopia deb file (x86_64)
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-amd64.deb"
|
||||||
|
dest: "/var/cache/apt/archives/kopia-{{ version['packages']['kopia'] }}.deb"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
when: ansible_facts['architecture'] == "x86_64"
|
||||||
|
- name: Deploy kopia deb file (aarch64)
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-arm64.deb"
|
||||||
|
dest: "/var/cache/apt/archives/kopia-{{ version['packages']['kopia'] }}.deb"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
when: ansible_facts['architecture'] == "aarch64"
|
||||||
|
- name: Create kopia group
|
||||||
|
ansible.builtin.group:
|
||||||
|
name: "kopia"
|
||||||
|
gid: "{{ kopia_uid }}"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
- name: Create kopia user
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "kopia"
|
||||||
|
uid: "{{ kopia_uid }}"
|
||||||
|
group: "kopia"
|
||||||
|
shell: "/usr/sbin/nologin"
|
||||||
|
password_lock: true
|
||||||
|
comment: "Kopia backup User"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
- name: Create kopia directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item.name }}"
|
||||||
|
state: "directory"
|
||||||
|
owner: "kopia"
|
||||||
|
group: "root"
|
||||||
|
mode: "{{ item.mode }}"
|
||||||
|
loop:
|
||||||
|
- name: "/etc/kopia"
|
||||||
|
mode: "0700"
|
||||||
|
- name: "/etc/secrets/951"
|
||||||
|
mode: "0500"
|
||||||
|
- name: "/var/cache/kopia"
|
||||||
|
mode: "0700"
|
||||||
|
become: true
|
||||||
|
no_log: true
|
||||||
|
- name: Install kopia
|
||||||
|
ansible.builtin.apt:
|
||||||
|
deb: "/var/cache/apt/archives/kopia-{{ version['packages']['kopia'] }}.deb"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
when: is_kopia_installed.rc != 0
|
||||||
|
- name: Deploy kopia env
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/kopia/kopia.env.j2"
|
||||||
|
dest: "/etc/secrets/{{ kopia_uid }}/kopia.env"
|
||||||
|
owner: "{{ kopia_uid }}"
|
||||||
|
group: "root"
|
||||||
|
mode: "0400"
|
||||||
|
become: true
|
||||||
|
no_log: true
|
||||||
|
- name: Deploy kopia service files
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/kopia/{{ item }}.j2"
|
||||||
|
dest: "/etc/systemd/system/{{ item }}"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
validate: "/usr/bin/systemd-analyze verify %s"
|
||||||
|
loop:
|
||||||
|
- "kopia-backup.service"
|
||||||
|
- "kopia-backup.timer"
|
||||||
|
become: true
|
||||||
|
- name: Enable auto kopia rules update
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "kopia-backup.timer"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
46
ansible/roles/common/tasks/services/set_podman.yaml
Normal file
46
ansible/roles/common/tasks/services/set_podman.yaml
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
- name: Check podman installation
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
command -v podman
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: "is_podman_installed"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Create container directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['home_path'] }}/containers"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
state: "directory"
|
||||||
|
mode: "0700"
|
||||||
|
|
||||||
|
- name: Create contaienr data directory for app
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['home_path'] }}/data/containers"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
state: "directory"
|
||||||
|
mode: "0770"
|
||||||
|
when: node['name'] == "app"
|
||||||
|
|
||||||
|
- name: Install podman and reset ssh connection for initiating
|
||||||
|
when: is_podman_installed.rc != 0
|
||||||
|
become: true
|
||||||
|
block:
|
||||||
|
- name: Set subid scope (Overwrite)
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ ansible_user }}:100000:65536
|
||||||
|
dest: "/etc/sub{{ item }}"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
loop:
|
||||||
|
- "uid"
|
||||||
|
- "gid"
|
||||||
|
- name: Install podman
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- "podman"
|
||||||
|
state: "present"
|
||||||
8
ansible/roles/console/handlers/main.yaml
Normal file
8
ansible/roles/console/handlers/main.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
- name: Register font
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
fc-cache -f -v
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_update_font"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
29
ansible/roles/console/tasks/node/load_secret_vars.yaml
Normal file
29
ansible/roles/console/tasks/node/load_secret_vars.yaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
- name: Check sops installation (Prerequisite)
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
command -v sops
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: "is_sops_installed"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Failure when sops is missing
|
||||||
|
ansible.builtin.fail:
|
||||||
|
msg: "sops is not installed. Please install sops manually as described in README.md before running this playbook"
|
||||||
|
when: is_sops_installed.rc != 0
|
||||||
|
|
||||||
|
- name: Decrypt secret values in console
|
||||||
|
environment:
|
||||||
|
SOPS_AGE_KEY: "{{ hostvars['console']['age_key'] }}"
|
||||||
|
ansible.builtin.command: |
|
||||||
|
sops -d --output-type yaml {{ hostvars['console']['node']['config_path'] }}/secrets/secrets.yaml
|
||||||
|
changed_when: false
|
||||||
|
register: "decrypted_secrets"
|
||||||
|
run_once: true
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Load decrypted secret vaules in console
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
"{{ item.key }}": "{{ item.value }}"
|
||||||
|
loop: "{{ decrypted_secrets.stdout | from_yaml | dict2items }}"
|
||||||
|
no_log: true
|
||||||
109
ansible/roles/console/tasks/node/set_ssh_client.yaml
Normal file
109
ansible/roles/console/tasks/node/set_ssh_client.yaml
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
---
|
||||||
|
- name: Create ssh id_console
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: "{{ hostvars['console']['ssh']['console']['key'] }}"
|
||||||
|
dest: "/etc/secrets/{{ node['uid'] }}/id_console"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "root"
|
||||||
|
mode: "0400"
|
||||||
|
become: true
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Create ssh id_console.pub
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: "{{ hostvars['console']['ssh']['console']['pub'] }}"
|
||||||
|
dest: "/etc/secrets/{{ node['uid'] }}/id_console.pub"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "root"
|
||||||
|
mode: "0400"
|
||||||
|
become: true
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Create ssh_known_hosts
|
||||||
|
become: true
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
@cert-authority *.ilnmors.internal {{ hostvars['console']['ssh']['ca']['pub'] }}
|
||||||
|
dest: "/etc/ssh/ssh_known_hosts"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Check id_console-cert.pub
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "/etc/secrets/{{ node['uid'] }}/id_console-cert.pub"
|
||||||
|
register: "is_signed_console_key"
|
||||||
|
|
||||||
|
- name: Get current id_console-cert.pub allow users
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
set -o pipefail
|
||||||
|
ssh-keygen -L -f /etc/secrets/{{ node['uid'] }}/id_console-cert.pub | \
|
||||||
|
sed -n '/Principals:/,/Critical Options:/p' | \
|
||||||
|
sed '1d;$d' | \
|
||||||
|
sed 's/^[[:space:]]*//'
|
||||||
|
when: is_signed_console_key.stat.exists
|
||||||
|
changed_when: false
|
||||||
|
register: "current_allow_users"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Set key informations
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
current_user_list: "{{ current_allow_users.stdout_lines }}"
|
||||||
|
when: is_signed_console_key.stat.exists
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Compare key values between current information and defined information
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
is_certificate_info_different: true
|
||||||
|
when: (current_user_list | default([])) != (node['ssh_users'].split(',') | map('trim') | list)
|
||||||
|
|
||||||
|
- name: Get SSH CA and signing
|
||||||
|
when: not is_signed_console_key.stat.exists or (is_certificate_info_different | default(false))
|
||||||
|
block:
|
||||||
|
- name: Get SSH CA
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ hostvars['console']['ssh']['ca']['key'] }}
|
||||||
|
dest: "/run/user/{{ node['uid'] }}/local_ssh_ca_private_key"
|
||||||
|
owner: "console"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0400"
|
||||||
|
no_log: true
|
||||||
|
- name: Sign on ssh console key (pub file)
|
||||||
|
ansible.builtin.command: |
|
||||||
|
ssh-keygen -s /run/user/{{ node['uid'] }}/local_ssh_ca_private_key \
|
||||||
|
-I "{{ node['name'] }}" \
|
||||||
|
-n "{{ node['ssh_users'] }}" \
|
||||||
|
/etc/secrets/{{ node['uid'] }}/id_console.pub
|
||||||
|
become: true
|
||||||
|
changed_when: not is_signed_console_key.stat.exists or (is_certificate_info_different | default(false))
|
||||||
|
no_log: true
|
||||||
|
always:
|
||||||
|
- name: Clean temporary files
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/run/user/{{ node['uid'] }}/local_ssh_ca_private_key"
|
||||||
|
state: "absent"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Create .ssh directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['home_path'] }}/.ssh"
|
||||||
|
state: "directory"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0700"
|
||||||
|
|
||||||
|
- name: Create ssh config file
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{% for host in groups['all'] if host != 'console' %}
|
||||||
|
Host {{ host }}
|
||||||
|
HostName {{ hostvars[host]['ansible_host'] }}
|
||||||
|
User {{ hostvars[host]['ansible_user'] }}
|
||||||
|
IdentityFile /etc/secrets/{{ node['uid'] }}/id_console
|
||||||
|
{% endfor %}
|
||||||
|
dest: "{{ node['home_path'] }}/.ssh/config"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
31
ansible/roles/console/tasks/services/set_chromium.yaml
Normal file
31
ansible/roles/console/tasks/services/set_chromium.yaml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
- name: Check chromium installation
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
command -v chromium
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: "is_chromium_installed"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Check korean font installation
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
fc-list | grep -i "nanum"
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: "is_font_installed"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Install chromium
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: "chromium"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
when: is_chromium_installed.rc != 0
|
||||||
|
|
||||||
|
- name: Install font
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: "fonts-nanum"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
when: is_font_installed.rc != 0
|
||||||
|
notify: "notification_update_font"
|
||||||
108
ansible/roles/console/tasks/services/set_cli_tools.yaml
Normal file
108
ansible/roles/console/tasks/services/set_cli_tools.yaml
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
---
|
||||||
|
- name: Gather system facts (hardware)
|
||||||
|
ansible.builtin.setup:
|
||||||
|
gather_subset:
|
||||||
|
- hardware
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Check ansible installation
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
command -v ansible
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: "is_ansible_installed"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Upgrade ansible module
|
||||||
|
community.general.ansible_galaxy_install:
|
||||||
|
type: "collection"
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: "latest"
|
||||||
|
loop:
|
||||||
|
- "ansible.posix"
|
||||||
|
- "community.libvirt"
|
||||||
|
- "community.general"
|
||||||
|
- "containers.podman"
|
||||||
|
when: is_ansible_installed.rc == 0
|
||||||
|
|
||||||
|
- name: Download sops
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: "https://github.com/getsops/sops/releases/download/v{{ version['packages']['sops'] }}/\
|
||||||
|
sops_{{ version['packages']['sops'] }}_{{ item }}.deb"
|
||||||
|
dest: "{{ node['data_path'] }}/bin/sops-{{ version['packages']['sops'] }}-{{ item }}.deb"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
loop:
|
||||||
|
- "amd64"
|
||||||
|
- "arm64"
|
||||||
|
|
||||||
|
- name: Download step-cli
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: "https://dl.smallstep.com/gh-release/cli/gh-release-header/v{{ version['packages']['step'] }}/\
|
||||||
|
step-cli_{{ version['packages']['step'] }}-1_{{ item }}.deb"
|
||||||
|
dest: "{{ node['data_path'] }}/bin/step-{{ version['packages']['step'] }}-{{ item }}.deb"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
loop:
|
||||||
|
- "amd64"
|
||||||
|
- "arm64"
|
||||||
|
|
||||||
|
- name: Download kopia
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: "https://github.com/kopia/kopia/releases/download/v{{ version['packages']['kopia'] }}/\
|
||||||
|
kopia_{{ version['packages']['kopia'] }}_linux_{{ item }}.deb"
|
||||||
|
dest: "{{ node['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-{{ item }}.deb"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
loop:
|
||||||
|
- "amd64"
|
||||||
|
- "arm64"
|
||||||
|
|
||||||
|
- name: Download blocky
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: "https://github.com/0xERR0R/blocky/releases/download/v{{ version['packages']['blocky'] }}/\
|
||||||
|
blocky_v{{ version['packages']['blocky'] }}_Linux_{{ item }}.tar.gz"
|
||||||
|
dest: "{{ node['data_path'] }}/bin/blocky-{{ version['packages']['blocky'] }}-{{ item }}.tar.gz"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600" # noqa: line-length
|
||||||
|
loop:
|
||||||
|
- "x86_64"
|
||||||
|
- "arm64"
|
||||||
|
|
||||||
|
- name: Download alloy
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: "https://github.com/grafana/alloy/releases/download/v{{ version['packages']['alloy'] }}/\
|
||||||
|
alloy-{{ version['packages']['alloy'] }}-1.{{ item }}.deb"
|
||||||
|
dest: "{{ node['data_path'] }}/bin/alloy-{{ version['packages']['alloy'] }}-{{ item }}.deb"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
loop:
|
||||||
|
- "amd64"
|
||||||
|
- "arm64"
|
||||||
|
|
||||||
|
- name: Apply cli tools (x86_64)
|
||||||
|
ansible.builtin.apt:
|
||||||
|
deb: "{{ node['data_path'] }}/bin/{{ item }}"
|
||||||
|
state: "present"
|
||||||
|
loop:
|
||||||
|
- "sops-{{ version['packages']['sops'] }}-amd64.deb"
|
||||||
|
- "step-{{ version['packages']['step'] }}-amd64.deb"
|
||||||
|
- "kopia-{{ version['packages']['kopia'] }}-amd64.deb"
|
||||||
|
become: true
|
||||||
|
when: ansible_facts['architecture'] == "x86_64"
|
||||||
|
|
||||||
|
- name: Apply cli tools (aarch64)
|
||||||
|
ansible.builtin.apt:
|
||||||
|
deb: "{{ node['data_path'] }}/bin/{{ item }}"
|
||||||
|
state: "present"
|
||||||
|
loop:
|
||||||
|
- "sops-{{ version['packages']['sops'] }}-arm64.deb"
|
||||||
|
- "step-{{ version['packages']['step'] }}-arm64.deb"
|
||||||
|
- "kopia-{{ version['packages']['kopia'] }}-arm64.deb"
|
||||||
|
become: true
|
||||||
|
when: ansible_facts['architecture'] == "aarch64"
|
||||||
63
ansible/roles/fw/handlers/main.yaml
Normal file
63
ansible/roles/fw/handlers/main.yaml
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
---
|
||||||
|
- name: Restart chrony
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "chrony.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_chrony"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Update suricata rules
|
||||||
|
ansible.builtin.command:
|
||||||
|
suricata-update --disable-conf /etc/suricata/disable.conf --enable-conf /etc/suricata/enable.conf --local /etc/suricata/rules/local.rules
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_update_suricata_rules"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart suricata
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "suricata.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_suricata"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart bind9
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "named.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_bind"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart blocky
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "blocky.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: "true"
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_blocky"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart kea-dhcp4
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "kea-dhcp4-server.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_kea4"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
103
ansible/roles/fw/tasks/services/set_bind.yaml
Normal file
103
ansible/roles/fw/tasks/services/set_bind.yaml
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
- name: Check bind9 installation
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
command -v named
|
||||||
|
become: true # named is located in /usr/sbin, which means root permission is needed.
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: "is_bind_installed"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Set bind9 zone files
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
bind_zone_files:
|
||||||
|
- "db.ilnmors.internal"
|
||||||
|
- "db.ilnmors.com"
|
||||||
|
- "db.1.168.192.in-addr.arpa"
|
||||||
|
- "db.10.168.192.in-addr.arpa"
|
||||||
|
- "db.1.00df.ip6.arpa"
|
||||||
|
- "db.10.00df.ip6.arpa"
|
||||||
|
|
||||||
|
- name: Install bind9
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: "bind9"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
when: is_bind_installed.rc != 0
|
||||||
|
|
||||||
|
- name: Deploy acem.key
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: "{{ hostvars['console']['bind']['acme_key'] }}"
|
||||||
|
dest: "/etc/bind/acme.key"
|
||||||
|
owner: "bind"
|
||||||
|
group: "bind"
|
||||||
|
mode: "0640"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_bind"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy db files
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/fw/bind/lib/{{ item }}"
|
||||||
|
dest: "/var/lib/bind/{{ item }}"
|
||||||
|
owner: "bind"
|
||||||
|
group: "bind"
|
||||||
|
mode: "0640"
|
||||||
|
loop: "{{ bind_zone_files }}"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_bind"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Clean BIND journal files
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/var/lib/bind/{{ item }}.jnl"
|
||||||
|
state: absent
|
||||||
|
loop: "{{ bind_zone_files }}"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_bind"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy named.conf
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/fw/bind/etc/named.conf.j2"
|
||||||
|
dest: "/etc/bind/named.conf"
|
||||||
|
owner: "root"
|
||||||
|
group: "bind"
|
||||||
|
mode: "0640"
|
||||||
|
validate: "/usr/bin/named-checkconf -z %s"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_bind"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Create named.service.d
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/systemd/system/named.service.d"
|
||||||
|
state: "directory"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0755"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Set named.service.d/override.conf
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "/etc/systemd/system/named.service.d/override.conf"
|
||||||
|
content: |
|
||||||
|
[Service]
|
||||||
|
Restart=always
|
||||||
|
RestartSec=60
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_bind"
|
||||||
|
|
||||||
|
- name: Enable bind9 service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "named.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
become: true
|
||||||
|
|
||||||
|
# Verify working
|
||||||
|
# dig A fw.ilnmors.internal @fd00:10::3
|
||||||
|
# dig AAAA fw.ilnmors.internal @fd00:10::3
|
||||||
117
ansible/roles/fw/tasks/services/set_blocky.yaml
Normal file
117
ansible/roles/fw/tasks/services/set_blocky.yaml
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
---
|
||||||
|
- name: Gather system facts (hardware)
|
||||||
|
ansible.builtin.setup:
|
||||||
|
gather_subset:
|
||||||
|
- hardware
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Create blocky group
|
||||||
|
ansible.builtin.group:
|
||||||
|
name: "blocky"
|
||||||
|
gid: 953
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Create blocky user
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "blocky"
|
||||||
|
uid: 953
|
||||||
|
group: "blocky"
|
||||||
|
shell: "/usr/sbin/nologin"
|
||||||
|
password_lock: true
|
||||||
|
comment: "Blocky DNS User"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Create blocky etc directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
owner: "blocky"
|
||||||
|
group: "blocky"
|
||||||
|
mode: "0750"
|
||||||
|
state: "directory"
|
||||||
|
loop:
|
||||||
|
- "/etc/blocky"
|
||||||
|
- "/etc/blocky/ssl"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy blocky binary file (x86_64)
|
||||||
|
ansible.builtin.unarchive:
|
||||||
|
src: "{{ hostvars['console']['node']['data_path'] }}/bin/blocky-{{ version['packages']['blocky'] }}-x86_64.tar.gz"
|
||||||
|
dest: "/usr/local/bin/"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0755"
|
||||||
|
extra_opts:
|
||||||
|
- "--strip-components=0"
|
||||||
|
- "--wildcards"
|
||||||
|
- "blocky"
|
||||||
|
become: true
|
||||||
|
when: ansible_facts['architecture'] == "x86_64"
|
||||||
|
notify: "notification_restart_blocky"
|
||||||
|
|
||||||
|
- name: Deploy blocky binary file (aarch64)
|
||||||
|
ansible.builtin.unarchive:
|
||||||
|
src: "{{ hostvars['console']['node']['data_path'] }}/bin/blocky-{{ version['packages']['blocky'] }}-arm64.tar.gz"
|
||||||
|
dest: "/usr/local/bin/"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0755"
|
||||||
|
extra_opts:
|
||||||
|
- "--strip-components=0"
|
||||||
|
- "--wildcards"
|
||||||
|
- "blocky"
|
||||||
|
become: true
|
||||||
|
when: ansible_facts['architecture'] == "aarch64"
|
||||||
|
notify: "notification_restart_blocky"
|
||||||
|
|
||||||
|
- name: Deploy blocky config
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/fw/blocky/etc/config.yaml.j2"
|
||||||
|
dest: "/etc/blocky/config.yaml"
|
||||||
|
owner: "blocky"
|
||||||
|
group: "blocky"
|
||||||
|
mode: "0640"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_blocky"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy blocky certificate and key
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ item.value }}
|
||||||
|
dest: "/etc/blocky/ssl/{{ item.name }}"
|
||||||
|
owner: "blocky"
|
||||||
|
group: "blocky"
|
||||||
|
mode: "{{ item.mode }}"
|
||||||
|
loop:
|
||||||
|
- name: "blocky.crt"
|
||||||
|
value: |
|
||||||
|
{{ hostvars['console']['blocky']['crt'] | trim }}
|
||||||
|
{{ hostvars['console']['ca']['intermediate']['crt'] }}
|
||||||
|
mode: "0440"
|
||||||
|
- name: "blocky.key"
|
||||||
|
value: "{{ hostvars['console']['blocky']['key'] }}"
|
||||||
|
mode: "0400"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_blocky"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy blocky service
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/fw/blocky/blocky.service"
|
||||||
|
dest: "/etc/systemd/system/blocky.service"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
validate: "/usr/bin/systemd-analyze verify %s"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_blocky"
|
||||||
|
|
||||||
|
- name: Enable blocky service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "blocky.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
55
ansible/roles/fw/tasks/services/set_chrony.yaml
Normal file
55
ansible/roles/fw/tasks/services/set_chrony.yaml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
- name: Check chrnoy installation
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
command -v chronyc
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: "is_chrony_installed"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Install chrony
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: "chrony"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
when: is_chrony_installed.rc != 0
|
||||||
|
|
||||||
|
- name: Deploy local acl file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/fw/chrony/local-acl.conf.j2"
|
||||||
|
dest: "/etc/chrony/conf.d/local-acl.conf"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_chrony"
|
||||||
|
|
||||||
|
- name: Create chrony.service.d
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/systemd/system/chrony.service.d"
|
||||||
|
state: "directory"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0755"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Set chrony.service.d/override.conf
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "/etc/systemd/system/chrony.service.d/override.conf"
|
||||||
|
content: |
|
||||||
|
[Service]
|
||||||
|
Restart=always
|
||||||
|
RestartSec=60
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_chrony"
|
||||||
|
|
||||||
|
- name: Enable chrony service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "chrony.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
41
ansible/roles/fw/tasks/services/set_ddns.yaml
Normal file
41
ansible/roles/fw/tasks/services/set_ddns.yaml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
- name: Create ddns secret env file
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
ZONE_ID={{ hostvars['console']['ddns']['zone_id'] }}
|
||||||
|
API_KEY={{ hostvars['console']['ddns']['api_key'] }}
|
||||||
|
dest: "/etc/secrets/{{ node['uid'] }}/ddns.env"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0400"
|
||||||
|
become: true
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy ddns script
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/fw/ddns/ddns.sh"
|
||||||
|
dest: "/usr/local/bin"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0711"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy ddns service files
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/fw/ddns/{{ item }}"
|
||||||
|
dest: "{{ node['home_path'] }}/.config/systemd/user/{{ item }}"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
validate: "/usr/bin/systemd-analyze verify %s"
|
||||||
|
loop:
|
||||||
|
- "ddns.service"
|
||||||
|
- "ddns.timer"
|
||||||
|
|
||||||
|
- name: Register ddns timer
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "ddns.timer"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
57
ansible/roles/fw/tasks/services/set_kea.yaml
Normal file
57
ansible/roles/fw/tasks/services/set_kea.yaml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
---
|
||||||
|
- name: Check Kea dhcp4 installation
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
command -v kea-dhcp4
|
||||||
|
become: true # kea-dhcp4 is located in /usr/sbin, which means root permission is needed.
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: "is_kea4_installed"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Install kea dhcp 4
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- "kea-dhcp4-server"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
when: is_kea4_installed.rc != 0
|
||||||
|
|
||||||
|
- name: Deploy kea dhcp4 conf
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/fw/kea/kea-dhcp4.conf.j2"
|
||||||
|
dest: "/etc/kea/kea-dhcp4.conf"
|
||||||
|
owner: "_kea"
|
||||||
|
group: "_kea"
|
||||||
|
mode: "0600"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_kea4"
|
||||||
|
|
||||||
|
- name: Create kea-dhcp-server.service.d
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/systemd/system/kea-dhcp4-server.service.d"
|
||||||
|
state: "directory"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0755"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Set kea-dhcp-server.service.d/override.conf
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "/etc/systemd/system/kea-dhcp4-server.service.d/override.conf"
|
||||||
|
content: |
|
||||||
|
[Service]
|
||||||
|
Restart=always
|
||||||
|
RestartSec=60
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify:
|
||||||
|
- "notification_restart_kea4"
|
||||||
|
|
||||||
|
- name: Enable kea service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "kea-dhcp4-server.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
become: true
|
||||||
141
ansible/roles/fw/tasks/services/set_suricata.yaml
Normal file
141
ansible/roles/fw/tasks/services/set_suricata.yaml
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
---
|
||||||
|
- name: Check suricata installation
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
command -v suricata
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: "is_suricata_installed"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Install suricata
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- "suricata"
|
||||||
|
- "suricata-update"
|
||||||
|
state: "present"
|
||||||
|
become: true
|
||||||
|
when: is_suricata_installed.rc != 0
|
||||||
|
|
||||||
|
- name: Deploy suricata-update service files
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/fw/suricata/{{ item }}"
|
||||||
|
dest: "/etc/systemd/system/{{ item }}"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
validate: "/usr/bin/systemd-analyze verify %s"
|
||||||
|
loop:
|
||||||
|
- "suricata-update.service"
|
||||||
|
- "suricata-update.timer"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy suricata custom configurations
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/fw/suricata/etc/{{ item }}"
|
||||||
|
dest: "/etc/suricata/{{ item }}"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
loop:
|
||||||
|
- "disable.conf"
|
||||||
|
- "enable.conf"
|
||||||
|
become: true
|
||||||
|
notify:
|
||||||
|
- "notification_update_suricata_rules"
|
||||||
|
- "notification_restart_suricata"
|
||||||
|
|
||||||
|
- name: Deploy suricata custom rules
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/fw/suricata/etc/local.rules"
|
||||||
|
dest: "/etc/suricata/rules/local.rules"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify:
|
||||||
|
- "notification_update_suricata_rules"
|
||||||
|
- "notification_restart_suricata"
|
||||||
|
|
||||||
|
- name: Check suricata rules
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "/var/lib/suricata/rules/suricata.rules"
|
||||||
|
register: "is_suricata_rules_file"
|
||||||
|
|
||||||
|
- name: Update suricata rules
|
||||||
|
ansible.builtin.command:
|
||||||
|
suricata-update
|
||||||
|
become: true
|
||||||
|
when: not is_suricata_rules_file.stat.exists
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Enable auto suricata rules update
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "suricata-update.timer"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy suricata.yaml
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/fw/suricata/etc/suricata.yaml.j2"
|
||||||
|
dest: "/etc/suricata/suricata.yaml"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
validate: "/usr/bin/suricata -T -c %s"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_suricata"
|
||||||
|
|
||||||
|
- name: Create suricata.service.d
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/systemd/system/suricata.service.d"
|
||||||
|
state: "directory"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0755"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Set suricata.service.d/override.conf
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "/etc/systemd/system/suricata.service.d/override.conf"
|
||||||
|
content: |
|
||||||
|
[Service]
|
||||||
|
Restart=always
|
||||||
|
RestartSec=60
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
notify:
|
||||||
|
- "notification_restart_suricata"
|
||||||
|
|
||||||
|
- name: Enable suricata service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "suricata.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Set suricata logs logrotate
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
/var/log/suricata/*.log /var/log/suricata/*.json {
|
||||||
|
weekly
|
||||||
|
missingok
|
||||||
|
rotate 4
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
notifempty
|
||||||
|
maxsize 500M
|
||||||
|
sharedscripts
|
||||||
|
postrotate
|
||||||
|
/usr/bin/systemctl reload suricata > /dev/null 2>/dev/null || true
|
||||||
|
endscript
|
||||||
|
}
|
||||||
|
dest: "/etc/logrotate.d/suricata"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
85
ansible/roles/infra/handlers/main.yaml
Normal file
85
ansible/roles/infra/handlers/main.yaml
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
- name: Restart ca
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "ca.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: "true"
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_ca"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Reload postgresql
|
||||||
|
ansible.builtin.command:
|
||||||
|
/usr/bin/podman exec -u postgres postgresql sh -c "pg_ctl reload"
|
||||||
|
when: not (is_postgresql_init_run | default(false))
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_reload_postgresql"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart postgresql
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "postgresql.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
|
when: not (is_postgresql_init_run | default(false))
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_postgresql"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart ldap
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "ldap.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_ldap"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart prometheus
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "prometheus.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_prometheus"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart loki
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "loki.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_loki"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Restart grafana
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "grafana.service"
|
||||||
|
state: "restarted"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_grafana"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
|
|
||||||
|
- name: Enable x509-exporter.service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "x509-exporter.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
|
changed_when: false
|
||||||
|
listen: "notification_restart_x509-exporter"
|
||||||
|
ignore_errors: true # noqa: ignore-errors
|
||||||
84
ansible/roles/infra/tasks/services/set_ca_server.yaml
Normal file
84
ansible/roles/infra/tasks/services/set_ca_server.yaml
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
---
|
||||||
|
- name: Set ca container subuid
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
ca_subuid: "100999"
|
||||||
|
|
||||||
|
- name: Create ca directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['home_path'] }}/containers/{{ item }}"
|
||||||
|
owner: "{{ ca_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
state: "directory"
|
||||||
|
mode: "0770"
|
||||||
|
loop:
|
||||||
|
- "ca"
|
||||||
|
- "ca/certs"
|
||||||
|
- "ca/secrets"
|
||||||
|
- "ca/config"
|
||||||
|
- "ca/db"
|
||||||
|
- "ca/templates"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Register secret value to podman secret
|
||||||
|
containers.podman.podman_secret:
|
||||||
|
name: "STEP_CA_PASSWORD"
|
||||||
|
data: "{{ hostvars['console']['ca']['intermediate']['password'] }}"
|
||||||
|
state: "present"
|
||||||
|
force: true
|
||||||
|
notify: "notification_restart_ca"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy ca config files
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/ca/config/{{ item }}.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/containers/ca/config/{{ item }}"
|
||||||
|
owner: "{{ ca_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0400"
|
||||||
|
loop:
|
||||||
|
- "ca.json"
|
||||||
|
- "defaults.json"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_ca"
|
||||||
|
|
||||||
|
- name: Deploy ca certificate and key
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ item.value }}
|
||||||
|
dest: "{{ item.path }}/{{ item.name }}"
|
||||||
|
owner: "{{ ca_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "{{ item.mode }}"
|
||||||
|
loop:
|
||||||
|
- name: "ilnmors_root_ca.crt"
|
||||||
|
value: "{{ hostvars['console']['ca']['root']['crt'] }}"
|
||||||
|
path: "{{ node['home_path'] }}/containers/ca/certs"
|
||||||
|
mode: "0440"
|
||||||
|
- name: "ilnmors_intermediate_ca.crt"
|
||||||
|
value: "{{ hostvars['console']['ca']['intermediate']['crt'] }}"
|
||||||
|
path: "{{ node['home_path'] }}/containers/ca/certs"
|
||||||
|
mode: "0440"
|
||||||
|
- name: "ilnmors_intermediate_ca.key"
|
||||||
|
value: "{{ hostvars['console']['ca']['intermediate']['key'] }}"
|
||||||
|
path: "{{ node['home_path'] }}/containers/ca/secrets"
|
||||||
|
mode: "0400"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_ca"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy container file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/ca/ca.container.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/.config/containers/systemd/ca.container"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0644"
|
||||||
|
notify: "notification_restart_ca"
|
||||||
|
|
||||||
|
- name: Enable ca
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "ca.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
89
ansible/roles/infra/tasks/services/set_grafana.yaml
Normal file
89
ansible/roles/infra/tasks/services/set_grafana.yaml
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
---
|
||||||
|
- name: Set grafana container subuid
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
grafana_subuid: "100471"
|
||||||
|
|
||||||
|
- name: Create grafana directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['home_path'] }}/containers/{{ item }}"
|
||||||
|
owner: "{{ grafana_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
state: "directory"
|
||||||
|
mode: "0770"
|
||||||
|
loop:
|
||||||
|
- "grafana"
|
||||||
|
- "grafana/data"
|
||||||
|
- "grafana/etc"
|
||||||
|
- "grafana/etc/provisioning"
|
||||||
|
- "grafana/etc/dashboards"
|
||||||
|
- "grafana/ssl"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy root certificate and key
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ hostvars['console']['ca']['root']['crt'] }}
|
||||||
|
dest: "{{ node['home_path'] }}/containers/grafana/ssl/ilnmors_root_ca.crt"
|
||||||
|
owner: "{{ grafana_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0400"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_grafana"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Register secret value to podman secret
|
||||||
|
containers.podman.podman_secret:
|
||||||
|
name: "{{ item.name }}"
|
||||||
|
data: "{{ item.value }}"
|
||||||
|
state: "present"
|
||||||
|
force: true
|
||||||
|
loop:
|
||||||
|
- name: "GF_DB_PASSWORD"
|
||||||
|
value: "{{ hostvars['console']['postgresql']['password']['grafana'] }}"
|
||||||
|
- name: "LDAP_BIND_PASSWORD"
|
||||||
|
value: "{{ hostvars['console']['ldap']['password']['grafana'] }}"
|
||||||
|
- name: "GF_ADMIN_PASSWORD"
|
||||||
|
value: "{{ hostvars['console']['grafana']['user']['password'] }}"
|
||||||
|
notify: "notification_restart_grafana"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy configruation files
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/grafana/etc/{{ item }}.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/containers/grafana/etc/{{ item }}"
|
||||||
|
owner: "{{ grafana_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0400"
|
||||||
|
loop:
|
||||||
|
- "grafana.ini"
|
||||||
|
- "ldap.toml"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_grafana"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy provisioing and dashboard files
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/grafana/etc/provisioning/"
|
||||||
|
dest: "{{ node['home_path'] }}/containers/grafana/etc/provisioning/"
|
||||||
|
owner: "{{ grafana_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0400"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_grafana"
|
||||||
|
|
||||||
|
- name: Deploy container file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/grafana/grafana.container.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/.config/containers/systemd/grafana.container"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0644"
|
||||||
|
notify: "notification_restart_grafana"
|
||||||
|
|
||||||
|
- name: Enable grafana
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "grafana.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
112
ansible/roles/infra/tasks/services/set_ldap.yaml
Normal file
112
ansible/roles/infra/tasks/services/set_ldap.yaml
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
---
|
||||||
|
- name: Set ldap container subuid
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
ldap_subuid: "100999"
|
||||||
|
|
||||||
|
- name: Create ldap directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['home_path'] }}/containers/{{ item }}"
|
||||||
|
owner: "{{ ldap_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
state: "directory"
|
||||||
|
mode: "0770"
|
||||||
|
loop:
|
||||||
|
- "ldap"
|
||||||
|
- "ldap/data"
|
||||||
|
- "ldap/ssl"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy ldap certificate and key
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ item.value }}
|
||||||
|
dest: "{{ node['home_path'] }}/containers/ldap/ssl/{{ item.name }}"
|
||||||
|
owner: "{{ ldap_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "{{ item.mode }}"
|
||||||
|
loop:
|
||||||
|
- name: "ilnmors_root_ca.crt"
|
||||||
|
value: "{{ hostvars['console']['ca']['root']['crt'] }}"
|
||||||
|
mode: "0440"
|
||||||
|
- name: "ldap.crt"
|
||||||
|
value: |
|
||||||
|
{{ hostvars['console']['ldap']['crt'] | trim }}
|
||||||
|
{{ hostvars['console']['ca']['intermediate']['crt'] }}
|
||||||
|
mode: "0440"
|
||||||
|
- name: "ldap.key"
|
||||||
|
value: "{{ hostvars['console']['ldap']['key'] }}"
|
||||||
|
mode: "0400"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_ldap"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Register secret value to podman secret
|
||||||
|
containers.podman.podman_secret:
|
||||||
|
name: "{{ item.name }}"
|
||||||
|
data: "{{ item.value }}"
|
||||||
|
state: "present"
|
||||||
|
force: true
|
||||||
|
loop:
|
||||||
|
# urlencode doesn't fix `/` as `%2F`. It needs replace
|
||||||
|
- name: "LLDAP_DATABASE_URL"
|
||||||
|
value: "postgres://ldap:{{ hostvars['console']['postgresql']['password']['ldap'] | urlencode | replace('/', '%2F') }}\
|
||||||
|
@{{ infra_uri['postgresql']['domain'] }}/ldap_db?sslmode=verify-full&sslrootcert=/etc/ssl/ldap/ilnmors_root_ca.crt"
|
||||||
|
- name: "LLDAP_KEY_SEED"
|
||||||
|
value: "{{ hostvars['console']['ldap']['seed_key'] }}"
|
||||||
|
- name: "LLDAP_JWT_SECRET"
|
||||||
|
value: "{{ hostvars['console']['ldap']['jwt_secret'] }}"
|
||||||
|
notify: "notification_restart_ldap"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Initiate ldap (When = false, If DB data does not exist in postgresql, activate this block)
|
||||||
|
when: false
|
||||||
|
become: true
|
||||||
|
block:
|
||||||
|
- name: Register extra secret value to podman secret
|
||||||
|
containers.podman.podman_secret:
|
||||||
|
name: "LLDAP_LDAP_USER_PASSWORD"
|
||||||
|
data: "{{ hostvars['console']['ldap']['password']['user'] }}"
|
||||||
|
state: "present"
|
||||||
|
force: true
|
||||||
|
# You must check the image version first (following container file on data/config/containers/infra/ldap/ldap.container)
|
||||||
|
|
||||||
|
- name: Initiate ldap
|
||||||
|
containers.podman.podman_container:
|
||||||
|
name: "init_LLDAP"
|
||||||
|
image: "docker.io/lldap/lldap:{{ version['containers']['ldap'] }}"
|
||||||
|
rm: true
|
||||||
|
detach: false
|
||||||
|
env:
|
||||||
|
TZ: "Asia/Seoul"
|
||||||
|
LLDAP_LDAP_BASE_DN: "dc=ilnmors,dc=internal"
|
||||||
|
secrets:
|
||||||
|
- "LLDAP_DATABASE_URL,type=env"
|
||||||
|
- "LLDAP_KEY_SEED,type=env"
|
||||||
|
- "LLDAP_JWT_SECRET,type=env"
|
||||||
|
- "LLDAP_LDAP_USER_PASSWORD,type=env"
|
||||||
|
volumes:
|
||||||
|
- "{{ node['home_path'] }}/containers/ldap/data:/data:rw"
|
||||||
|
- "{{ node['home_path'] }}/containers/ldap/ssl:/etc/ssl/ldap:ro"
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: Clean extra secret value from podman secret
|
||||||
|
containers.podman.podman_secret:
|
||||||
|
name: "LLDAP_LDAP_USER_PASSWORD"
|
||||||
|
state: "absent"
|
||||||
|
|
||||||
|
- name: Deploy container file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/ldap/ldap.container.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/.config/containers/systemd/ldap.container"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0644"
|
||||||
|
notify: "notification_restart_ldap"
|
||||||
|
|
||||||
|
- name: Enable ldap
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "ldap.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
70
ansible/roles/infra/tasks/services/set_loki.yaml
Normal file
70
ansible/roles/infra/tasks/services/set_loki.yaml
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
---
|
||||||
|
- name: Set loki container subuid
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
loki_subuid: "110000" # 10001
|
||||||
|
|
||||||
|
- name: Create loki directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['home_path'] }}/containers/{{ item }}"
|
||||||
|
state: "directory"
|
||||||
|
owner: "{{ loki_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0770"
|
||||||
|
loop:
|
||||||
|
- "loki"
|
||||||
|
- "loki/etc"
|
||||||
|
- "loki/data"
|
||||||
|
- "loki/ssl"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy loki configuration file
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/loki/etc/loki.yaml"
|
||||||
|
dest: "{{ node['home_path'] }}/containers/loki/etc/loki.yaml"
|
||||||
|
owner: "{{ loki_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_loki"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy loki certificate and key
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ item.value }}
|
||||||
|
dest: "{{ node['home_path'] }}/containers/loki/ssl/{{ item.name }}"
|
||||||
|
owner: "{{ loki_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "{{ item.mode }}"
|
||||||
|
loop:
|
||||||
|
- name: "ilnmors_root_ca.crt"
|
||||||
|
value: "{{ hostvars['console']['ca']['root']['crt'] }}"
|
||||||
|
mode: "0440"
|
||||||
|
- name: "loki.crt"
|
||||||
|
value: |
|
||||||
|
{{ hostvars['console']['loki']['crt'] | trim }}
|
||||||
|
{{ hostvars['console']['ca']['intermediate']['crt'] }}
|
||||||
|
mode: "0440"
|
||||||
|
- name: "loki.key"
|
||||||
|
value: "{{ hostvars['console']['loki']['key'] }}"
|
||||||
|
mode: "0400"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_loki"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy container file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/loki/loki.container.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/.config/containers/systemd/loki.container"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0644"
|
||||||
|
notify: "notification_restart_loki"
|
||||||
|
|
||||||
|
- name: Enable loki
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "loki.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
169
ansible/roles/infra/tasks/services/set_postgresql.yaml
Normal file
169
ansible/roles/infra/tasks/services/set_postgresql.yaml
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
---
|
||||||
|
- name: Set postgresql container subuid
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
postgresql_subuid: "100998"
|
||||||
|
|
||||||
|
- name: Set connected services list
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
# telegraf has no database
|
||||||
|
connected_services:
|
||||||
|
- "ldap"
|
||||||
|
- "authelia"
|
||||||
|
- "grafana"
|
||||||
|
|
||||||
|
- name: Create postgresql directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['home_path'] }}/containers/{{ item }}"
|
||||||
|
state: "directory"
|
||||||
|
owner: "{{ postgresql_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0770"
|
||||||
|
loop:
|
||||||
|
- "postgresql"
|
||||||
|
- "postgresql/data"
|
||||||
|
- "postgresql/config"
|
||||||
|
- "postgresql/ssl"
|
||||||
|
- "postgresql/init"
|
||||||
|
- "postgresql/backups"
|
||||||
|
- "postgresql/build"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy containerfile for build
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/build/postgresql.containerfile.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/containers/postgresql/build/Containerfile"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0640"
|
||||||
|
|
||||||
|
- name: Build postgresql container image
|
||||||
|
containers.podman.podman_image:
|
||||||
|
name: "ilnmors.internal/{{ node['name'] }}/postgres"
|
||||||
|
# check tags from container file
|
||||||
|
tag: "pg{{ version['containers']['postgresql'] }}-vectorchord{{ version['containers']['vectorchord'] }}"
|
||||||
|
state: "build"
|
||||||
|
path: "{{ node['home_path'] }}/containers/postgresql/build"
|
||||||
|
|
||||||
|
- name: Prune postgresql dangling images
|
||||||
|
containers.podman.podman_prune:
|
||||||
|
image: true
|
||||||
|
|
||||||
|
- name: Deploy postgresql configuration files
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/config/{{ item }}.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/containers/postgresql/config/{{ item }}"
|
||||||
|
owner: "{{ postgresql_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
loop:
|
||||||
|
- "postgresql.conf"
|
||||||
|
- "pg_hba.conf"
|
||||||
|
become: true
|
||||||
|
notify: "notification_reload_postgresql"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy postgresql certificate and key
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ item.value }}
|
||||||
|
dest: "{{ node['home_path'] }}/containers/postgresql/ssl/{{ item.name }}"
|
||||||
|
owner: "{{ postgresql_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "{{ item.mode }}"
|
||||||
|
loop:
|
||||||
|
- name: "ilnmors_root_ca.crt"
|
||||||
|
value: "{{ hostvars['console']['ca']['root']['crt'] }}"
|
||||||
|
mode: "0440"
|
||||||
|
- name: "postgresql.crt"
|
||||||
|
value: |
|
||||||
|
{{ hostvars['console']['postgresql']['crt'] | trim }}
|
||||||
|
{{ hostvars['console']['ca']['intermediate']['crt'] }}
|
||||||
|
mode: "0440"
|
||||||
|
- name: "postgresql.key"
|
||||||
|
value: "{{ hostvars['console']['postgresql']['key'] }}"
|
||||||
|
mode: "0400"
|
||||||
|
become: true
|
||||||
|
notify: "notification_reload_postgresql"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Check data directory empty
|
||||||
|
ansible.builtin.find:
|
||||||
|
paths: "{{ node['home_path'] }}/containers/postgresql/data/"
|
||||||
|
hidden: true
|
||||||
|
file_type: "any"
|
||||||
|
become: true
|
||||||
|
register: "is_data_dir_empty"
|
||||||
|
|
||||||
|
- name: Prepare initiating DB
|
||||||
|
when: is_data_dir_empty.matched == 0
|
||||||
|
become: true
|
||||||
|
block:
|
||||||
|
# `init/pg_cluster.sql` should be fetched from postgresql's backup directory before running initiating
|
||||||
|
- name: Deploy init cluster sql file
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/init/pg_cluster.sql"
|
||||||
|
dest: "{{ node['home_path'] }}/containers/postgresql/init/0_pg_cluster.sql"
|
||||||
|
owner: "{{ postgresql_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
|
||||||
|
- name: Deploy resoring data sql files
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/init/pg_{{ item }}.sql"
|
||||||
|
dest: "{{ node['home_path'] }}/containers/postgresql/init/{{ index_num + 1 }}_pg_{{ item }}.sql"
|
||||||
|
owner: "{{ postgresql_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
loop: "{{ connected_services }}"
|
||||||
|
loop_control:
|
||||||
|
index_var: index_num
|
||||||
|
- name: Set is_postgresql_init_run
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
is_postgresql_init_run: true
|
||||||
|
|
||||||
|
- name: Deploy container file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/postgresql.container.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/.config/containers/systemd/postgresql.container"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0644"
|
||||||
|
notify: "notification_restart_postgresql"
|
||||||
|
|
||||||
|
- name: Deploy backup service files
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/services/{{ item }}"
|
||||||
|
dest: "{{ node['home_path'] }}/.config/systemd/user/{{ item }}"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0644"
|
||||||
|
loop:
|
||||||
|
- "postgresql-cluster-backup.service"
|
||||||
|
- "postgresql-cluster-backup.timer"
|
||||||
|
- "postgresql-data-backup@.service"
|
||||||
|
- "postgresql-data-backup@.timer"
|
||||||
|
|
||||||
|
- name: Enable postgresql
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "postgresql.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
|
|
||||||
|
- name: Enable cluster backup timer
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "postgresql-cluster-backup.timer"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
|
|
||||||
|
- name: Enable data backup timer
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "postgresql-data-backup@{{ item }}.timer"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
|
loop: "{{ connected_services }}"
|
||||||
74
ansible/roles/infra/tasks/services/set_prometheus.yaml
Normal file
74
ansible/roles/infra/tasks/services/set_prometheus.yaml
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
---
|
||||||
|
- name: Set prometheus container subuid
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
prometheus_subuid: "165533" # nobody - 65534
|
||||||
|
|
||||||
|
- name: Create prometheus directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['home_path'] }}/containers/{{ item }}"
|
||||||
|
state: "directory"
|
||||||
|
owner: "{{ prometheus_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0770"
|
||||||
|
loop:
|
||||||
|
- "prometheus"
|
||||||
|
- "prometheus/etc"
|
||||||
|
- "prometheus/data"
|
||||||
|
- "prometheus/ssl"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy prometheus configuration file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/prometheus/etc/{{ item }}.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/containers/prometheus/etc/{{ item }}"
|
||||||
|
owner: "{{ prometheus_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
loop:
|
||||||
|
- "prometheus.yaml"
|
||||||
|
- "rules.yaml"
|
||||||
|
- "web-config.yaml"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_prometheus"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy prometheus certificate and key
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ item.value }}
|
||||||
|
dest: "{{ node['home_path'] }}/containers/prometheus/ssl/{{ item.name }}"
|
||||||
|
owner: "{{ prometheus_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "{{ item.mode }}"
|
||||||
|
loop:
|
||||||
|
- name: "ilnmors_root_ca.crt"
|
||||||
|
value: "{{ hostvars['console']['ca']['root']['crt'] }}"
|
||||||
|
mode: "0440"
|
||||||
|
- name: "prometheus.crt"
|
||||||
|
value: |
|
||||||
|
{{ hostvars['console']['prometheus']['crt'] | trim }}
|
||||||
|
{{ hostvars['console']['ca']['intermediate']['crt'] }}
|
||||||
|
mode: "0440"
|
||||||
|
- name: "prometheus.key"
|
||||||
|
value: "{{ hostvars['console']['prometheus']['key'] }}"
|
||||||
|
mode: "0400"
|
||||||
|
become: true
|
||||||
|
notify: "notification_restart_prometheus"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy container file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/prometheus/prometheus.container.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/.config/containers/systemd/prometheus.container"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0644"
|
||||||
|
notify: "notification_restart_prometheus"
|
||||||
|
|
||||||
|
- name: Enable prometheus
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "prometheus.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
63
ansible/roles/infra/tasks/services/set_x509-exporter.yaml
Normal file
63
ansible/roles/infra/tasks/services/set_x509-exporter.yaml
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
---
|
||||||
|
- name: Set x509-exporter container subuid
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
x509_exporter_subuid: "165533" # nobody - 65534
|
||||||
|
|
||||||
|
- name: Create x509-exporter directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ node['home_path'] }}/containers/{{ item }}"
|
||||||
|
state: "directory"
|
||||||
|
owner: "{{ x509_exporter_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0770"
|
||||||
|
loop:
|
||||||
|
- "x509-exporter"
|
||||||
|
- "x509-exporter/certs"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Deploy certificates
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
{{ item.value }}
|
||||||
|
dest: "{{ node['home_path'] }}/containers/x509-exporter/certs/{{ item.name }}"
|
||||||
|
owner: "{{ x509_exporter_subuid }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0440"
|
||||||
|
loop:
|
||||||
|
- name: "root.crt"
|
||||||
|
value: "{{ hostvars['console']['ca']['root']['crt'] }}"
|
||||||
|
- name: "intermediate.crt"
|
||||||
|
value: "{{ hostvars['console']['ca']['intermediate']['crt'] }}"
|
||||||
|
- name: "crowdsec.crt"
|
||||||
|
value: "{{ hostvars['console']['crowdsec']['crt'] }}"
|
||||||
|
- name: "blocky.crt"
|
||||||
|
value: "{{ hostvars['console']['blocky']['crt'] }}"
|
||||||
|
- name: "postgresql.crt"
|
||||||
|
value: "{{ hostvars['console']['postgresql']['crt'] }}"
|
||||||
|
- name: "ldap.crt"
|
||||||
|
value: "{{ hostvars['console']['ldap']['crt'] }}"
|
||||||
|
- name: "prometheus.crt"
|
||||||
|
value: "{{ hostvars['console']['prometheus']['crt'] }}"
|
||||||
|
- name: "loki.crt"
|
||||||
|
value: "{{ hostvars['console']['loki']['crt'] }}"
|
||||||
|
- name: "dsm.crt"
|
||||||
|
value: "{{ hostvars['console']['dsm']['crt'] }}"
|
||||||
|
become: true
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Deploy container file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/x509-exporter/x509-exporter.container.j2"
|
||||||
|
dest: "{{ node['home_path'] }}/.config/containers/systemd/x509-exporter.container"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0644"
|
||||||
|
notify: "notification_restart_x509-exporter"
|
||||||
|
|
||||||
|
- name: Enable x509-exporter.service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "x509-exporter.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
92
ansible/roles/vmm/tasks/node/set_libvirt.yaml
Normal file
92
ansible/roles/vmm/tasks/node/set_libvirt.yaml
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
---
|
||||||
|
- name: Add user in libvirt group
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ ansible_user }}"
|
||||||
|
state: "present"
|
||||||
|
groups: "libvirt, kvm, libvirt-qemu"
|
||||||
|
append: true
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Check libvirt directory
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "/var/lib/libvirt/{{ item }}"
|
||||||
|
loop:
|
||||||
|
- "images"
|
||||||
|
- "seeds"
|
||||||
|
register: "is_libvirt_dir"
|
||||||
|
|
||||||
|
- name: Create libvirt directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/var/lib/libvirt/{{ item.item }}"
|
||||||
|
state: "directory"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0711"
|
||||||
|
loop: "{{ is_libvirt_dir.results }}"
|
||||||
|
when: not item.stat.exists
|
||||||
|
become: true
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Set LIBVIRT_DEFAULT_URI
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: "{{ node['home_path'] }}/.bashrc"
|
||||||
|
state: "present"
|
||||||
|
line: "export LIBVIRT_DEFAULT_URI='qemu:///system'"
|
||||||
|
regexp: '^export LIBVIRT_DEFAULT_URI='
|
||||||
|
|
||||||
|
- name: Define virtual networks
|
||||||
|
community.libvirt.virt_net:
|
||||||
|
name: "{{ item }}"
|
||||||
|
xml: "{{ lookup('file', hostvars['console']['node']['config_path'] + '/services/systemd/vmm/libvirt/xml/networks/' + item + '.xml') }}"
|
||||||
|
uri: "qemu:///system"
|
||||||
|
command: "define"
|
||||||
|
loop:
|
||||||
|
- "wan-net"
|
||||||
|
- "lan-net"
|
||||||
|
|
||||||
|
- name: Start virtual networks
|
||||||
|
community.libvirt.virt_net:
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: "active"
|
||||||
|
uri: "qemu:///system"
|
||||||
|
autostart: true
|
||||||
|
loop:
|
||||||
|
- "wan-net"
|
||||||
|
- "lan-net"
|
||||||
|
|
||||||
|
- name: Autostart virtual networks
|
||||||
|
community.libvirt.virt_net:
|
||||||
|
name: "{{ item }}"
|
||||||
|
uri: "qemu:///system"
|
||||||
|
autostart: true
|
||||||
|
loop:
|
||||||
|
- "wan-net"
|
||||||
|
- "lan-net"
|
||||||
|
|
||||||
|
- name: Define virtual storage pool
|
||||||
|
community.libvirt.virt_pool:
|
||||||
|
name: "{{ item }}"
|
||||||
|
xml: "{{ lookup('file', hostvars['console']['node']['config_path'] + '/services/systemd/vmm/libvirt/xml/storages/' + item + '.xml') }}"
|
||||||
|
uri: "qemu:///system"
|
||||||
|
command: "define"
|
||||||
|
loop:
|
||||||
|
- "images-pool"
|
||||||
|
- "seeds-pool"
|
||||||
|
|
||||||
|
- name: Start virtual storage pool
|
||||||
|
community.libvirt.virt_pool:
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: "active"
|
||||||
|
uri: "qemu:///system"
|
||||||
|
loop:
|
||||||
|
- "images-pool"
|
||||||
|
- "seeds-pool"
|
||||||
|
|
||||||
|
- name: Autostart virtual storage pool
|
||||||
|
community.libvirt.virt_pool:
|
||||||
|
name: "{{ item }}"
|
||||||
|
uri: "qemu:///system"
|
||||||
|
autostart: true
|
||||||
|
loop:
|
||||||
|
- "images-pool"
|
||||||
|
- "seeds-pool"
|
||||||
59
ansible/roles/vmm/tasks/vm/create_seed.yaml
Normal file
59
ansible/roles/vmm/tasks/vm/create_seed.yaml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
---
|
||||||
|
# This task is located in vmm roles because of its attributes,
|
||||||
|
# but all process should be run in "console".
|
||||||
|
# At the playbook, `delegate_to: "console"` option is applyed by `apply:`.
|
||||||
|
- name: Create images directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}"
|
||||||
|
state: "directory"
|
||||||
|
owner: "console"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0700"
|
||||||
|
|
||||||
|
- name: Create temp meta-data
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
instance-id: vm-{{ target_vm }}
|
||||||
|
local-hostname: {{ target_vm }}
|
||||||
|
dest: "{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/meta-data"
|
||||||
|
owner: "console"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
register: "vm_meta_data"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Create temp user-data
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/vmm/libvirt/seeds/user-data.j2"
|
||||||
|
dest: "{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/user-data"
|
||||||
|
owner: "console"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
register: "vm_user_data"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Create temp network-config
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
network: {config: disabled}
|
||||||
|
dest: "{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/network-config"
|
||||||
|
owner: "console"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0600"
|
||||||
|
register: "vm_network_config"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Check seed.iso
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/seed.iso"
|
||||||
|
register: "is_seediso"
|
||||||
|
|
||||||
|
- name: Create seed.iso
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: |
|
||||||
|
cloud-localds -N {{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/network-config \
|
||||||
|
{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/seed.iso \
|
||||||
|
{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/user-data \
|
||||||
|
{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/meta-data
|
||||||
|
when: vm_meta_data.changed or vm_user_data.changed or vm_network_config.changed or not is_seediso.stat.exists
|
||||||
|
changed_when: true
|
||||||
55
ansible/roles/vmm/tasks/vm/deploy_vm_init.yaml
Normal file
55
ansible/roles/vmm/tasks/vm/deploy_vm_init.yaml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
- name: Check vm cloud-init
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "/var/lib/libvirt/images/debian-13.qcow2"
|
||||||
|
become: true
|
||||||
|
register: is_cloud_init_file
|
||||||
|
|
||||||
|
- name: Deploy vm cloud-init
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['data_path'] }}/images/debian-13-generic-amd64.qcow2"
|
||||||
|
dest: "/var/lib/libvirt/images/debian-13.qcow2"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0644"
|
||||||
|
force: false
|
||||||
|
become: true
|
||||||
|
when: not is_cloud_init_file.stat.exists
|
||||||
|
|
||||||
|
- name: Remote copy vm cloud-init file
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "/var/lib/libvirt/images/debian-13.qcow2"
|
||||||
|
dest: "/var/lib/libvirt/images/{{ target_vm }}.qcow2"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0644"
|
||||||
|
remote_src: true
|
||||||
|
force: false
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Check deployed cloud-init file info
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "qemu-img info /var/lib/libvirt/images/{{ target_vm }}.qcow2 --output json"
|
||||||
|
changed_when: false
|
||||||
|
failed_when:
|
||||||
|
- deployed_cloudfile_info.rc != 0
|
||||||
|
- ("lock") not in deployed_cloudfile_info.stderr
|
||||||
|
register: "deployed_cloudfile_info"
|
||||||
|
|
||||||
|
- name: Resize deployed cloud-init file
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "qemu-img resize /var/lib/libvirt/images/{{ target_vm }}.qcow2 {{ hostvars[target_vm]['vm']['storage'] }}G"
|
||||||
|
when:
|
||||||
|
- deployed_cloudfile_info.rc == 0
|
||||||
|
- (deployed_cloudfile_info.stdout | from_json)['virtual-size'] < (hostvars[target_vm]['vm']['storage'] | int * 1024 * 1024 * 1024)
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Deploy vm seed.iso
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/seed.iso"
|
||||||
|
dest: "/var/lib/libvirt/seeds/{{ target_vm }}_seed.iso"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0644"
|
||||||
|
become: true
|
||||||
|
when: deployed_cloudfile_info.rc == 0
|
||||||
24
ansible/roles/vmm/tasks/vm/register_vm.yaml
Normal file
24
ansible/roles/vmm/tasks/vm/register_vm.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
- name: Register VM xml file
|
||||||
|
community.libvirt.virt:
|
||||||
|
name: "{{ target_vm }}"
|
||||||
|
xml: |
|
||||||
|
{{ lookup('template', hostvars['console']['node']['config_path'] + '/services/systemd/vmm/libvirt/xml/vms/vms.xml.j2') }}
|
||||||
|
uri: "qemu:///system"
|
||||||
|
command: define
|
||||||
|
|
||||||
|
- name: Deploy VM systemd file
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/vmm/libvirt/services/{{ target_vm }}.service"
|
||||||
|
dest: "{{ node['home_path'] }}/.config/systemd/user/{{ target_vm }}.service"
|
||||||
|
owner: "{{ ansible_user }}"
|
||||||
|
group: "svadmins"
|
||||||
|
mode: "0400"
|
||||||
|
|
||||||
|
- name: Register VM service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "{{ target_vm }}.service"
|
||||||
|
state: "started"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
scope: "user"
|
||||||
38
config/node/app/nftables.conf.j2
Normal file
38
config/node/app/nftables.conf.j2
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/sbin/nft -f
|
||||||
|
flush ruleset
|
||||||
|
|
||||||
|
define NET4_SERVER = {{ hostvars['fw']['network4']['subnet']['server'] }}
|
||||||
|
define NET6_SERVER = {{ hostvars['fw']['network6']['subnet']['server'] }}
|
||||||
|
define HOSTS4_CONSOLE = { {{ hostvars['fw']['network4']['console'].values() | join(', ') }} }
|
||||||
|
define HOSTS6_CONSOLE = { {{ hostvars['fw']['network6']['console'].values() | join(', ') }} }
|
||||||
|
define PORTS_SSH = 22
|
||||||
|
|
||||||
|
table inet nat {
|
||||||
|
chain prerouting {
|
||||||
|
type nat hook prerouting priority dstnat; policy accept;
|
||||||
|
}
|
||||||
|
chain postrouting {
|
||||||
|
|
||||||
|
}
|
||||||
|
chain output {
|
||||||
|
type nat hook output priority dstnat; policy accept;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table inet filter {
|
||||||
|
chain input {
|
||||||
|
type filter hook input priority 0; policy drop;
|
||||||
|
ct state invalid drop comment "deny invalid connection"
|
||||||
|
ct state established, related accept comment "allow all connection already existing"
|
||||||
|
iifname "lo" accept comment "allow local connection"
|
||||||
|
meta l4proto { icmp, icmpv6 } accept comment "allow icmp connection"
|
||||||
|
ip saddr $HOSTS4_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv4 ssh connection: CONSOLE > APP"
|
||||||
|
ip6 saddr $HOSTS6_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv6 ssh connection: CONSOLE > APP"
|
||||||
|
}
|
||||||
|
chain forward {
|
||||||
|
type filter hook forward priority 0; policy drop;
|
||||||
|
}
|
||||||
|
chain output {
|
||||||
|
type filter hook output priority 0; policy accept;
|
||||||
|
}
|
||||||
|
}
|
||||||
48
config/node/auth/nftables.conf.j2
Normal file
48
config/node/auth/nftables.conf.j2
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/sbin/nft -f
|
||||||
|
flush ruleset
|
||||||
|
|
||||||
|
define NET4_SERVER = {{ hostvars['fw']['network4']['subnet']['server'] }}
|
||||||
|
define NET6_SERVER = {{ hostvars['fw']['network6']['subnet']['server'] }}
|
||||||
|
define HOSTS4_CONSOLE = { {{ hostvars['fw']['network4']['console'].values() | join(', ') }} }
|
||||||
|
define HOSTS6_CONSOLE = { {{ hostvars['fw']['network6']['console'].values() | join(', ') }} }
|
||||||
|
define PORTS_SSH = 22
|
||||||
|
define PORTS_HTTP = 80
|
||||||
|
define PORTS_HTTP_FORWARD = 2080
|
||||||
|
define PORTS_HTTPS = 443
|
||||||
|
define PORTS_HTTPS_FORWARD = 2443
|
||||||
|
|
||||||
|
table inet nat {
|
||||||
|
chain prerouting {
|
||||||
|
type nat hook prerouting priority dstnat; policy accept;
|
||||||
|
tcp dport $PORTS_HTTP dnat to :$PORTS_HTTP_FORWARD comment "dnat http ports to $PORTS_HTTP_FORWARD"
|
||||||
|
tcp dport $PORTS_HTTPS dnat to :$PORTS_HTTPS_FORWARD comment "dnat https ports to $PORTS_HTTPS_FORWARD"
|
||||||
|
}
|
||||||
|
chain postrouting {
|
||||||
|
|
||||||
|
}
|
||||||
|
chain output {
|
||||||
|
type nat hook output priority dstnat; policy accept;
|
||||||
|
oifname "lo" tcp dport $PORTS_HTTP dnat to :$PORTS_HTTP_FORWARD comment "dnat http ports to $PORTS_HTTP_FORWARD out of LOCALHOST"
|
||||||
|
oifname "lo" tcp dport $PORTS_HTTPS dnat to :$PORTS_HTTPS_FORWARD comment "dnat https ports to $PORTS_HTTPS_FORWARD out of LOCALHOST"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table inet filter {
|
||||||
|
chain input {
|
||||||
|
type filter hook input priority 0; policy drop;
|
||||||
|
ct state invalid drop comment "deny invalid connection"
|
||||||
|
ct state established, related accept comment "allow all connection already existing"
|
||||||
|
iifname "lo" accept comment "allow local connection: AUTH > AUTH"
|
||||||
|
meta l4proto { icmp, icmpv6 } accept comment "allow icmp connection: AUTH"
|
||||||
|
ip saddr $HOSTS4_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv4 ssh connection: CONSOLE > AUTH"
|
||||||
|
ip6 saddr $HOSTS6_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv6 ssh connection: CONSOLE > AUTH"
|
||||||
|
tcp dport $PORTS_HTTP_FORWARD ct original proto-dst $PORTS_HTTP accept comment "allow ipv4, 6 http connection: > AUTH"
|
||||||
|
tcp dport $PORTS_HTTPS_FORWARD ct original proto-dst $PORTS_HTTPS accept comment "allow ipv4, 6 https connection: > AUTH"
|
||||||
|
}
|
||||||
|
chain forward {
|
||||||
|
type filter hook forward priority 0; policy drop;
|
||||||
|
}
|
||||||
|
chain output {
|
||||||
|
type filter hook output priority 0; policy accept;
|
||||||
|
}
|
||||||
|
}
|
||||||
34
config/node/common/hosts.j2
Normal file
34
config/node/common/hosts.j2
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# localhost
|
||||||
|
127.0.0.1 {{ node['local_san'] }}
|
||||||
|
::1 {{ node['local_san'] }}
|
||||||
|
{% if node['name'] == 'console' %}
|
||||||
|
# Hosts IPv4
|
||||||
|
{{ hostvars['fw']['network4']['firewall']['server'] }} fw.ilnmors.internal
|
||||||
|
{{ hostvars['fw']['network4']['vmm']['client'] }} init.vmm.ilnmors.internal
|
||||||
|
{{ hostvars['fw']['network4']['vmm']['server'] }} vmm.ilnmors.internal
|
||||||
|
{{ hostvars['fw']['network4']['infra']['server'] }} infra.ilnmors.internal
|
||||||
|
{{ hostvars['fw']['network4']['auth']['server'] }} auth.ilnmors.internal
|
||||||
|
{{ hostvars['fw']['network4']['app']['server'] }} app.ilnmors.internal
|
||||||
|
# Hosts IPv6
|
||||||
|
{{ hostvars['fw']['network6']['firewall']['server'] }} fw.ilnmors.internal
|
||||||
|
{{ hostvars['fw']['network6']['vmm']['client'] }} init.vmm.ilnmors.internal
|
||||||
|
{{ hostvars['fw']['network6']['vmm']['server'] }} vmm.ilnmors.internal
|
||||||
|
{{ hostvars['fw']['network6']['infra']['server'] }} infra.ilnmors.internal
|
||||||
|
{{ hostvars['fw']['network6']['auth']['server'] }} auth.ilnmors.internal
|
||||||
|
{{ hostvars['fw']['network6']['app']['server'] }} app.ilnmors.internal
|
||||||
|
{% else %}
|
||||||
|
# IPv4
|
||||||
|
# Crowdsec, blocky, bind(fw)
|
||||||
|
{{ hostvars['fw']['network4']['firewall']['server'] }} ntp.ilnmors.internal crowdsec.ilnmors.internal
|
||||||
|
{{ hostvars['fw']['network4']['blocky']['server'] }} blocky.ilnmors.internal
|
||||||
|
{{ hostvars['fw']['network4']['bind']['server'] }} bind.ilnmors.internal
|
||||||
|
# DB, LDAP, CA, Prometheus, Loki, mail (infra)
|
||||||
|
{{ hostvars['fw']['network4']['infra']['server'] }} postgresql.ilnmors.internal ldap.ilnmors.internal prometheus.ilnmors.internal loki.ilnmors.internal mail.ilnmors.internal ca.ilnmors.internal
|
||||||
|
# IPv6
|
||||||
|
# Crowdsec, blocky, bind(fw)
|
||||||
|
{{ hostvars['fw']['network6']['firewall']['server'] }} ntp.ilnmors.internal crowdsec.ilnmors.internal
|
||||||
|
{{ hostvars['fw']['network6']['blocky']['server'] }} blocky.ilnmors.internal
|
||||||
|
{{ hostvars['fw']['network6']['bind']['server'] }} bind.ilnmors.internal
|
||||||
|
# DB, LDAP, CA, Prometheus, Loki, mail (infra)
|
||||||
|
{{ hostvars['fw']['network6']['infra']['server'] }} postgresql.ilnmors.internal ldap.ilnmors.internal prometheus.ilnmors.internal loki.ilnmors.internal mail.ilnmors.internal ca.ilnmors.internal
|
||||||
|
{% endif %}
|
||||||
5
config/node/common/networkd/00-eth0.link
Normal file
5
config/node/common/networkd/00-eth0.link
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[Match]
|
||||||
|
MACAddress={{ hostvars[target_vm]['vm']['lan_mac'] }}
|
||||||
|
|
||||||
|
[Link]
|
||||||
|
Name=eth0
|
||||||
13
config/node/common/networkd/20-eth0.network
Normal file
13
config/node/common/networkd/20-eth0.network
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[Match]
|
||||||
|
Name=eth0
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
# IPv4
|
||||||
|
Address={{ hostvars['fw']['network4'][target_vm]['server'] }}/24
|
||||||
|
Gateway={{ hostvars['fw']['network4']['firewall']['server'] }}
|
||||||
|
DNS={{ hostvars['fw']['network4']['blocky']['server'] }}
|
||||||
|
# IPv6
|
||||||
|
IPv6AcceptRA=false
|
||||||
|
Address={{ hostvars['fw']['network6'][target_vm]['server'] }}/64
|
||||||
|
Gateway={{ hostvars['fw']['network6']['firewall']['server'] }}
|
||||||
|
DNS={{ hostvars['fw']['network6']['blocky']['server'] }}
|
||||||
6
config/node/common/resolved/global.conf.j2
Normal file
6
config/node/common/resolved/global.conf.j2
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[Resolve]
|
||||||
|
{% if node['name'] in ['vmm', 'fw'] %}
|
||||||
|
DNS=1.1.1.2 1.0.0.2
|
||||||
|
DNS=2606:4700:4700::1112 2606:4700:4700::1002
|
||||||
|
{% endif %}
|
||||||
|
cache=false
|
||||||
2
config/node/common/ssh/host_certificate.conf
Normal file
2
config/node/common/ssh/host_certificate.conf
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
HostKey /etc/ssh/ssh_host_ed25519_key
|
||||||
|
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
|
||||||
1
config/node/common/ssh/prohibit_root.conf
Normal file
1
config/node/common/ssh/prohibit_root.conf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
PermitRootLogin no
|
||||||
1
config/node/common/ssh/ssh_ca.conf
Normal file
1
config/node/common/ssh/ssh_ca.conf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
TrustedUserCAKeys /etc/ssh/local_ssh_ca.pub
|
||||||
3
config/node/common/timesyncd/local-ntp.conf
Normal file
3
config/node/common/timesyncd/local-ntp.conf
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[Time]
|
||||||
|
NTP=ntp.ilnmors.internal
|
||||||
|
FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org
|
||||||
5
config/node/fw/networkd/00-fw-wan.link
Normal file
5
config/node/fw/networkd/00-fw-wan.link
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[Match]
|
||||||
|
MACAddress={{ hostvars['fw']['vm']['wan_mac'] }}
|
||||||
|
|
||||||
|
[Link]
|
||||||
|
Name=wan
|
||||||
5
config/node/fw/networkd/01-fw-client.link
Normal file
5
config/node/fw/networkd/01-fw-client.link
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[Match]
|
||||||
|
MACAddress={{ hostvars['fw']['vm']['lan_mac'] }}
|
||||||
|
|
||||||
|
[Link]
|
||||||
|
Name=client
|
||||||
6
config/node/fw/networkd/10-fw-server.netdev
Normal file
6
config/node/fw/networkd/10-fw-server.netdev
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[NetDev]
|
||||||
|
Name=server
|
||||||
|
Kind=vlan
|
||||||
|
|
||||||
|
[VLAN]
|
||||||
|
Id=10
|
||||||
6
config/node/fw/networkd/11-fw-user.netdev
Normal file
6
config/node/fw/networkd/11-fw-user.netdev
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[NetDev]
|
||||||
|
Name=user
|
||||||
|
Kind=vlan
|
||||||
|
|
||||||
|
[VLAN]
|
||||||
|
Id=20
|
||||||
16
config/node/fw/networkd/20-fw-wan.network
Normal file
16
config/node/fw/networkd/20-fw-wan.network
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[Match]
|
||||||
|
Name=wan
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
DHCP=true
|
||||||
|
IPv6AcceptRA=true
|
||||||
|
IPForward=true
|
||||||
|
RequiredForOnline=false
|
||||||
|
|
||||||
|
[DHCPv4]
|
||||||
|
UseDNS=false
|
||||||
|
|
||||||
|
[DHCPv6]
|
||||||
|
WithoutRA=solicit
|
||||||
|
PrefixDelegationHint=yes
|
||||||
|
UseDNS=false
|
||||||
16
config/node/fw/networkd/21-fw-client.network
Normal file
16
config/node/fw/networkd/21-fw-client.network
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[Match]
|
||||||
|
Name=client
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
# General
|
||||||
|
IPForward=true
|
||||||
|
IPv6SendRA=false
|
||||||
|
IPv6AcceptRA=false
|
||||||
|
VLAN=server
|
||||||
|
VLAN=user
|
||||||
|
# IPv4
|
||||||
|
Address={{ hostvars['fw']['network4']['firewall']['client'] }}/24
|
||||||
|
DNS={{ hostvars['fw']['network4']['blocky']['server'] }}
|
||||||
|
# IPv6
|
||||||
|
Address={{ hostvars['fw']['network6']['firewall']['client'] }}/64
|
||||||
|
DNS={{ hostvars['fw']['network6']['blocky']['server'] }}
|
||||||
24
config/node/fw/networkd/22-fw-server.network
Normal file
24
config/node/fw/networkd/22-fw-server.network
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
[Match]
|
||||||
|
Name=server
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
IPForward=true
|
||||||
|
IPv6SendRA=false
|
||||||
|
IPv6AcceptRA=false
|
||||||
|
# IPv4
|
||||||
|
Address={{ hostvars['fw']['network4']['firewall']['server'] }}/24
|
||||||
|
DNS={{ hostvars['fw']['network4']['blocky']['server'] }}
|
||||||
|
# IPv6
|
||||||
|
Address={{ hostvars['fw']['network6']['firewall']['server'] }}/64
|
||||||
|
DNS={{ hostvars['fw']['network6']['blocky']['server'] }}
|
||||||
|
|
||||||
|
[Address]
|
||||||
|
Address={{ hostvars['fw']['network4']['blocky']['server'] }}/24
|
||||||
|
[Address]
|
||||||
|
Address={{ hostvars['fw']['network4']['bind']['server'] }}/24
|
||||||
|
[Address]
|
||||||
|
Address={{ hostvars['fw']['network6']['blocky']['server'] }}/64
|
||||||
|
PreferredLifetime=0
|
||||||
|
[Address]
|
||||||
|
Address={{ hostvars['fw']['network6']['bind']['server'] }}/64
|
||||||
|
PreferredLifetime=0
|
||||||
25
config/node/fw/networkd/23-fw-user.network
Normal file
25
config/node/fw/networkd/23-fw-user.network
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
[Match]
|
||||||
|
Name=user
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
IPForward=true
|
||||||
|
IPv6PrefixDelegation=true
|
||||||
|
IPv6SendRA=true
|
||||||
|
IPv6SendRAExtension=false
|
||||||
|
# IPv4
|
||||||
|
Address={{ hostvars['fw']['network4']['firewall']['user'] }}/24
|
||||||
|
DNS={{ hostvars['fw']['network4']['blocky']['server'] }}
|
||||||
|
|
||||||
|
[IPv6PrefixDelegation]
|
||||||
|
SubnetId=20
|
||||||
|
# A-Flag: Enable SLAAC
|
||||||
|
AddressAutoconfiguration=true
|
||||||
|
OnLink=true
|
||||||
|
|
||||||
|
[IPv6SendRA]
|
||||||
|
# M-Flag: Client IP from DHCPv6
|
||||||
|
Managed=false
|
||||||
|
# O-Flag: Other information form DHCPv6
|
||||||
|
OtherInformation=false
|
||||||
|
EmitDNS=true
|
||||||
|
DNS={{ hostvars['fw']['network6']['blocky']['server'] }}
|
||||||
186
config/node/fw/nftables.conf.j2
Normal file
186
config/node/fw/nftables.conf.j2
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
#!/usr/sbin/nft -f
|
||||||
|
# Convention
|
||||||
|
# iifname oifname saddr daddr proto dport ct state action / Ellipsis if you can something
|
||||||
|
flush ruleset
|
||||||
|
|
||||||
|
define IF_WAN = "wan"
|
||||||
|
define IF_CLIENT = "client"
|
||||||
|
define IF_SERVER = "server"
|
||||||
|
define IF_USER = "user"
|
||||||
|
define IF_WG = "wg0"
|
||||||
|
|
||||||
|
define NET4_CLIENT = {{ hostvars['fw']['network4']['subnet']['client'] }}
|
||||||
|
define NET4_SERVER = {{ hostvars['fw']['network4']['subnet']['server'] }}
|
||||||
|
define NET4_USER = {{ hostvars['fw']['network4']['subnet']['user'] }}
|
||||||
|
define NET4_WG = {{ hostvars['fw']['network4']['subnet']['wg'] }}
|
||||||
|
define NET4_LLA = {{ hostvars['fw']['network4']['subnet']['lla'] }}
|
||||||
|
define NET4_RFC1918 = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 }
|
||||||
|
|
||||||
|
define NET6_CLIENT = {{ hostvars['fw']['network6']['subnet']['client'] }}
|
||||||
|
define NET6_SERVER = {{ hostvars['fw']['network6']['subnet']['server'] }}
|
||||||
|
define NET6_WG = {{ hostvars['fw']['network6']['subnet']['wg'] }}
|
||||||
|
define NET6_LLA = {{ hostvars['fw']['network6']['subnet']['lla'] }}
|
||||||
|
|
||||||
|
define HOSTS4_FW = { {{ hostvars['fw']['network4']['firewall'].values() | join(', ') }} }
|
||||||
|
define HOSTS4_BLOCKY = {{ hostvars['fw']['network4']['blocky']['server'] }}
|
||||||
|
define HOSTS4_BIND = {{ hostvars['fw']['network4']['bind']['server'] }}
|
||||||
|
define HOSTS4_CONSOLE = { {{ hostvars['fw']['network4']['console'].values() | join(', ') }} }
|
||||||
|
define HOSTS4_VMM = { {{ hostvars['fw']['network4']['vmm'].values() | join(', ') }} }
|
||||||
|
define HOSTS4_INFRA = {{ hostvars['fw']['network4']['infra']['server'] }}
|
||||||
|
define HOSTS4_AUTH = {{ hostvars['fw']['network4']['auth']['server'] }}
|
||||||
|
define HOSTS4_APP = {{ hostvars['fw']['network4']['app']['server'] }}
|
||||||
|
define HOSTS4_NAS = {{ hostvars['fw']['network4']['nas']['client'] }}
|
||||||
|
|
||||||
|
define HOSTS6_FW = { {{ hostvars['fw']['network6']['firewall'].values() | join(', ') }} }
|
||||||
|
define HOSTS6_BLOCKY = {{ hostvars['fw']['network6']['blocky']['server'] }}
|
||||||
|
define HOSTS6_BIND = {{ hostvars['fw']['network6']['bind']['server'] }}
|
||||||
|
define HOSTS6_CONSOLE = { {{ hostvars['fw']['network6']['console'].values() | join(', ') }} }
|
||||||
|
define HOSTS6_VMM = { {{ hostvars['fw']['network6']['vmm'].values() | join(', ') }} }
|
||||||
|
define HOSTS6_INFRA = {{ hostvars['fw']['network6']['infra']['server'] }}
|
||||||
|
define HOSTS6_AUTH = {{ hostvars['fw']['network6']['auth']['server'] }}
|
||||||
|
define HOSTS6_APP = {{ hostvars['fw']['network6']['app']['server'] }}
|
||||||
|
define HOSTS6_NAS = {{ hostvars['fw']['network6']['nas']['client'] }}
|
||||||
|
|
||||||
|
define PORTS_SSH = 22
|
||||||
|
define PORTS_WEB = { 80, 443 }
|
||||||
|
define PORTS_DHCP = { 67, 68, 546, 547 }
|
||||||
|
define PORTS_DNS = 53
|
||||||
|
define PORTS_NTP = 123
|
||||||
|
define PORTS_VPN = 11290
|
||||||
|
define PORTS_CROWDSEC = 8080
|
||||||
|
define PORTS_NAS = { 5000, 5001 }
|
||||||
|
define PORTS_KOPIA = 51515
|
||||||
|
|
||||||
|
table inet nat {
|
||||||
|
chain prerouting {
|
||||||
|
type nat hook prerouting priority dstnat; policy accept;
|
||||||
|
# After prerouting, accept forward chain WAN
|
||||||
|
iifname $IF_WAN meta nfproto ipv4 tcp dport $PORTS_WEB dnat to $HOSTS4_AUTH comment "DNAT44 ipv4 web connection: WAN > FW > SERVER AUTH"
|
||||||
|
iifname $IF_WAN meta nfproto ipv6 tcp dport $PORTS_WEB dnat to $HOSTS6_AUTH comment "DNAT66 ipv6 web connection: WAN > FW > SERVER AUTH"
|
||||||
|
}
|
||||||
|
chain postrouting {
|
||||||
|
type nat hook postrouting priority srcnat; policy accept;
|
||||||
|
# Masquerade the packet
|
||||||
|
oifname $IF_WAN meta nfproto ipv4 masquerade comment "masquerade ipv4 wan connection: > FW > WAN"
|
||||||
|
# $IF_USER uses GUA on IPv6
|
||||||
|
iifname { $IF_CLIENT, $IF_SERVER, $IF_WG } oifname $IF_WAN meta nfproto ipv6 masquerade comment "masquerade ipv6 wan connection: CLIENT/SERVER/WG > FW > WAN"
|
||||||
|
}
|
||||||
|
chain output {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table inet filter {
|
||||||
|
set crowdsec-blacklists {
|
||||||
|
type ipv4_addr
|
||||||
|
flags timeout
|
||||||
|
}
|
||||||
|
set crowdsec6-blacklists {
|
||||||
|
type ipv6_addr
|
||||||
|
flags timeout
|
||||||
|
}
|
||||||
|
chain global {
|
||||||
|
# invalid packets
|
||||||
|
ct state invalid drop comment "deny invalid connection"
|
||||||
|
# crowdsec
|
||||||
|
ip saddr @crowdsec-blacklists counter drop comment "deny all crowdsec blacklist"
|
||||||
|
ip6 saddr @crowdsec6-blacklists counter drop comment "deny all ipv6 crowdsec blacklist"
|
||||||
|
# fw
|
||||||
|
ct state established, related accept comment "allow all connection already existing"
|
||||||
|
ip6 saddr $NET6_LLA return comment "return ipv6 linklocaladdress to input and forward chain"
|
||||||
|
iifname $IF_WAN tcp dport $PORTS_SSH drop comment "deny ssh connection: WAN !> "
|
||||||
|
iifname $IF_WAN udp dport $PORTS_DNS drop comment "deny udp dns connection: WAN !> "
|
||||||
|
iifname $IF_WAN tcp dport $PORTS_DNS drop comment "deny tcp dns connection: WAN !> "
|
||||||
|
iifname $IF_WAN icmp type echo-request drop comment "deny icmp echo connection (Ping): WAN !>"
|
||||||
|
iifname $IF_WAN icmpv6 type echo-request drop comment "deny icmpv6 echo connection (Ping): WAN !>"
|
||||||
|
iifname $IF_WAN meta l4proto { icmp, icmpv6 } accept comment "allow icmp, icmpv6 connection: WAN >"
|
||||||
|
iifname $IF_WAN ip saddr $NET4_RFC1918 drop comment "deny ipv4 all connection: WAN RFC1918 !>"
|
||||||
|
iifname $IF_WAN ip saddr $NET4_LLA drop comment "deny ipv4 all connection: WAN APIPA(bogon) !>"
|
||||||
|
iifname { $IF_CLIENT, $IF_SERVER, $IF_USER } udp dport $PORTS_DHCP accept comment "allow dhcp4, dhcp6 connection: CLIENT/SERVER/USER > FW"
|
||||||
|
iifname $IF_CLIENT ip saddr != $NET4_CLIENT drop comment "deny ipv4 all connection: CLIENT !CLIENT !>"
|
||||||
|
iifname $IF_CLIENT ip6 saddr != $NET6_CLIENT drop comment "deny ipv6 all connection: CLIENT !CLIENT !>"
|
||||||
|
iifname $IF_SERVER ip saddr != $NET4_SERVER drop comment "deny ipv4 all connection: SERVER !SERVER !>"
|
||||||
|
iifname $IF_SERVER ip6 saddr != $NET6_SERVER drop comment "deny ipv6 all connection: SERVER !SERVER !>"
|
||||||
|
# IF_USER uses GUA on ipv6, so ipv6 rule is not needed
|
||||||
|
iifname $IF_USER ip saddr != $NET4_USER drop comment "deny ipv4 all connection: USER !USER !>"
|
||||||
|
iifname $IF_WG ip saddr != $NET4_WG drop comment "deny all ipv4 connection: WG !WG !>"
|
||||||
|
iifname $IF_WG ip6 saddr != $NET6_WG drop comment "deny all ipv6 connection: WG !WG !>"
|
||||||
|
}
|
||||||
|
chain input {
|
||||||
|
type filter hook input priority filter; policy drop;
|
||||||
|
jump global comment "set global condition"
|
||||||
|
iifname "lo" accept comment "allow local connection: FW > FW"
|
||||||
|
udp dport $PORTS_VPN accept comment "allow vpn connection: > FW"
|
||||||
|
iifname { $IF_CLIENT, $IF_SERVER, $IF_USER, $IF_WG } meta l4proto { icmp, icmpv6 } accept comment "allow icmp, icmpv6 connection: CLIENT/SERVER/USER/WG > FW"
|
||||||
|
iifname { $IF_CLIENT, $IF_SERVER, $IF_USER, $IF_WG } udp dport $PORTS_NTP accept comment "allow ntp connection: CLIENT/SERVER/USER/WG > FW"
|
||||||
|
# Global chain contains "WAN !> :SSH_PORT"
|
||||||
|
ip saddr $HOSTS4_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv4 ssh connection: CONSOLE > FW"
|
||||||
|
ip6 saddr $HOSTS6_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv6 ssh connection: CONSOLE > FW"
|
||||||
|
ip saddr { $HOSTS4_VMM, $HOSTS4_INFRA, $HOSTS4_AUTH, $HOSTS4_APP } tcp dport $PORTS_CROWDSEC accept comment "allow ipv4 crowdsec lapi connection: SERVER > FW"
|
||||||
|
ip6 saddr { $HOSTS6_VMM, $HOSTS6_INFRA, $HOSTS6_AUTH, $HOSTS6_APP } tcp dport $PORTS_CROWDSEC accept comment "allow ipv6 crowdsec lapi connection: SERVER > FW"
|
||||||
|
# Global chain contains "WAN !> :DNS_PORT"
|
||||||
|
ip daddr $HOSTS4_BLOCKY udp dport $PORTS_DNS accept comment "allow ipv4 udp dns connection: !WAN > SERVER BLOCKY(FW)"
|
||||||
|
ip daddr $HOSTS4_BLOCKY tcp dport $PORTS_DNS accept comment "allow ipv4 tcp dns connection: !WAN > SERVER BLOCKY(FW)"
|
||||||
|
ip6 daddr $HOSTS6_BLOCKY udp dport $PORTS_DNS accept comment "allow ipv6 udp dns connection: !WAN > SERVER BLOCKY(FW)"
|
||||||
|
ip6 daddr $HOSTS6_BLOCKY tcp dport $PORTS_DNS accept comment "allow ipv6 tcp dns connection: !WAN > SERVER BLOCKY(FW)"
|
||||||
|
ip saddr { $HOSTS4_INFRA, $HOSTS4_AUTH, $HOSTS4_APP } ip daddr $HOSTS4_BIND udp dport $PORTS_DNS accept comment "allow ipv4 udp dns connection (nsupdate): SERVER INFRA/AUTH/APP > BIND9(FW)"
|
||||||
|
ip saddr { $HOSTS4_INFRA, $HOSTS4_AUTH, $HOSTS4_APP } ip daddr $HOSTS4_BIND tcp dport $PORTS_DNS accept comment "allow ipv4 tcp dns connection (nsupdate): SERVER INFRA/AUTH/APP > BIND9(FW)"
|
||||||
|
ip6 saddr { $HOSTS6_INFRA, $HOSTS6_AUTH, $HOSTS6_APP } ip6 daddr $HOSTS6_BIND udp dport $PORTS_DNS accept comment "allow ipv6 udp dns connection (nsupdate): SERVER INFRA/AUTH/APP > BIND9(FW)"
|
||||||
|
ip6 saddr { $HOSTS6_INFRA, $HOSTS6_AUTH, $HOSTS6_APP } ip6 daddr $HOSTS6_BIND tcp dport $PORTS_DNS accept comment "allow ipv6 tcp dns connection (nsupdate): SERVER INFRA/AUTH/APP > BIND9(FW)"
|
||||||
|
}
|
||||||
|
chain forward {
|
||||||
|
type filter hook forward priority filter; policy drop;
|
||||||
|
|
||||||
|
jump global comment "set global condition"
|
||||||
|
# ICMP
|
||||||
|
ip saddr $HOSTS4_CONSOLE meta l4proto icmp accept comment "allow icmp connection: CONSOLE > FW >"
|
||||||
|
ip6 saddr $HOSTS6_CONSOLE meta l4proto icmpv6 accept comment "allow icmpv6 connection: CONSOLE > FW >"
|
||||||
|
# SSH connection
|
||||||
|
ip saddr $HOSTS4_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv4 ssh connection: CONSOLE > FW >"
|
||||||
|
ip6 saddr $HOSTS6_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv6 ssh connection: CONSOLE > FW >"
|
||||||
|
# Reverse proxy (WAN)
|
||||||
|
oifname $IF_SERVER ip daddr $HOSTS4_AUTH tcp dport $PORTS_WEB accept comment "allow ipv4 web connection: > FW > SERVER AUTH"
|
||||||
|
oifname $IF_SERVER ip6 daddr $HOSTS6_AUTH tcp dport $PORTS_WEB accept comment "allow ipv6 web connection: > FW > SERVER AUTH"
|
||||||
|
# Reverse proxy (SERVER)
|
||||||
|
oifname $IF_SERVER ip saddr $HOSTS4_CONSOLE ip daddr { $HOSTS4_INFRA, $HOSTS4_APP } tcp dport $PORTS_WEB accept comment "allow ipv4 web connection: CONSOLE > FW > SERVER INFRA/APP"
|
||||||
|
oifname $IF_SERVER ip6 saddr $HOSTS6_CONSOLE ip6 daddr { $HOSTS6_INFRA, $HOSTS6_APP } tcp dport $PORTS_WEB accept comment "allow ipv6 web connection: CONSOLE > FW > SERVER INFRA/APP"
|
||||||
|
# Kopia/NAS Console > NAS
|
||||||
|
oifname $IF_CLIENT ip saddr $HOSTS4_CONSOLE ip daddr $HOSTS4_NAS tcp dport { $PORTS_NAS, $PORTS_KOPIA } accept comment "allow ipv4 web connection (DSM, KOPIA): CONSOLE > FW > CLIENT NAS"
|
||||||
|
oifname $IF_CLIENT ip6 saddr $HOSTS6_CONSOLE ip6 daddr $HOSTS6_NAS tcp dport { $PORTS_NAS, $PORTS_KOPIA } accept comment "allow ipv6 web connection (DSM, KOPIA): CONSOLE > FW > CLIENT NAS"
|
||||||
|
|
||||||
|
iifname $IF_WAN jump wan comment "set WAN interface rules"
|
||||||
|
iifname $IF_CLIENT jump client comment "set CLIENT interface rules"
|
||||||
|
iifname $IF_SERVER jump server comment "set SERVER interface rules"
|
||||||
|
iifname $IF_USER jump user comment "set USER interface rules"
|
||||||
|
iifname $IF_WG jump wg comment "set WG interface rules"
|
||||||
|
}
|
||||||
|
chain wan {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
chain client {
|
||||||
|
oifname $IF_WAN ip saddr { $HOSTS4_CONSOLE, $HOSTS4_NAS } accept comment "allow ipv4 internet connection: CLIENT CONSOLE/NAS > FW > WAN"
|
||||||
|
oifname $IF_WAN ip6 saddr { $HOSTS6_CONSOLE, $HOSTS6_NAS } accept comment "allow ipv6 internet connection: CLIENT CONSOLE/NAS > FW > WAN"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
chain server {
|
||||||
|
# reverse proxy AUTH > NAS
|
||||||
|
oifname $IF_CLIENT ip saddr $HOSTS4_AUTH ip daddr $HOSTS4_NAS tcp dport $PORTS_NAS accept comment "allow ipv4 web connection(DSM): SERVER AUTH > FW > CLIENT NAS"
|
||||||
|
oifname $IF_CLIENT ip6 saddr $HOSTS6_AUTH ip6 daddr $HOSTS6_NAS tcp dport $PORTS_NAS accept comment "allow ipv6 web connection(DSM): SERVER AUTH > FW > CLIENT NAS"
|
||||||
|
# Kopia INFRA, APP > NAS
|
||||||
|
oifname $IF_CLIENT ip saddr { $HOSTS4_INFRA, $HOSTS4_APP } ip daddr $HOSTS4_NAS tcp dport $PORTS_KOPIA accept comment "allow ipv4 web connection(kopia): SERVER INFRA/APP > FW > CLIENT NAS"
|
||||||
|
oifname $IF_CLIENT ip6 saddr { $HOSTS6_INFRA, $HOSTS6_APP } ip6 daddr $HOSTS6_NAS tcp dport $PORTS_KOPIA accept comment "allow ipv6 web connection(kopia): SERVER INFRA/APP > FW > CLIENT NAS"
|
||||||
|
oifname $IF_WAN ip saddr { $HOSTS4_VMM, $HOSTS4_INFRA, $HOSTS4_AUTH, $HOSTS4_APP } accept comment "allow ipv4 internet connection: SERVER VMM/INFRA/AUTH/APP > FW > WAN"
|
||||||
|
oifname $IF_WAN ip6 saddr { $HOSTS6_VMM, $HOSTS6_INFRA, $HOSTS6_AUTH, $HOSTS6_APP } accept comment "allow ipv6 internet connection: SERVER VMM/INFRA/AUTH/APP > FW > WAN"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
chain user {
|
||||||
|
oifname $IF_WAN accept comment "allow internet connection: USER > FW > WAN"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
chain wg {
|
||||||
|
oifname $IF_WAN accept comment "allow internet connection: WG > FW > WAN"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
chain output {
|
||||||
|
type filter hook output priority filter; policy accept;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
config/node/fw/wireguard/30-fw-wg0.netdev
Normal file
10
config/node/fw/wireguard/30-fw-wg0.netdev
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[NetDev]
|
||||||
|
Name=wg0
|
||||||
|
Kind=wireguard
|
||||||
|
[WireGuard]
|
||||||
|
ListenPort=11290
|
||||||
|
PrivateKey={{ hostvars['console']['wireguard']['server']['private_key'] }}
|
||||||
|
[WireGuardPeer]
|
||||||
|
PublicKey={{ hostvars['console']['wireguard']['console']['public_key'] }}
|
||||||
|
PresharedKey={{ hostvars['console']['wireguard']['console']['preshared_key'] }}
|
||||||
|
AllowedIPs={{ hostvars['fw']["network4"]["console"]["wg"] }}/32, {{ hostvars['fw']["network6"]["console"]["wg"] }}/128
|
||||||
6
config/node/fw/wireguard/31-fw-wg0.network
Normal file
6
config/node/fw/wireguard/31-fw-wg0.network
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[Match]
|
||||||
|
Name=wg0
|
||||||
|
[Network]
|
||||||
|
Address={{ hostvars['fw']["network4"]["firewall"]["wg"] }}/24
|
||||||
|
Address={{ hostvars['fw']["network6"]["firewall"]["wg"] }}/64
|
||||||
|
IPForward=yes
|
||||||
70
config/node/infra/nftables.conf.j2
Normal file
70
config/node/infra/nftables.conf.j2
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/sbin/nft -f
|
||||||
|
# Convention
|
||||||
|
# iifname oifname saddr daddr proto dport ct state action / Ellipsis if you can something
|
||||||
|
flush ruleset
|
||||||
|
|
||||||
|
define NET4_SERVER = {{ hostvars['fw']['network4']['subnet']['server'] }}
|
||||||
|
define NET6_SERVER = {{ hostvars['fw']['network6']['subnet']['server'] }}
|
||||||
|
define HOSTS4_CONSOLE = { {{ hostvars['fw']['network4']['console'].values() | join(', ') }} }
|
||||||
|
define HOSTS6_CONSOLE = { {{ hostvars['fw']['network6']['console'].values() | join(', ') }} }
|
||||||
|
define PORTS_SSH = 22
|
||||||
|
define PORTS_DB = 5432
|
||||||
|
define PORTS_CA = 9000
|
||||||
|
define PORTS_LDAPS = 636
|
||||||
|
define PORTS_LDAPS_FORWARD = 6360
|
||||||
|
define PORTS_HTTP = 80
|
||||||
|
define PORTS_HTTP_FORWARD = 2080
|
||||||
|
define PORTS_HTTPS = 443
|
||||||
|
define PORTS_HTTPS_FORWARD = 2443
|
||||||
|
define PORTS_PROMETHEUS = 9090
|
||||||
|
define PORTS_LOKI = 3100
|
||||||
|
|
||||||
|
table inet nat {
|
||||||
|
chain prerouting {
|
||||||
|
type nat hook prerouting priority dstnat; policy accept;
|
||||||
|
tcp dport $PORTS_HTTP dnat to :$PORTS_HTTP_FORWARD comment "DNAT http ports to $PORTS_HTTP_FORWARD"
|
||||||
|
tcp dport $PORTS_HTTPS dnat to :$PORTS_HTTPS_FORWARD comment "DNAT https ports to $PORTS_HTTPS_FORWARD"
|
||||||
|
tcp dport $PORTS_LDAPS dnat to :$PORTS_LDAPS_FORWARD comment "DNAT ldaps ports to $PORTS_LDAPS_FORWARD"
|
||||||
|
}
|
||||||
|
chain postrouting {
|
||||||
|
|
||||||
|
}
|
||||||
|
chain output {
|
||||||
|
type nat hook output priority dstnat; policy accept;
|
||||||
|
oifname "lo" tcp dport $PORTS_HTTP dnat to :$PORTS_HTTP_FORWARD comment "DNAT http ports to $PORTS_HTTP_FORWARD out of LOCALHOST"
|
||||||
|
oifname "lo" tcp dport $PORTS_HTTPS dnat to :$PORTS_HTTPS_FORWARD comment "DNAT https ports to $PORTS_HTTPS_FORWARD out of LOCALHOST"
|
||||||
|
oifname "lo" tcp dport $PORTS_LDAPS dnat to :$PORTS_LDAPS_FORWARD comment "DNAT ldaps ports to $PORTS_LDAPS_FORWARD out of LOCALHOST"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table inet filter {
|
||||||
|
chain input {
|
||||||
|
type filter hook input priority 0; policy drop;
|
||||||
|
ct state invalid drop comment "deny invalid connection"
|
||||||
|
ct state established, related accept comment "allow all connection already existing"
|
||||||
|
iifname "lo" accept comment "allow local connection: INFRA > INFRA"
|
||||||
|
meta l4proto { icmp, icmpv6 } accept comment "allow icmp connection: > INFRA"
|
||||||
|
ip saddr $HOSTS4_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv4 ssh connection: CONSOLE > INFRA"
|
||||||
|
ip6 saddr $HOSTS6_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv6 ssh connection: CONSOLE > INFRA"
|
||||||
|
ip saddr $NET4_SERVER tcp dport $PORTS_CA accept comment "allow ipv4 ca connection: SERVER > INFRA"
|
||||||
|
ip6 saddr $NET6_SERVER tcp dport $PORTS_CA accept comment "allow ipv6 ca connection: SERVER > INFRA"
|
||||||
|
ip saddr $NET4_SERVER tcp dport $PORTS_DB accept comment "allow ipv4 db connection: SERVER > INFRA"
|
||||||
|
ip6 saddr $NET6_SERVER tcp dport $PORTS_DB accept comment "allow ipv6 db connection: SERVER > INFRA"
|
||||||
|
ip saddr $HOSTS4_CONSOLE tcp dport $PORTS_HTTP_FORWARD ct original proto-dst $PORTS_HTTP accept comment "allow ipv4 http connection: CONSOLE > INFRA"
|
||||||
|
ip6 saddr $HOSTS6_CONSOLE tcp dport $PORTS_HTTP_FORWARD ct original proto-dst $PORTS_HTTP accept comment "allow ipv6 http connection: CONSOLE > INFRA"
|
||||||
|
ip saddr $HOSTS4_CONSOLE tcp dport $PORTS_HTTPS_FORWARD ct original proto-dst $PORTS_HTTPS accept comment "allow ipv4 https connection: CONSOLE > INFRA"
|
||||||
|
ip6 saddr $HOSTS6_CONSOLE tcp dport $PORTS_HTTPS_FORWARD ct original proto-dst $PORTS_HTTPS accept comment "allow ipv6 https connection: CONSOLE > INFRA"
|
||||||
|
ip saddr $NET4_SERVER tcp dport $PORTS_LDAPS_FORWARD ct original proto-dst $PORTS_LDAPS accept comment "allow ipv4 ldaps connection: SERVER > INFRA"
|
||||||
|
ip6 saddr $NET6_SERVER tcp dport $PORTS_LDAPS_FORWARD ct original proto-dst $PORTS_LDAPS accept comment "allow ipv6 ldaps connection: SERVER > INFRA"
|
||||||
|
ip saddr $NET4_SERVER tcp dport $PORTS_PROMETHEUS accept comment "allow ipv4 prometheus connection: SERVER > INFRA"
|
||||||
|
ip6 saddr $NET6_SERVER tcp dport $PORTS_PROMETHEUS accept comment "allow ipv6 prometheus connection: SERVER > INFRA"
|
||||||
|
ip saddr $NET4_SERVER tcp dport $PORTS_LOKI accept comment "allow ipv4 loki connection: SERVER > INFRA"
|
||||||
|
ip6 saddr $NET6_SERVER tcp dport $PORTS_LOKI accept comment "allow ipv6 loki connection: SERVER > INFRA"
|
||||||
|
}
|
||||||
|
chain forward {
|
||||||
|
type filter hook forward priority 0; policy drop;
|
||||||
|
}
|
||||||
|
chain output {
|
||||||
|
type filter hook output priority 0; policy accept;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
config/node/vmm/networkd/00-vmm-eth0.link
Normal file
5
config/node/vmm/networkd/00-vmm-eth0.link
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[Match]
|
||||||
|
MACAddress=c8:ff:bf:05:aa:b0
|
||||||
|
|
||||||
|
[Link]
|
||||||
|
Name=eth0
|
||||||
5
config/node/vmm/networkd/01-vmm-eth1.link
Normal file
5
config/node/vmm/networkd/01-vmm-eth1.link
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[Match]
|
||||||
|
MACAddress=c8:ff:bf:05:aa:b1
|
||||||
|
|
||||||
|
[Link]
|
||||||
|
Name=eth1
|
||||||
3
config/node/vmm/networkd/10-vmm-br0.netdev
Normal file
3
config/node/vmm/networkd/10-vmm-br0.netdev
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[NetDev]
|
||||||
|
Name=br0
|
||||||
|
Kind=bridge
|
||||||
7
config/node/vmm/networkd/11-vmm-br1.netdev
Normal file
7
config/node/vmm/networkd/11-vmm-br1.netdev
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[NetDev]
|
||||||
|
Name=br1
|
||||||
|
Kind=bridge
|
||||||
|
|
||||||
|
[Bridge]
|
||||||
|
VLANFiltering=true
|
||||||
|
DefaultPVID=1
|
||||||
6
config/node/vmm/networkd/12-vmm-vlan1.netdev
Normal file
6
config/node/vmm/networkd/12-vmm-vlan1.netdev
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[NetDev]
|
||||||
|
Name=vlan1
|
||||||
|
Kind=vlan
|
||||||
|
|
||||||
|
[VLAN]
|
||||||
|
Id=1
|
||||||
6
config/node/vmm/networkd/13-vmm-vlan10.netdev
Normal file
6
config/node/vmm/networkd/13-vmm-vlan10.netdev
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[NetDev]
|
||||||
|
Name=vlan10
|
||||||
|
Kind=vlan
|
||||||
|
|
||||||
|
[VLAN]
|
||||||
|
Id=10
|
||||||
6
config/node/vmm/networkd/14-vmm-vlan20.netdev
Normal file
6
config/node/vmm/networkd/14-vmm-vlan20.netdev
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[NetDev]
|
||||||
|
Name=vlan20
|
||||||
|
Kind=vlan
|
||||||
|
|
||||||
|
[VLAN]
|
||||||
|
Id=20
|
||||||
6
config/node/vmm/networkd/20-vmm-eth0.network
Normal file
6
config/node/vmm/networkd/20-vmm-eth0.network
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[Match]
|
||||||
|
Name=eth0
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
Bridge=br0
|
||||||
|
LinkLocalAddressing=false
|
||||||
15
config/node/vmm/networkd/21-vmm-eth1.network
Normal file
15
config/node/vmm/networkd/21-vmm-eth1.network
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
[Match]
|
||||||
|
Name=eth1
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
Bridge=br1
|
||||||
|
LinkLocalAddressing=false
|
||||||
|
|
||||||
|
[BridgeVLAN]
|
||||||
|
VLAN=1
|
||||||
|
PVID=true
|
||||||
|
EgressUntagged=true
|
||||||
|
|
||||||
|
[BridgeVLAN]
|
||||||
|
VLAN=10
|
||||||
|
VLAN=20
|
||||||
5
config/node/vmm/networkd/22-vmm-br0.network
Normal file
5
config/node/vmm/networkd/22-vmm-br0.network
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[Match]
|
||||||
|
Name=br0
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
LinkLocalAddressing=false
|
||||||
17
config/node/vmm/networkd/23-vmm-br1.network
Normal file
17
config/node/vmm/networkd/23-vmm-br1.network
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
[Match]
|
||||||
|
Name=br1
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
VLAN=vlan1
|
||||||
|
VLAN=vlan10
|
||||||
|
VLAN=vlan20
|
||||||
|
LinkLocalAddressing=false
|
||||||
|
|
||||||
|
[BridgeVLAN]
|
||||||
|
VLAN=1
|
||||||
|
PVID=yes
|
||||||
|
EgressUntagged=true
|
||||||
|
|
||||||
|
[BridgeVLAN]
|
||||||
|
VLAN=10
|
||||||
|
VLAN=20
|
||||||
28
config/node/vmm/networkd/24-vmm-vlan1.network
Normal file
28
config/node/vmm/networkd/24-vmm-vlan1.network
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
[Match]
|
||||||
|
Name=vlan1
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
# IPv4
|
||||||
|
Address=192.168.1.10/24
|
||||||
|
# IPv6
|
||||||
|
Address=fd00:1::10/64
|
||||||
|
|
||||||
|
[RoutingPolicyRule]
|
||||||
|
From=192.168.1.10/32
|
||||||
|
Table=1
|
||||||
|
Priority=100
|
||||||
|
|
||||||
|
[Route]
|
||||||
|
Destination=192.168.1.0/24
|
||||||
|
Scope=link
|
||||||
|
Table=1
|
||||||
|
|
||||||
|
[RoutingPolicyRule]
|
||||||
|
From=fd00:1::10/128
|
||||||
|
Table=61
|
||||||
|
Priority=100
|
||||||
|
|
||||||
|
[Route]
|
||||||
|
Destination=fd00:1::/64
|
||||||
|
Scope=link
|
||||||
|
Table=61
|
||||||
32
config/node/vmm/networkd/25-vmm-vlan10.network
Normal file
32
config/node/vmm/networkd/25-vmm-vlan10.network
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
[Match]
|
||||||
|
Name=vlan10
|
||||||
|
[Network]
|
||||||
|
RequiredForOnline=false
|
||||||
|
# IPv4
|
||||||
|
Address=192.168.10.10/24
|
||||||
|
Gateway=192.168.10.1
|
||||||
|
DNS=192.168.10.2
|
||||||
|
# IPv6
|
||||||
|
Address=fd00:10::10/64
|
||||||
|
Gateway=fd00:10::1
|
||||||
|
DNS=fd00:10::2
|
||||||
|
|
||||||
|
[RoutingPolicyRule]
|
||||||
|
From=192.168.10.10/32
|
||||||
|
Table=2
|
||||||
|
Priority=100
|
||||||
|
|
||||||
|
[Route]
|
||||||
|
Destination=0.0.0.0/0
|
||||||
|
Gateway=192.168.10.1
|
||||||
|
Table=2
|
||||||
|
|
||||||
|
[RoutingPolicyRule]
|
||||||
|
From=fd00:10::10/128
|
||||||
|
Table=62
|
||||||
|
Priority=100
|
||||||
|
|
||||||
|
[Route]
|
||||||
|
Destination=::/0
|
||||||
|
Gateway=fd00:10::1
|
||||||
|
Table=62
|
||||||
26
config/node/vmm/nftables.conf.j2
Normal file
26
config/node/vmm/nftables.conf.j2
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/sbin/nft -f
|
||||||
|
# Convention
|
||||||
|
# iifname oifname saddr daddr proto dport ct state action / Ellipsis if you can something
|
||||||
|
flush ruleset
|
||||||
|
|
||||||
|
define HOSTS4_CONSOLE = { {{ hostvars['fw']['network4']['console'].values() | join(', ') }} }
|
||||||
|
define HOSTS6_CONSOLE = { {{ hostvars['fw']['network6']['console'].values() | join(', ') }} }
|
||||||
|
define PORTS_SSH = 22
|
||||||
|
|
||||||
|
table inet filter {
|
||||||
|
chain input {
|
||||||
|
type filter hook input priority 0; policy drop;
|
||||||
|
ct state invalid drop comment "deny invalid connection"
|
||||||
|
ct state established, related accept comment "allow all connection already existing"
|
||||||
|
iifname "lo" accept comment "allow local connection"
|
||||||
|
meta l4proto { icmp, icmpv6 } accept comment "allow icmp connection: > VMM"
|
||||||
|
ip saddr $HOSTS4_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv4 ssh connection: CONSOLE > VMM"
|
||||||
|
ip6 saddr $HOSTS6_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv6 ssh connection: CONSOLE > VMM"
|
||||||
|
}
|
||||||
|
chain forward {
|
||||||
|
type filter hook forward priority 0; policy drop;
|
||||||
|
}
|
||||||
|
chain output {
|
||||||
|
type filter hook output priority 0; policy accept;
|
||||||
|
}
|
||||||
|
}
|
||||||
3
config/secrets/.sops.yaml
Normal file
3
config/secrets/.sops.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
creation_rules:
|
||||||
|
- path_regex: secrets\.yaml$
|
||||||
|
age: age120wuwcmsm845ztsvsz46pswj5je53uc2n35vadklrfqudu6cxuusxetk7y
|
||||||
BIN
config/secrets/age-key.gpg
Normal file
BIN
config/secrets/age-key.gpg
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user