Compare commits

..

1 Commits

Author SHA1 Message Date
7246261798
feat(docker): add ansible role (WIP) 2025-04-20 19:43:33 +02:00
36 changed files with 12 additions and 500 deletions

View File

@ -1,27 +1,20 @@
namespace: finallycoffee namespace: finallycoffee
name: base name: base
version: 0.3.0 version: 0.2.1
readme: README.md readme: README.md
authors: authors:
- transcaffeine <transcaffeine@finally.coffee> - transcaffeine <transcaffeine@finally.coffee>
description: >-2 description: Roles for base services which are common dependencies other services like databases
Roles for base services which are core functionality like managing packages
and ssh or common dependencies other services like databases
dependencies: dependencies:
"community.docker": "^4.2.0" "community.docker": "^4.2.0"
"community.general": "^10.0.0"
license_file: LICENSE.md license_file: LICENSE.md
build_ignore: build_ignore:
- '*.tar.gz' - '*.tar.gz'
repository: https://git.finally.coffee/finallycoffee/base repository: https://git.finally.coffee/finallycoffee/base
issues: https://codeberg.org/finallycoffee/ansible-collection-base/issues issues: https://codeberg.org/finallycoffee/ansible-collection-base/issues
tags: tags:
- bootstrap
- ssh
- mosh
- docker - docker
- lego - lego
- minio - minio
- nginx - nginx
- restic - restic
- user_management

View File

@ -1,78 +0,0 @@
---
- name: Bootstrap everything needed for an ansible connection
hosts: "{{ target_hosts | default('all', true) }}"
become: "{{ target_host_become | default(true, false) }}"
gather_facts: false
pre_tasks:
- name: Gather information about the target system id
ansible.builtin.raw: "cat /etc/os-release | grep '^ID=' | cut -d '=' -f2"
register: target_host_os_info
check_mode: false
changed_when: false
- name: Set /etc/os-release system id
ansible.builtin.set_fact:
target_host_system_id: "{{ target_host_os_info.stdout_lines | first | trim }}"
delegate_to: localhost
- name: Gather information about the target system version
ansible.builtin.raw: "cat /etc/os-release | grep '^VERSION_ID=' | cut -d '=' -f2"
register: target_host_os_info_version
check_mode: false
changed_when: false
- name: Set /etc/os-release system version id
ansible.builtin.set_fact:
target_host_system_version_id: "{{ target_host_os_info_version.stdout_lines | first | trim }}"
delegate_to: localhost
tasks:
- name: Ensure apt bootstrap packages are installed
ansible.builtin.raw: "apt install {{ apt_bootstrap_packages | join(' ') }}"
register: target_host_apt_info
when: target_host_system_id in targets_using_apt
changed_when:
- "'0 upgraded' not in target_host_apt_info.stdout_lines | last"
- "'0 newly installed' not in target_host_apt_info.stdout_lines | last"
- name: Ensure dnf < 4 bootstrap packages are installed
ansible.builtin.raw: "dnf install --assumeyes {{ dnf4_bootstrap_packages | join(' ') }}"
register: target_host_dnf_info
when:
- target_host_system_id in targets_using_dnf4.keys()
- target_host_system_version_id | int < targets_using_dnf4[target_host_system_id]
changed_when:
- "(target_host_dnf_info.stdout_lines | last) != 'Nothing to do.'"
- name: Ensure dnf5 bootstrap packages are installed
ansible.builtin.raw: "dnf install --assumeyes {{ dnf5_bootstrap_packages | join(' ') }}"
register: target_host_dnf_info
when:
- target_host_system_id in targets_using_dnf5.keys()
- target_host_system_version_id | int >= targets_using_dnf5[target_host_system_id]
changed_when:
- "(target_host_dnf_info.stdout_lines | last) != 'Nothing to do.'"
- name: Sort hosts into os-specific groups
ansible.builtin.group_by:
key: >-2
{{ (os_group_prefix
| default(false, true)
| ternary(os_group_prefix | default('') + (os_group_seperator | default('_')), ''))
+ target_host_system_id }}
when: target_hosts_sort_into_system_ids | default(false, true)
changed_when: false
delegate_to: localhost
vars:
targets_using_apt:
- debian
- ubuntu
apt_bootstrap_packages:
- python3
- python3-apt
# default package manager is dnf5 since fedora 41
# https://fedoraproject.org/wiki/Changes/SwitchToDnf5#Current_status
targets_using_dnf4:
fedora: 41
targets_using_dnf5:
fedora: 41
dnf4_bootstrap_packages:
- python3
- python3-dnf
- python3-libdnf
dnf5_bootstrap_packages:
- python3-libdnf5

View File

@ -1,6 +0,0 @@
---
- name: Install and configure docker daemon
hosts: "{{ docker_hosts | default('docker', true) }}"
become: "{{ docker_become | default(false, true) }}"
roles:
- role: finallycoffee.base.docker

View File

@ -1,16 +0,0 @@
---
- name: Manage docker registry credentials
hosts: "{{ docker_hosts | default('docker', true) }}"
become: "{{ docker_become | default(false) }}"
gather_facts: "{{ docker_registry_gather_facts | default(true) }}"
tasks:
- name: Manage docker registry credentials
community.docker.docker_login:
registry_url: "{{ docker_registry.registry }}"
username: "{{ docker_registry.username | default(omit) }}"
password: "{{ docker_registry.password | default(omit) }}"
state: "{{ docker_registry.state | default('present') }}"
loop: "{{ docker_registries | default([], true) }}"
loop_control:
loop_var: "docker_registry"
label: "{{ docker_registry.username}}@{{ docker_registry.registry }}"

View File

@ -1,6 +0,0 @@
---
- name: Manage and configure mosh
hosts: "{{ mosh_hosts | default('mosh', true) }}"
become: "{{ mosh_become | default(true) }}"
roles:
- role: finallycoffee.base.mosh

View File

@ -1,7 +0,0 @@
---
- name: Ensure openssh is installed and configured
hosts: "{{ openssh_target | default('openssh') }}"
become: "{{ openssh_become | default(true) }}"
gather_facts: "{{ openssh_gather_facts | default(true) }}"
roles:
- role: finallycoffee.base.openssh

View File

@ -1,24 +0,0 @@
---
- name: Install system packages on the remote
hosts: "{{ target_hosts | default('all', true) }}"
become: "{{ target_host_become | default(true, true) }}"
gather_facts: "{{ target_host_gather_facts | default(true, true) }}"
tasks:
- name: Install packages (apt)
ansible.builtin.apt:
package: "{{ package.name }}"
state: "{{ package.state | default('present') }}"
loop: "{{ system_packages | default([], true) }}"
loop_control:
loop_var: package
label: "{{ package.name }}"
when: ansible_facts['pkg_mgr'] == 'apt'
- name: Install packages (dnf)
ansible.builtin.dnf:
name: "{{ package.name }}"
state: "{{ package.state | default('present') }}"
loop: "{{ system_packages | default([], true) }}"
loop_control:
loop_var: package
label: "{{ package.name }}"
when: ansible_facts['pkg_mgr'] in ['dnf', 'dnf5', 'yum']

View File

@ -1,13 +0,0 @@
# `finallycoffee.base.docker` ansible role
Install and configure the docker daemon.
## Configuration
- `docker_daemon_config` - configuration for the docker daemon
- `docker_remove_legacy_packages` - clean up old versions of docker (see https://docs.docker.com/engine/install/debian/#uninstall-old-versions)
## Plugins
- `docker_plugin_buildx_enable` - enable the buildx plugin
- `docker_plugin_compose_enable` - enable docker compose

View File

@ -1,13 +1,7 @@
--- ---
docker_state: "present" docker_state: "present"
docker_daemon_config: ~
docker_daemon_config: {}
docker_daemon_config_file: "/etc/docker/daemon.json" docker_daemon_config_file: "/etc/docker/daemon.json"
docker_daemon_config_file_mode: "0644" docker_daemon_config_file_mode: "0644"
docker_daemon_config_owner: root docker_daemon_config_owner: root
docker_daemon_config_group: "{{ docker_daemon_config_owner }}" docker_daemon_config_group: "{{ docker_daemon_config_owner }}"
docker_plugin_buildx_enable: false
docker_plugin_compose_enable: false
docker_remove_legacy_packages: true

View File

@ -1,31 +0,0 @@
---
docker_apt_key_url: "https://download.docker.com/linux/debian/gpg"
docker_apt_key_id: "9DC858229FC7DD38854AE2D88D81803C0EBFCD88"
docker_apt_arch: amd64
docker_apt_release_channel: stable
docker_apt_repository_url: "https://download.docker.com/linux/debian"
docker_apt_repository: >-2
deb [arch={{ docker_apt_arch }}] {{ docker_apt_repository_url }} {{ ansible_distribution_release }} {{ docker_apt_release_channel }}
docker_apt_cli_package: "docker-ce-cli"
docker_apt_plugin_buildx_package: "docker-buildx-plugin"
docker_apt_plugin_compose_package: "docker-compose-plugin"
docker_apt_base_packages:
- "docker-ce"
- "docker-ce-cli"
- "containerd.io"
docker_apt_packages: >-2
{{
docker_apt_base_packages
+ (docker_plugin_buildx_enable | default(false)
| ternary([ docker_apt_plugin_buildx_package ], []))
+ (docker_plugin_compose_enable | default(false)
| ternary([ docker_apt_plugin_compose_package ], []))
}}
docker_apt_legacy_packages:
- "docker.io"
- "docker-compose"
- "docker-doc"
- "podman-docker"
- "containerd"
- "runc"

View File

@ -1,34 +0,0 @@
---
docker_fedora_repo_name: "docker-ce-stable"
docker_fedora_repo_description: "Docker CE Stable - $basearch"
docker_fedora_repo_url: "https://download.docker.com/linux/fedora/$releasever/$basearch/stable"
docker_fedora_repo_validate_certs: true
docker_fedora_repo_gpg_check: true
docker_fedora_repo_gpg_key: "https://download.docker.com/linux/fedora/gpg"
docker_fedora_cli_package: "docker-ce-cli"
docker_fedora_plugin_buildx_package: "docker-buildx-plugin"
docker_fedora_plugin_compose_package: "docker-compose-plugin"
docker_fedora_base_packages:
- "docker-ce"
- "docker-ce-cli"
- "containerd.io"
docker_fedora_packages: >-2
{{
docker_fedora_base_packages
+ (docker_plugin_buildx_enable | default(false)
| ternary([ docker_fedora_plugin_buildx_package ], []))
+ (docker_plugin_compose_enable | default(false)
| ternary([ docker_fedora_plugin_compose_package ], []))
}}
docker_fedora_legacy_packages:
- "docker"
- "docker-client"
- "docker-client-latest"
- "docker-common"
- "docker-latest"
- "docker-latest-logrotate"
- "docker-logrotate"
- "docker-selinux"
- "docker-engine-selinux"
- "docker-engine"

View File

@ -9,7 +9,7 @@
- name: Configure docker daemon using '{{ docker_daemon_config_file }}' - name: Configure docker daemon using '{{ docker_daemon_config_file }}'
ansible.builtin.copy: ansible.builtin.copy:
content: "{{ docker_daemon_config | to_nice_json }}" content: "{{ docker_daemon_config | to_json }}"
dest: "{{ docker_daemon_config_file }}" dest: "{{ docker_daemon_config_file }}"
mode: "{{ docker_daemon_config_file_mode }}" mode: "{{ docker_daemon_config_file_mode }}"
owner: "{{ docker_daemon_config_owner }}" owner: "{{ docker_daemon_config_owner }}"

View File

@ -1,30 +0,0 @@
---
- name: Ensure legacy docker packages are removed
ansible.builtin.apt:
name: "{{ docker_apt_legacy_packages }}"
state: absent
when: docker_remove_legacy_packages
- name: Add apt key for docker repository
ansible.builtin.apt_key:
id: "{{ docker_apt_key_id }}"
url: "{{ docker_apt_key_url }}"
state: "{{ docker_state }}"
- name: Add apt repository for docker
ansible.builtin.apt_repository:
repo: "{{ docker_apt_repository }}"
state: "{{ docker_state }}"
register: docker_apt_repository_info
- name: Update apt cache if repository was newly added
ansible.builtin.apt:
update_cache: true
when:
- docker_state == 'present'
- docker_apt_repository_info.changed
- name: Install apt packages for docker
ansible.builtin.apt:
name: "{{ docker_apt_packages }}"
state: "{{ docker_state }}"

View File

@ -1,21 +0,0 @@
---
- name: Ensure legacy docker packages are removed
ansible.builtin.dnf:
name: "{{ docker_fedora_legacy_packages }}"
state: "removed"
when: docker_remove_legacy_packages
- name: Ensure dnf repository for docker is {{ docker_state }}
ansible.builtin.yum_repository:
name: "{{ docker_fedora_repo_name }}"
description: "{{ docker_fedora_repo_description }}"
baseurl: "{{ docker_fedora_repo_url }}"
validate_certs: "{{ docker_fedora_repo_validate_certs }}"
gpgkey: "{{ docker_fedora_repo_gpg_key }}"
gpgcheck: "{{ docker_fedora_repo_gpg_check }}"
state: "{{ docker_state }}"
- name: Install dnf packages for docker
ansible.builtin.dnf:
name: "{{ docker_fedora_packages }}"
state: "{{ docker_state }}"

View File

@ -2,14 +2,14 @@
- name: Check if target OS is supported - name: Check if target OS is supported
ansible.builtin.fail: ansible.builtin.fail:
msg: >-2 msg: >-2
OS '{{ docker_os }}' is not supported! OS Family '{{ docker_os_family }}' is not supported!
when: docker_os not in docker_supported_oses when: docker_os_family not in docker_supported_os_families
vars: vars:
docker_os: "{{ ansible_distribution | lower }}" docker_os_family: "{{ ansible_os_family | lower }}"
- name: Ensure docker is {{ docker_state }} on {{ ansible_distribution }} - name: Ensure docker is {{ docker_state }} on {{ ansible_os_family }}-family
ansible.builtin.include_tasks: ansible.builtin.include_tasks:
file: "install-{{ ansible_distribution | lower }}.yml" file: "install-{{ ansible_os_family | lower }}.yml"
- name: Configure docker daemon - name: Configure docker daemon
ansible.builtin.include_tasks: ansible.builtin.include_tasks:

View File

@ -1,4 +1,3 @@
--- ---
docker_supported_oses: docker_supported_os_families:
- 'debian' - 'debian'
- 'fedora'

View File

@ -107,7 +107,6 @@
{{ entry.key }}={{ entry.value }} {{ entry.key }}={{ entry.value }}
{% endfor %} {% endfor %}
dest: "{{ lego_base_path }}/{{ lego_instance }}.conf" dest: "{{ lego_base_path }}/{{ lego_instance }}.conf"
register: lego_env_file_info
- name: Ensure timer unit is templated - name: Ensure timer unit is templated
ansible.builtin.template: ansible.builtin.template:
@ -121,7 +120,6 @@
src: "lego_run.sh" src: "lego_run.sh"
dest: "{{ lego_base_path }}/run.sh" dest: "{{ lego_base_path }}/run.sh"
mode: "0755" mode: "0755"
register: lego_handler_script_info
- name: Ensure per-instance base path is created - name: Ensure per-instance base path is created
ansible.builtin.file: ansible.builtin.file:
@ -161,18 +159,7 @@
name: "{{ lego_systemd_timer_name }}" name: "{{ lego_systemd_timer_name }}"
state: "started" state: "started"
- name: Check if certificates are present
ansible.builtin.find:
path: "{{ lego_instance_path }}/certificates"
recurse: false
file_type: "file"
register: lego_certificate_info
- name: Ensure systemd service is started once to obtain the certificate - name: Ensure systemd service is started once to obtain the certificate
ansible.builtin.systemd_service: ansible.builtin.systemd_service:
name: "{{ lego_systemd_service_name }}" name: "{{ lego_systemd_service_name }}"
state: "started" state: "started"
when: >-2
lego_handler_script_info.changed
or lego_env_file_info.changed
or lego_certificate_info.files | default([]) | length == 0

View File

@ -1,7 +1,7 @@
--- ---
minio_container_name: minio minio_container_name: minio
minio_container_image_name: "docker.io/minio/minio" minio_container_image_name: "docker.io/minio/minio"
minio_container_image_tag: "RELEASE.2025-04-22T22-12-26Z" minio_container_image_tag: "RELEASE.2025-04-08T15-41-24Z"
minio_container_image: "{{ minio_container_image_name }}:{{ minio_container_image_tag }}" minio_container_image: "{{ minio_container_image_name }}:{{ minio_container_image_tag }}"
minio_container_networks: [] minio_container_networks: []
minio_container_ports: [] minio_container_ports: []

View File

@ -1,4 +0,0 @@
# `finallycoffee.base.mosh`
Installs [`mosh`](https://mosh.org/#), a remote 'mobile shell' which supports
roaming and re-uses SSH for the authentication layer.

View File

@ -1,2 +0,0 @@
---
mosh_state: present

View File

@ -1,15 +0,0 @@
---
mosh_debian_packages:
- "mosh"
- "openssh-server"
mosh_fedora_packages:
- "mosh"
- "openssh-server"
mosh_archlinux_packages:
- "mosh"
- "openssh"
mosh_packages:
debian: "{{ mosh_debian_packages }}"
fedora: "{{ mosh_fedora_packages }}"
archlinux: "{{ mosh_archlinux_packages }}"

View File

@ -1,30 +0,0 @@
---
- name: Ensure mosh is {{ mosh_state }} (dnf)
ansible.builtin.dnf:
name: "{{ mosh_packages[_key] }}"
state: "{{ mosh_state }}"
when:
- ansible_facts['pkg_mgr'] in ['dnf', 'dnf5']
- _key in mosh_packages.keys()
vars:
_key: "{{ ansible_distribution | lower }}"
- name: Ensure mosh is {{ mosh_state }} (apt)
ansible.builtin.apt:
package: "{{ mosh_packages[_key] }}"
state: "{{ mosh_state }}"
when:
- ansible_facts['pkg_mgr'] in ['apt']
- _key in mosh_packages.keys()
vars:
_key: "{{ ansible_distribution | lower }}"
- name: Ensure mosh is {{ mosh_state }} (pacman)
community.general.pacman:
name: "{{ mosh_packages[_key] }}"
state: "{{ mosh_state }}"
when:
- ansible_facts['pkg_mgr'] in ['pacman']
- _key in mosh_packages.keys()
vars:
_key: "{{ ansible_distribution | lower }}"

View File

@ -1,11 +0,0 @@
---
- name: Ensure 'mosh_state' is valid
ansible.builtin.fail:
msg: >-2
Invalid state '{{ mosh_state }}' for 'mosh_state'!
Allowed states are {{ mosh_states | join(', ') }}.
when: mosh_state not in mosh_states
- name: Ensure mosh is {{ mosh_state }}
ansible.builtin.include_tasks:
file: "install.yml"

View File

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

View File

@ -1,5 +1,5 @@
--- ---
nginx_version: "1.28.0" nginx_version: "1.27.5"
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"

View File

@ -1,13 +0,0 @@
# `finallycoffee.base.openssh`
Ansible role to manage and configure openssh and it's components (like `sshd`).
Currently supports `fedora` and `debian` linux distributions.
## `sshd`
To configure `sshd`, see the [`defaults/main/sshd.yml`](defaults/main/sshd.yml),
where snake\_cased config keys for `/etc/ssh/sshd_config` are available in
the `openssh_sshd_config_` namespace.
To add your own config on top, simply use key-value syntax in `openssh_sshd_config`.

View File

@ -1,3 +0,0 @@
---
openssh_state: 'present'
openssh_sshd_config_file: "/etc/ssh/sshd_config"

View File

@ -1,8 +0,0 @@
---
openssh_packages:
fedora: "{{ openssh_fedora_packages }}"
debian: "{{ openssh_debian_packages }}"
openssh_fedora_packages:
- "openssh-server"
openssh_debian_packages:
- "openssh-server"

View File

@ -1,33 +0,0 @@
---
openssh_sshd_enable: true
openssh_sshd_config_pubkey_authentication: true
openssh_sshd_config_password_authentication: false
openssh_sshd_config_challenge_response_authentication: false
openssh_sshd_config_permit_root_login: false
# Limits
openssh_sshd_config_max_sessions: ~
openssh_sshd_config_max_startups: ~
# Hardening
openssh_sshd_config_protocol: 2
openssh_sshd_config_x11_forwarding: false
openssh_sshd_config_allow_agent_forwarding: false
openssh_sshd_config_allow_tcp_forwarding: false
openssh_sshd_default_config:
PubkeyAuthentication: "{{ openssh_sshd_config_pubkey_authentication }}"
PasswordAuthentication: "{{ openssh_sshd_config_password_authentication }}"
ChallengeResponseAuthentication: >-2
{{ openssh_sshd_config_challenge_response_authentication }}
PermitRootLogin: "{{ openssh_sshd_config_permit_root_login }}"
MaxSessions: "{{ openssh_sshd_config_max_sessions }}"
MaxStartups: "{{ openssh_sshd_config_max_startups }}"
Protocol: "{{ openssh_sshd_config_protocol }}"
X11Forwarding: "{{ openssh_sshd_config_x11_forwarding }}"
AllowAgentForwarding: "{{ openssh_sshd_config_allow_agent_forwarding }}"
AllowTcpForwarding: "{{ openssh_sshd_config_allow_tcp_forwarding }}"
openssh_sshd_merged_config: >-2
{{ openssh_sshd_default_config | default({}, true)
| combine(openssh_sshd_config | default({}, true)) }}

View File

@ -1,2 +0,0 @@
---
openssh_sshd_systemd_service_name: "sshd.service"

View File

@ -1,7 +0,0 @@
---
- name: Ensure sshd is reloaded
ansible.builtin.systemd_service:
name: "{{ openssh_sshd_systemd_service_name }}"
state: "reloaded"
when: ansible_facts['service_mgr'] == 'systemd'
listen: openssh_sshd_reload

View File

@ -1,28 +0,0 @@
---
- name: Configure sshd
ansible.builtin.lineinfile:
path: "{{ openssh_sshd_config_file }}"
regexp: "{{ openssh_sshd_config_regexp }}"
line: "{{ openssh_sshd_config_line }}"
firstmatch: true
state: present
validate: "sshd -Tf %s"
loop: "{{ openssh_sshd_merged_config | dict2items }}"
loop_control:
loop_var: "tuple"
label: "{{ tuple.key }}"
notify:
- openssh_sshd_reload
vars:
openssh_sshd_config_regexp: "^\\s*#?\\s*{{ tuple.key }}"
openssh_sshd_config_line: >-2
{{ openssh_sshd_config_line_commented }}{{ tuple.key }} {{ openssh_sshd_config_value }}
openssh_sshd_config_value_is_none: "{{ tuple.value is none }}"
openssh_sshd_config_line_commented: >-2
{{ openssh_sshd_config_value_is_none | ternary('#', '') }}
openssh_sshd_config_value: >-2
{{ (tuple.value is boolean) | ternary(
tuple.value | ternary('yes', 'no'),
tuple.value
)
}}

View File

@ -1,16 +0,0 @@
---
- name: Ensure openssh server package is {{ openssh_state }} (dnf)
ansible.builtin.dnf:
name: "{{ openssh_packages[ansible_distribution | lower] }}"
state: "{{ openssh_state }}"
when:
- ansible_facts['pkg_mgr'] in ['dnf', 'dnf5']
- ansible_distribution | lower in openssh_packages.keys()
- name: Ensure openssh server package is {{ openssh_state }} (apt)
ansible.builtin.apt:
package: "{{ openssh_packages[ansible_distribution | lower] }}"
state: "{{ openssh_state }}"
when:
- ansible_facts['pkg_mgr'] in ['apt']
- ansible_distribution | lower in openssh_packages.keys()

View File

@ -1,15 +0,0 @@
---
- name: Ensure 'openssh_state' is valid
ansible.builtin.fail:
msg: >-2
Invalid value '{{ openssh_state }}' for 'openssh_state'.
Valid values are {{ openssh_states | join(', ') }}!
when: openssh_state not in openssh_states
- name: Ensure openssh is {{ openssh_state }}
ansible.builtin.include_tasks:
file: "install.yml"
- name: Ensure sshd is configured
ansible.builtin.include_tasks:
file: "configure-sshd.yml"

View File

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