Compare commits

..

1 Commits

Author SHA1 Message Date
4e04c508db feat(wg_quick): add ansible role and playbook 2026-01-10 10:23:02 +01:00
28 changed files with 48 additions and 103 deletions

View File

@@ -1,21 +0,0 @@
---
# see https://docs.ansible.com/projects/lint/configuring/#ansible-lint-configuration
profile: moderate
exclude_paths:
- ".ansible/"
# Enable checking of loop variable prefixes in roles
loop_var_prefix: "^(__|{role}_)"
# Enforce variable names to follow pattern below, in addition to Ansible own
# requirements, like avoiding python identifiers. To disable add `var-naming`
# to skip_list.
var_naming_pattern: "^[a-z_][a-z0-9_]*$"
skip_list:
- "name[template]"
enable_list:
- galaxy
- fqcn
offline: true

2
.gitignore vendored
View File

@@ -1,2 +0,0 @@
.ansible/
results/

View File

@@ -1,6 +1,6 @@
namespace: finallycoffee namespace: finallycoffee
name: base name: base
version: 0.4.1 version: 0.4.0
readme: README.md readme: README.md
authors: authors:
- transcaffeine <transcaffeine@finally.coffee> - transcaffeine <transcaffeine@finally.coffee>
@@ -8,9 +8,9 @@ description: >-2
Roles for base services which are core functionality like managing packages Roles for base services which are core functionality like managing packages
and ssh or common dependencies other services like databases and ssh or common dependencies other services like databases
dependencies: dependencies:
"community.docker": ">=4.7.0" "community.docker": "^4.7.0"
"community.general": ">=11.1.2" "community.general": "^11.1.2"
"containers.podman": ">=1.17.0" "containers.podman": "^1.17.0"
license_file: LICENSE.md license_file: LICENSE.md
build_ignore: build_ignore:
- '*.tar.gz' - '*.tar.gz'

View File

@@ -13,4 +13,4 @@
loop: "{{ docker_registries | default([], true) }}" loop: "{{ docker_registries | default([], true) }}"
loop_control: loop_control:
loop_var: "docker_registry" loop_var: "docker_registry"
label: "{{ docker_registry.username }}@{{ docker_registry.registry }}" label: "{{ docker_registry.username}}@{{ docker_registry.registry }}"

View File

@@ -6,7 +6,7 @@
pre_tasks: pre_tasks:
- name: Build target dns records - name: Build target dns records
ansible.builtin.set_fact: ansible.builtin.set_fact:
target_dns_records: "{{ target_dns_records + [_dns_record] }}" target_dns_records: "{{ target_dns_records + [ _dns_record ] }}"
vars: vars:
_dns_record: _dns_record:
type: "CNAME" type: "CNAME"

View File

@@ -1,6 +1,6 @@
--- ---
- name: Configure wireguard interfaces with wg_quick - name: Configure wireguard interfaces with wg_quick
hosts: "{{ wg_quick_hosts | default('wg_quick') }}" hosts: "{{ wg_quick_hosts | default(wg_quick) }}"
become: "{{ wg_quick_become | default(false) }}" become: "{{ wg_quick_become | default(false) }}"
gather_facts: "{{ wg_quick_gather_facts | default(false) }}" gather_facts: "{{ wg_quick_gather_facts | default(false) }}"
roles: roles:

View File

@@ -17,6 +17,7 @@ caddy_config: |+2
# Import all configurations # Import all configurations
import {{ caddy_dynamic_configs_dir }}/*/Caddyfile import {{ caddy_dynamic_configs_dir }}/*/Caddyfile
:80 { :80 {
redir / https://{host}{uri} 301 redir / https://{host}{uri} 301
} }

View File

@@ -8,7 +8,7 @@
state: present state: present
marker: "#{mark} ANSIBLE MANAGED BLOCK by finallycoffee.base.git" marker: "#{mark} ANSIBLE MANAGED BLOCK by finallycoffee.base.git"
block: |+2 block: |+2
{% if git_config_user_name | default(false, true) and git_config_user_email | default(false, true) %} {% if git_config_user_name|default(false, true) and git_config_user_email|default(false, true) %}
[user] [user]
name = {{ git_config_user_name }} name = {{ git_config_user_name }}
email = {{ git_config_user_email }} email = {{ git_config_user_email }}

View File

@@ -14,7 +14,7 @@ gpg_config_emit_version: false
gpg_config_comments: false gpg_config_comments: false
gpg_config_ignore_time_conflict: false gpg_config_ignore_time_conflict: false
gpg_config_allow_freeform_uid: true gpg_config_allow_freeform_uid: true
gpg_config_keyid_format: "0xlong" gpg_config_keyid_format: 0xlong
gpg_config_with_fingerprint: true gpg_config_with_fingerprint: true
gpg_config_keyserver: hkps://keys.openpgp.org gpg_config_keyserver: hkps://keys.openpgp.org

View File

@@ -1,54 +1,55 @@
--- ---
- name: Ensure gnupg is installed (RedHat*) - name: Ensure gnupg is installed (RedHat*)
ansible.builtin.package: package:
name: gnupg2 name: gnupg2
state: latest state: latest
become: true become: true
when: ansible_os_family == "RedHat" when: ansible_os_family == "RedHat"
- name: Ensure gnupg is installed (Arch) - name: Ensure gnupg is installed (Arch)
ansible.builtin.package: package:
name: gnupg name: gnupg
state: latest state: latest
become: true become: true
when: ansible_os_family == "Archlinux" when: ansible_os_family == "Archlinux"
- name: Ensure ~/.gnupg folder exists with correct permissions - name: Ensure ~/.gnupg folder exists with correct permissions
ansible.builtin.file: file:
path: "{{ gpg_config_folder }}" path: "{{ gpg_config_folder }}"
state: directory state: directory
mode: "0700" mode: 0700
- name: Ensure gpg.conf is templated - name: Ensure gpg.conf is templated
ansible.builtin.template: template:
src: gpg.conf.j2 src: gpg.conf.j2
dest: "{{ gpg_config_file }}" dest: "{{ gpg_config_file }}"
- name: Configure gpg-agent.conf (agent configuration) - name: Configure gpg-agent.conf (agent configuration)
ansible.builtin.template: template:
src: gpg-agent.conf.j2 src: gpg-agent.conf.j2
dest: "{{ gpg_agent_config_file }}" dest: "{{ gpg_agent_config_file }}"
- name: Configure scdaemon.conf (smartcard daemon) - name: Configure scdaemon.conf (smartcard daemon)
ansible.builtin.template: template:
src: scdaemon.conf.j2 src: scdaemon.conf.j2
dest: "{{ gpg_scdaemon_config_file }}" dest: "{{ gpg_scdaemon_config_file }}"
- name: Configure sshcontrol (in order for gpg-agent to act as ssh-agent) - name: Configure sshcontrol (in order for gpg-agent to act as ssh-agent)
ansible.builtin.template: template:
src: sshcontrol.j2 src: sshcontrol.j2
dest: "{{ gpg_agent_sshcontrol_file }}" dest: "{{ gpg_agent_sshcontrol_file }}"
when: gpg_agent_config_enable_ssh_support when: gpg_agent_config_enable_ssh_support
- name: Copy gnupg_agent script, which makes gpg-agent responsible for ssh-auth - name: Copy gnupg_agent script, which makes gpg-agent responsible for ssh-auth
ansible.builtin.copy: copy:
src: gpg-configure-ssh-auth-socket.sh src: gpg-configure-ssh-auth-socket.sh
dest: "{{ gpg_configure_agent_script }}" dest: "{{ gpg_configure_agent_script }}"
mode: "0700" mode: 0700
when: gpg_agent_config_enable_ssh_support when: gpg_agent_config_enable_ssh_support
- name: Ensure gnupg_agent script is included in bashrc - name: Ensure gnupg_agent script is included in bashrc
ansible.builtin.lineinfile: lineinfile:
path: "~/.bashrc" path: "~/.bashrc"
line: "source {{ gpg_configure_agent_script }}" line: "source {{ gpg_configure_agent_script }}"
state: present state: present

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -xeuo pipefail set -euo pipefail
LEGO_BINARY=$(/usr/bin/env which lego) LEGO_BINARY=$(/usr/bin/env which lego)
@@ -8,11 +8,8 @@ if [[ -n "${LEGO_HTTP_FALLBACK_PORT:-}" ]]; then
echo "nc not found (in PATH), exiting" echo "nc not found (in PATH), exiting"
exit 1 exit 1
fi fi
set +e
nc -z 127.0.0.1 $LEGO_HTTP_PORT; nc -z 127.0.0.1 $LEGO_HTTP_PORT;
nc_exit_code=$?; if [[ $? -eq 0 ]]; then
set -e
if [[ $nc_exit_code -eq 0 ]]; then
LEGO_HTTP_PORT=$LEGO_HTTP_FALLBACK_PORT LEGO_HTTP_PORT=$LEGO_HTTP_FALLBACK_PORT
fi fi
fi fi

View File

@@ -1,11 +1,11 @@
--- ---
lego_domain_command_args: >-2 lego_domain_command_args: >-
{% for domain in lego_cert_domains %} {% for domain in lego_cert_domains %}
--domains={{ domain }} --domains={{ domain }}
{%- endfor %} {%- endfor %}
lego_config_command_args: >-2 lego_config_command_args: >-
{% for key in lego_full_command_config %} {% for key in lego_full_command_config %}
--{{ key | replace("_", "-") }} --{{ key | replace("_", "-") }}
{%- if lego_full_command_config[key] != None and lego_full_command_config[key] != '' -%} {%- if lego_full_command_config[key] != None and lego_full_command_config[key] != '' -%}

View File

@@ -23,7 +23,7 @@ minio_container_command:
- "--console-address" - "--console-address"
- ":{{ minio_container_listen_port_console }}" - ":{{ minio_container_listen_port_console }}"
minio_container_restart_policy: "unless-stopped" minio_container_restart_policy: "unless-stopped"
minio_container_image_force_source: "{{ (minio_container_image_tag == 'latest') | bool }}" minio_container_image_force_source: "{{ (minio_container_image_tag == 'latest')|bool }}"
minio_container_state: >-2 minio_container_state: >-2
{{ (minio_state == 'present') | ternary('started', 'absent') }} {{ (minio_state == 'present') | ternary('started', 'absent') }}

View File

@@ -3,15 +3,15 @@
ansible.builtin.file: ansible.builtin.file:
path: "{{ minio_data_path }}" path: "{{ minio_data_path }}"
state: directory state: directory
user: "{{ minio_user | default(omit, True) }}" user: "{{ minio_user|default(omit, True) }}"
group: "{{ minio_user | default(omit, True) }}" group: "{{ minio_user|default(omit, True) }}"
when: minio_manage_host_filesystem when: minio_manage_host_filesystem
- name: Ensure container image '{{ minio_container_image }}' is {{ minio_state }} - name: Ensure container image '{{ minio_container_image }}' is {{ minio_state }}
community.docker.docker_image: community.docker.docker_image:
name: "{{ minio_container_image }}" name: "{{ minio_container_image }}"
state: "{{ minio_state }}" state: "{{ minio_state }}"
source: "pull" source: pull
force_source: "{{ minio_container_image_force_source }}" force_source: "{{ minio_container_image_force_source }}"
- name: Ensure container '{{ minio_container_name }}' is {{ minio_container_state }} - name: Ensure container '{{ minio_container_name }}' is {{ minio_container_state }}
@@ -23,7 +23,7 @@
labels: "{{ minio_container_labels }}" labels: "{{ minio_container_labels }}"
networks: "{{ minio_container_networks }}" networks: "{{ minio_container_networks }}"
ports: "{{ minio_container_ports }}" ports: "{{ minio_container_ports }}"
user: "{{ minio_user | default(omit, True) }}" user: "{{ minio_user|default(omit, True) }}"
command: "{{ minio_container_command }}" command: "{{ minio_container_command }}"
restart_policy: "{{ minio_container_restart_policy }}" restart_policy: "{{ minio_container_restart_policy }}"
state: "{{ minio_container_state }}" state: "{{ minio_container_state }}"

View File

@@ -1,5 +1,5 @@
--- ---
nginx_version: "1.29.5" nginx_version: "1.29.4"
nginx_flavour: alpine nginx_flavour: alpine
nginx_base_path: /opt/nginx nginx_base_path: /opt/nginx
nginx_config_file: "{{ nginx_base_path }}/nginx.conf" nginx_config_file: "{{ nginx_base_path }}/nginx.conf"
@@ -34,3 +34,4 @@ nginx_container_state: >-2
nginx_container_restart_policy: "unless-stopped" nginx_container_restart_policy: "unless-stopped"
nginx_container_volumes: nginx_container_volumes:
- "{{ nginx_config_file }}:/etc/nginx/conf.d/nginx.conf:ro" - "{{ nginx_config_file }}:/etc/nginx/conf.d/nginx.conf:ro"

View File

@@ -30,7 +30,7 @@
ansible.builtin.copy: ansible.builtin.copy:
dest: "{{ nginx_config_file }}" dest: "{{ nginx_config_file }}"
content: "{{ nginx_config }}" content: "{{ nginx_config }}"
mode: "0640" mode: 0640
notify: notify:
- restart-nginx - restart-nginx
when: nginx_state == 'present' when: nginx_state == 'present'

View File

@@ -2,7 +2,7 @@
- name: Ensure config attributes are configured - name: Ensure config attributes are configured
community.general.ldap_attrs: community.general.ldap_attrs:
dn: "{{ openldap_config_dn }}" dn: "{{ openldap_config_dn }}"
attributes: "{{ {entry.key: entry.value} }}" attributes: "{{ { entry.key : entry.value } }}"
state: exact state: exact
server_uri: "{{ openldap_socket_url }}" server_uri: "{{ openldap_socket_url }}"
loop: "{{ openldap_config_attributes | dict2items }}" loop: "{{ openldap_config_attributes | dict2items }}"
@@ -13,7 +13,7 @@
- name: Ensure config db attributes are configured - name: Ensure config db attributes are configured
community.general.ldap_attrs: community.general.ldap_attrs:
dn: "{{ openldap_config_db_dn }}" dn: "{{ openldap_config_db_dn }}"
attributes: "{{ {entry.key: entry.value} }}" attributes: "{{ { entry.key : entry.value } }}"
state: exact state: exact
server_uri: "{{ openldap_socket_url }}" server_uri: "{{ openldap_socket_url }}"
loop: "{{ openldap_config_db_attributes | dict2items }}" loop: "{{ openldap_config_db_attributes | dict2items }}"

View File

@@ -22,3 +22,4 @@
{{ openldap_container_restart_policy | default(omit, true) }} {{ openldap_container_restart_policy | default(omit, true) }}
healthcheck: "{{ openldap_container_healthcheck | default(omit, true) }}" healthcheck: "{{ openldap_container_healthcheck | default(omit, true) }}"
state: "{{ openldap_container_state }}" state: "{{ openldap_container_state }}"

View File

@@ -2,7 +2,7 @@
- name: Ensure additional schemas are mapped to container - name: Ensure additional schemas are mapped to container
ansible.builtin.set_fact: ansible.builtin.set_fact:
openldap_init_container_volumes: >-2 openldap_init_container_volumes: >-2
{{ openldap_init_container_volumes + [schema_mount] }} {{ openldap_init_container_volumes + [ schema_mount ] }}
vars: vars:
schema_file: "{{ openldap_schema_path }}/{{ schema.name }}.ldif" schema_file: "{{ openldap_schema_path }}/{{ schema.name }}.ldif"
schema_mount: >-2 schema_mount: >-2

View File

@@ -18,10 +18,10 @@
msg: "`restic_backup_stdin_command` was set but no filename for the resulting output was supplied in `restic_backup_stdin_command_filename`" msg: "`restic_backup_stdin_command` was set but no filename for the resulting output was supplied in `restic_backup_stdin_command_filename`"
- name: Ensure backup frequency adheres to systemd's OnCalender syntax - name: Ensure backup frequency adheres to systemd's OnCalender syntax
ansible.builtin.command: command:
cmd: "systemd-analyze calendar {{ restic_policy.frequency }}" cmd: "systemd-analyze calendar {{ restic_policy.frequency }}"
register: restic_systemd_calender_parse_result register: systemd_calender_parse_res
failed_when: restic_systemd_calender_parse_result.rc != 0 failed_when: systemd_calender_parse_res.rc != 0
changed_when: false changed_when: false
- name: Ensure restic is installed - name: Ensure restic is installed
@@ -42,21 +42,13 @@
state: present state: present
when: ansible_os_family not in ['RedHat', 'Debian'] when: ansible_os_family not in ['RedHat', 'Debian']
- name: Ensure backup script is templated
ansible.builtin.copy:
src: restic-backup-directories.sh
dest: /opt/restic-backup-directories.sh
owner: root
group: root
mode: "0755"
- name: Ensure systemd service file for '{{ restic_job_name }}' is templated - name: Ensure systemd service file for '{{ restic_job_name }}' is templated
template: template:
dest: "/etc/systemd/system/{{ restic_systemd_unit_naming_scheme }}.service" dest: "/etc/systemd/system/{{ restic_systemd_unit_naming_scheme }}.service"
src: restic.service.j2 src: restic.service.j2
owner: root owner: root
group: root group: root
mode: "0640" mode: 0640
notify: notify:
- reload-systemd - reload-systemd
- trigger-restic - trigger-restic
@@ -67,7 +59,7 @@
src: restic.timer.j2 src: restic.timer.j2
owner: root owner: root
group: root group: root
mode: "0640" mode: 0640
notify: notify:
- reload-systemd - reload-systemd

View File

@@ -1,5 +0,0 @@
# `finallycoffee.base.wg_quick` ansible role
Configure a wireguard interface using `wg_quick`. This role writes
the configuration files and activates the interface using the systemd
template service abstractions.

View File

@@ -17,9 +17,3 @@
state: >-2 state: >-2
{{ (wg_quick_iface.state | default(wg_quick_state) == 'present') {{ (wg_quick_iface.state | default(wg_quick_state) == 'present')
| ternary('started', 'absent') }} | ternary('started', 'absent') }}
- name: Ensure wg-quick configuration for interface '{{ wg_quick_iface.name }}' is absent
ansible.builtin.file:
path: "{{ wg_quick_configuration_dir }}/{{ wg_quick_face.name }}.conf"
state: "absent"
when: wg_quick_iface.state | default(wg_quick_state) == 'absent'

View File

@@ -1,11 +1,4 @@
--- ---
- name: Ensure wg_quick_state is valid
ansible.builtin.fail:
msg: >-2
Invalid state '{{ wg_quick_state }}'. Valid
states are {{ wg_quick_states | join(', ') }}.
when: wg_quick_state not in wg_quick_states
- name: Ensure system packages are available - name: Ensure system packages are available
ansible.builtin.package: ansible.builtin.package:
name: "{{ wg_quick_system_packages }}" name: "{{ wg_quick_system_packages }}"

View File

@@ -8,7 +8,7 @@ PrivateKey = {{ wg_quick_iface.private_key }}
PrivateKeyFile = {{ wg_quick_iface.private_key_file }} PrivateKeyFile = {{ wg_quick_iface.private_key_file }}
{% endif %} {% endif %}
{% if wg_quick_iface.table is defined %} {% if wg_quick_iface.table is defined %}
Table = {{ wg_quick_iface.table | ternary('on', 'off') }} Table = {{ wg_quick_iface.table | ternary('On', 'Off') }}
{% endif %} {% endif %}
{% if wg_quick_iface.post_up %} {% if wg_quick_iface.post_up %}
PostUp = /bin/bash -c "{{ wg_quick_iface.post_up | join('; ') }}" PostUp = /bin/bash -c "{{ wg_quick_iface.post_up | join('; ') }}"
@@ -26,7 +26,4 @@ AllowedIPs = {{ _peer.allowed_ips | join(', ') }}
{% if _peer.persistent_keepalive %} {% if _peer.persistent_keepalive %}
PersistentKeepalive = {{ _peer.persistent_keepalive }} PersistentKeepalive = {{ _peer.persistent_keepalive }}
{% endif %} {% endif %}
{% if 'psk' in _peer %}
PresharedKey = {{ _peer.psk }}
{% endif %}
{% endfor %} {% endfor %}

View File

@@ -1,4 +0,0 @@
---
wg_quick_states:
- "present"
- "absent"