Compare commits

...

5 Commits

Author SHA1 Message Date
root
2f168317e2 add: import systemd-networkd role 2025-07-01 20:28:03 +00:00
root
d57fac58fb update: nfs_client role 2025-07-01 20:24:33 +00:00
root
69e73e438a update: os tweaks 2025-07-01 17:30:36 +00:00
root
cef17b69f9 add: support for multiple system accounts and package vars 2025-07-01 17:30:15 +00:00
root
4af2c65d8f fix: os disk management 2025-07-01 17:29:30 +00:00
23 changed files with 614 additions and 7 deletions

View File

@ -0,0 +1,11 @@
# Configure NFS mounts
Examples:
```
nfs_mounts:
- path: /mnt/nas_data__data_lan
nfs_server: 192.168.100.1
src: /mnt/pool-safe/data_lan
```

View File

@ -0,0 +1,4 @@
nsf_mount__default: []
nfs_mounts: "{{ vars | dict2items | selectattr('key', 'match', '^nfs_mounts__.*') | map(attribute='value') | list | flatten | unique }}"

View File

@ -21,11 +21,13 @@
src: "{{ src }}" src: "{{ src }}"
fstype: "{{ fstype }}" fstype: "{{ fstype }}"
state: "{{ state }}" state: "{{ state }}"
opts: "{{ opts }}"
loop: "{{ nfs_mounts }}" loop: "{{ nfs_mounts }}"
vars: vars:
state: "{{ item.state | default('mounted') }}" state: "{{ item.state | default('mounted') }}"
fstype: nfs fstype: nfs
src: "{{ nfs_server }}:{{ item.src }}" src: "{{ item.server }}:{{ item.src }}"
path: "{{ item.path }}" path: "{{ item.path }}"
opts: "{{ item.opts | d('ro') }}"

46
roles/os_base/README.md Normal file
View File

@ -0,0 +1,46 @@
# OS Base
Example config:
```
system_accounts:
- name: sysmaint
state: 'present'
system: true
uid: 1000
groups:
- sudo
- wheel
comment: 'Jzn42.net maintenance user'
create_home: true
sshkey_state: 'present'
sshkeys:
- ssh-ed25519 AAA...
permissions: &maint_permissions
- sudo
- sudo_nopass
- libvirt
- name: jez·
state: 'present'
uid: 1001
groups:
- sudo
- wheel
comment: 'Jzn42 admin'
create_home: true
sshkey_state: 'present'
sshkeys:
- ssh-ed25519 AAA...
- ssh-ed25519 AAA...
permissions: *maint_permissions
system_packages:
- htop
- vim
- ncdu
- git
- iftop
- rsync
- bash
```

View File

@ -1,6 +1,11 @@
--- ---
system_accounts: []
system_packages: []
system_packages_norecommend: false system_packages_norecommend: false
system_packages_nosuggest: false system_packages_nosuggest: false
system_accounts__default: []
system_packages__default: []
system_accounts: "{{ vars | dict2items | selectattr('key', 'match', '^system_accounts__.*') | map(attribute='value') | list | flatten | unique }}"
system_packages: "{{ vars | dict2items | selectattr('key', 'match', '^system_packages__.*') | map(attribute='value') | list | flatten | unique }}"

20
roles/os_disks/README.md Normal file
View File

@ -0,0 +1,20 @@
# OS Disk
Prepare LVM disks. Configuration example:
```
disks_vg:
- vg: data
state: present
devices_dev:
- /dev/vda
disks_lv:
- lv: var_lib_docker
vg: data
size: 20G
state: # present (mounted), absent (destroyed)
fstype: ext4
```
Note:
- Provides a VM disk detection helper

View File

@ -1,4 +1,8 @@
--- ---
disks_vg: [] disks_vg__default: []
disks_lv: [] disks_lv__default: []
disks_vg: "{{ vars | dict2items | selectattr('key', 'match', '^disks_vg__.*') | map(attribute='value') | list | flatten | unique }}"
disks_lv: "{{ vars | dict2items | selectattr('key', 'match', '^disks_lv__.*') | map(attribute='value') | list | flatten | unique }}"

View File

@ -67,7 +67,7 @@
state: "{{ state }}" state: "{{ state }}"
loop: "{{ disks_lv }}" loop: "{{ disks_lv }}"
vars: vars:
state: "{{ item.state | default('mounted') }}" state: "{{ ( item.state == 'present' ) | ternary( 'mounted', item.state | default('mounted')) }}"
fstype: "{{ item.fstype | default('ext4') }}" fstype: "{{ item.fstype | default('ext4') }}"
src: "/dev/{{ item.vg }}/{{ item.lv }}" src: "/dev/{{ item.vg }}/{{ item.lv }}"
path: "/{{ item.lv | replace('_', '/') }}" path: "/{{ item.lv | replace('_', '/') }}"

View File

@ -0,0 +1,7 @@
---
profile: production
skip_list: [role-name]
exclude_paths:
- .cache/
- .github/

View File

@ -0,0 +1,18 @@
name: check_pr
on:
push:
branches: ["master"]
pull_request:
branches: ["master"]
workflow_dispatch:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: run-ansible-lint
uses: ansible/ansible-lint@v24.2.1

View File

@ -0,0 +1,10 @@
Copyright (c) 2016, Anthony Ruhier All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project.

View File

@ -0,0 +1,238 @@
Ansible Role: systemd\_networkd
===============================
Ansible role to configure systemd-networkd.
Role Variables
--------------
```yaml
# links
systemd_networkd_link: {}
# netdevs
systemd_networkd_netdev: {}
# networks
systemd_networkd_network: {}
# does the role have to restart systemd-networkd to apply the new configuration?
systemd_networkd_apply_config: false
# enable or not systemd_resolved
systemd_networkd_enable_resolved: true
# remove configuration files matching a prefix
systemd_networkd_cleanup: false
systemd_networkd_cleanup_prefix: ''
systemd_networkd_cleanup_prefix_is_regex: false
```
Dependencies
------------
None
Example Playbook
-------------------------
1) Configure a network interface
```yaml
systemd_networkd_network:
eth0:
- Match:
- Name: "eth0"
- Network:
- DHCP: "no"
- IPv6AcceptRouterAdvertisements: "no"
- DNS: 8.8.8.8
- DNS: 8.8.4.4
- Domains: "your.tld"
- Address: "192.0.2.176/24"
- Gateway: "192.0.2.1"
- Address: "2001:db8::302/64"
- Address: "fc00:0:0:103::302/64"
- Gateway: "2001:db8::1"
```
It will create a `eth0.network` file in `/etc/systemd/network/`, and enable
`systemd-networkd` and `systemd-resolved`.
Every key under `systemd_networkd_*` corresponds to the file name to create
(`.network` in `systemd_networkd_network`, `.link` in systemd_networkd_link,
etc…). Then every key under the file name is a section documented in
systemd-networkd, which contains the couples of `option: value` pairs. Each
couple is then converted to the format `option=value`.
2) Configure a bonding interface
```yaml
systemd_networkd_netdev:
bond0:
- NetDev:
- Name: "bond0"
- Kind: "bond"
- Bond:
- Mode: "802.3ad"
- LACPTransmitRate: "fast"
systemd_networkd_network:
bond0:
- Match:
- Name: "eth*"
- Network:
- DHCP: "yes"
- Bond: "bond0"
```
What will create an LACP bond interface `bond0`, containing all interfaces
starting by `eth`.
3) Configure interface based routing
```yaml
systemd_networkd_conf:
route_tables:
- Network:
- RouteTable: "rtvlan10:10"
- RouteTable: "rtvlan11:11"
systemd_networkd_netdev:
netdev_bond0:
- NetDev:
- Name: bond0
- Kind: bond
- Bond:
- Mode: active-backup
- MIIMonitorSec: 0.1
- UpDelaySec: 0.2
- DownDelaySec: 0.2
- LACPTransmitRate: fast
- TransmitHashPolicy: layer2+3
netdev_vlan10:
- NetDev:
- Name: netdev_vlan10
- Kind: vlan
- VLAN:
- Id: 10
netdev_vlan11:
- NetDev:
- Name: netdev_vlan11
- Kind: vlan
- VLAN:
- Id: 11
netdev_bridge_vm_vlan10:
- NetDev:
- Name: netdev_bridge_vlan10
- Kind: bridge
netdev_bridge_vm_vlan11:
- NetDev:
- Name: netdev_bridge_vlan11
- Kind: bridge
systemd_networkd_network:
# Physical interfaces
eno3:
- Match:
- Name: eno3
- Network:
- Bond: bond0
eno4:
- Match:
- Name: eno4
- Network:
- Bond: bond0
bond0:
- Match:
- Name: bond0
- Network:
- Description: "Static/Unconfigured bond, for eno3 & eno4"
# We don't want any IP "on" the bond itself
- LinkLocalAddressing: "no"
- LLDP: "no"
- EmitLLDP: "no"
- IPv6AcceptRA: "no"
- IPv6SendRA: "no"
- VLAN: netdev_vlan10
- VLAN: netdev_vlan11
network_interface_vlan10:
- Match:
- Name: netdev_vlan10
- Type: vlan
- Network:
- Description: "Network interface on vlan10, connected to netdev_bridge_vm_vlan10"
- Bridge: "netdev_bridge_vm_vlan10"
- DHCP: "no"
- DNS: &gw_vlan10 "10.0.10.1"
- Address: "10.0.10.161/24"
- DNS: *gw_vlan10
- Gateway: *gw_vlan10
network_interface_vlan11:
- Match:
- Name: netdev_vlan11
- Type: vlan
- Network:
- Description: "Network interface on vlan11, connected to netdev_bridge_vm_vlan11"
- Bridge: "netdev_bridge_vm_vlan11"
- DHCP: "no"
- DNS: &gw_vlan11 "10.0.11.1"
- Address: "10.0.11.161/24"
- DNS: *gw_vlan11
- Gateway: *gw_vlan11
systemd_networkd_rt_tables:
- id: 11
name: rtvlan11
- id: 20
name: rtvlan20
```
systemd-resolved
----------------
By default this role manages `/etc/resolv.conf` and `/etc/nsswitch.conf` to use
the DNS stub resolver and NSS modules provided by `systemd-resolved`.
This behaviour can either be disabled by setting
`systemd_networkd_symlink_resolv_conf` and
`systemd_networkd_manage_nsswitch_config` to `false` or the resolution order can
be changed. The default configuration uses the default `files` database and
systemd modules where approriate:
```yaml
systemd_networkd_nsswitch_passwd: "files systemd"
systemd_networkd_nsswitch_group: "files systemd"
systemd_networkd_nsswitch_shadow: "files systemd"
systemd_networkd_nsswitch_gshadow: "files systemd"
systemd_networkd_nsswitch_hosts: "files resolve [!UNAVAIL=return] myhostname dns"
systemd_networkd_nsswitch_networks: "files dns"
systemd_networkd_nsswitch_protocols: "files"
systemd_networkd_nsswitch_services: "files"
systemd_networkd_nsswitch_ethers: "files"
systemd_networkd_nsswitch_rpc: "files"
systemd_networkd_nsswitch_netgroup: "nis"
systemd_networkd_nsswitch_automount: "files"
systemd_networkd_nsswitch_aliases: "files"
systemd_networkd_nsswitch_publickey: "files"
```
License
-------
Tool under the BSD license. Do not hesitate to report bugs, ask me some
questions or do some pull request if you want to!

View File

@ -0,0 +1,6 @@
# Fork source
* Remote: https://github.com/aruhier/ansible-role-systemd-networkd.git
* Last update: a689f58 from master (2025-07-01)

View File

@ -0,0 +1,36 @@
---
systemd_networkd_link: {}
systemd_networkd_netdev: {}
systemd_networkd_network: {}
systemd_networkd_conf: {}
systemd_networkd_directory: /etc/systemd/network
systemd_networkd_conf_directory: /etc/systemd/networkd.conf.d
systemd_networkd_apply_config: false
systemd_networkd_enable_resolved: true
systemd_networkd_symlink_resolv_conf: true
systemd_networkd_cleanup: false
systemd_networkd_cleanup_patterns: []
systemd_networkd_cleanup_patterns_use_regex: false
systemd_networkd_manage_nsswitch_config: true
systemd_networkd_nsswitch_passwd: files systemd
systemd_networkd_nsswitch_group: files systemd
systemd_networkd_nsswitch_shadow: files systemd
systemd_networkd_nsswitch_gshadow: files systemd
systemd_networkd_nsswitch_hosts: files resolve [!UNAVAIL=return] myhostname dns
systemd_networkd_nsswitch_networks: files dns
systemd_networkd_nsswitch_protocols: files
systemd_networkd_nsswitch_services: files
systemd_networkd_nsswitch_ethers: files
systemd_networkd_nsswitch_rpc: files
systemd_networkd_nsswitch_netgroup: nis
systemd_networkd_nsswitch_automount: files
systemd_networkd_nsswitch_aliases: files
systemd_networkd_nsswitch_publickey: files
systemd_networkd_rt_tables: []
systemd_networkd_rttables_conf_file: "/etc/iproute2/rt_tables"
# vim: set ts=2 sw=2:

View File

@ -0,0 +1,10 @@
---
# handlers for ansible-role-systemd-networkd
- name: Restart systemd-networkd
become: true
ansible.builtin.systemd:
name: systemd-networkd
state: restarted
daemon-reload: true
when: systemd_networkd_apply_config

View File

@ -0,0 +1,23 @@
---
galaxy_info:
role_name: systemd_networkd
author: Anthony Ruhier & StackHPC Ltd
description: Configures systemd-networkd
license: BSD
min_ansible_version: "2.5"
platforms:
- name: EL
versions:
- all
- name: Fedora
versions:
- all
- name: Ubuntu
versions:
- all
- name: Debian
versions:
- all
galaxy_tags:
- networking
dependencies: []

View File

@ -0,0 +1,25 @@
---
# This has been adapted from code in OpenStack Ansible's systemd_networkd role.
# https://github.com/openstack/ansible-role-systemd_networkd/blob/master/tasks/main.yml
- name: Find unexpected systemd-networkd configuration files
become: true
ansible.builtin.find:
paths: /etc/systemd/network
patterns: "{{ systemd_networkd_cleanup_patterns }}"
use_regex: "{{ systemd_networkd_cleanup_patterns_use_regex | bool }}"
register: networkd_files
- name: Remove unexpected systemd-networkd configuration files
become: true
vars:
expected_files:
- "{{ systemd_networkd_link.keys() | map('regex_replace', '^(.*)$', '\\1.link') | list }}"
- "{{ systemd_networkd_netdev.keys() | map('regex_replace', '^(.*)$', '\\1.netdev') | list }}"
- "{{ systemd_networkd_network.keys() | map('regex_replace', '^(.*)$', '\\1.network') | list }}"
ansible.builtin.file:
path: /etc/systemd/network/{{ item }}
state: absent
loop: "{{ networkd_files.files | map(attribute='path') | map('basename') | difference(expected_files | flatten) | list }}"
notify:
- Restart systemd-networkd

View File

@ -0,0 +1,67 @@
---
- name: Create route table if necessary
become: true
ansible.builtin.blockinfile:
path: "{{ systemd_networkd_rttables_conf_file }}"
block: "{{ lookup('template', 'rt_tables.j2') }}"
marker: "# {mark} ANSIBLE MANAGED BLOCK"
loop: "{{ systemd_networkd_rt_tables }}"
- name: Create systemd conf folder
become: true
ansible.builtin.file:
path: "{{ systemd_networkd_conf_directory }}"
state: directory
mode: "0755"
owner: root
group: root
- name: Ensure systemd-networkd configuration files exist
become: true
vars:
# Profiles to iterate over. Using a single looped task is more performant
# than multiple tasks.
all_files:
- type: link
files: "{{ systemd_networkd_link | dict2items }}"
dest_folder: "{{ systemd_networkd_directory }}"
- type: netdev
files: "{{ systemd_networkd_netdev | dict2items }}"
dest_folder: "{{ systemd_networkd_directory }}"
- type: network
files: "{{ systemd_networkd_network | dict2items }}"
dest_folder: "{{ systemd_networkd_directory }}"
- type: conf
files: "{{ systemd_networkd_conf | dict2items }}"
dest_folder: "{{ systemd_networkd_conf_directory }}"
ansible.builtin.template:
src: systemd_networkd_config.j2
dest: "{{ item.0.dest_folder }}/{{ item.1.key }}.{{ item.0.type }}"
owner: root
group: systemd-network
mode: "0640"
loop: "{{ query('subelements', all_files, 'files') }}"
loop_control:
label: "type: {{ item.0.type }}, name: {{ item.1.key }}"
notify: Restart systemd-networkd
register: systemd_networkd_status
- name: Set systemd_network_status task
ansible.builtin.set_fact:
systemd_networkd_status: "{{ systemd_networkd_status }}"
- name: Manage nsswitch configuration
become: true
ansible.builtin.template:
src: nsswitch.conf.j2
dest: /etc/nsswitch.conf
owner: root
group: root
mode: "0644"
when: systemd_networkd_manage_nsswitch_config
register: systemd_networkd_nssswitch_changed
- name: Set systemd_networkd_nssswitch_changed task
ansible.builtin.set_fact:
systemd_networkd_nssswitch_changed: "{{ systemd_networkd_nssswitch_changed }}"
# vim: set ts=2 sw=2:

View File

@ -0,0 +1,32 @@
---
- name: Import cleanup tasks
ansible.builtin.import_tasks: cleanup.yml
when: systemd_networkd_cleanup | bool
- name: Import config tasks
ansible.builtin.import_tasks: config.yml
- name: Enable systemd-networkd
become: true
ansible.builtin.systemd:
name: systemd-networkd
enabled: true
when: (systemd_networkd_network | length > 0) or (systemd_networkd_link | length > 0) or (systemd_networkd_netdev | length > 0)
- name: Start and enable systemd-resolved
become: true
ansible.builtin.systemd:
name: systemd-resolved
enabled: true
state: started
when: systemd_networkd_enable_resolved
- name: Replace /etc/resolv.conf with a symlink to the systemd-resolved stub
become: true
ansible.builtin.file:
path: /etc/resolv.conf
src: /run/systemd/resolve/stub-resolv.conf
state: link
force: true
when: systemd_networkd_symlink_resolv_conf
# vim: set ts=2 sw=2:

View File

@ -0,0 +1,20 @@
{{ ansible_managed | comment }}
passwd: {{ systemd_networkd_nsswitch_passwd }}
group: {{ systemd_networkd_nsswitch_group }}
shadow: {{ systemd_networkd_nsswitch_shadow }}
gshadow: {{ systemd_networkd_nsswitch_gshadow }}
hosts: {{ systemd_networkd_nsswitch_hosts }}
networks: {{ systemd_networkd_nsswitch_networks }}
protocols: {{ systemd_networkd_nsswitch_protocols }}
services: {{ systemd_networkd_nsswitch_services }}
ethers: {{ systemd_networkd_nsswitch_ethers }}
rpc: {{ systemd_networkd_nsswitch_rpc }}
netgroup: {{ systemd_networkd_nsswitch_netgroup }}
automount: {{ systemd_networkd_nsswitch_automount }}
aliases: {{ systemd_networkd_nsswitch_aliases }}
publickey: {{ systemd_networkd_nsswitch_publickey }}

View File

@ -0,0 +1,3 @@
{% for item in systemd_networkd_rt_tables %}
{{ item.id }} {{ item.name }}
{% endfor %}

View File

@ -0,0 +1,19 @@
{{ ansible_managed | comment }}
{% for section_dict in item.1.value %}
{% for section, options in section_dict.items() %}
[{{ section }}]
{% for opt in options %}
{% for key, val in opt.items() %}
{% if val is string or val is not iterable %}
{{ key }}={{ val }}
{% else %}
{% for subval in val %}
{{ key }}={{ subval }}
{% endfor %}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endfor %}

View File

@ -5,7 +5,8 @@
name: name:
- vim - vim
- htop - htop
- jq - iftop
- iotop
- bash-completion - bash-completion
state: present state: present