Compare commits

...

34 Commits
0.1.0 ... main

Author SHA1 Message Date
ea1c32358f
update(elasticsearch): bump version to 9.0.2 2025-06-03 18:20:30 +02:00
7779dbabe1
update(elasticsearch); bump version to 9.0.1 2025-05-07 17:45:50 +02:00
aa9cae373b
update(elasticsearch): bump version to 8.18.1 2025-05-07 17:45:12 +02:00
c32fde6f9c
meta: bump galaxy version to 0.1.4 2025-04-27 18:48:25 +02:00
caeedabb99
update(valkey): bump version to 8.1.1 2025-04-24 15:09:32 +02:00
1694a08374
fix(valkey): ensure config path is owned by root by default 2025-04-23 15:36:47 +02:00
5fa26ed187
fix(postgresql): ignore errors on first run in check mode, support overriding internal postgresql container username, fix container image name creation 2025-04-20 12:16:12 +02:00
f9f00d1919
feat(postgresql): add playbooks to provision users, databases, hba entries and entire client(s) 2025-04-19 16:21:22 +02:00
3816daa679
update(elasticsearch): bump version to 8.18.0 2025-04-15 16:59:18 +02:00
effb4976db
update(elasticsearch): bump version to 8.17.5 2025-04-15 16:56:57 +02:00
07e58e5ba4
update(valkey): bump version to 8.1.0 2025-04-01 17:47:24 +02:00
decb7ba39e
update(elasticsearch): bump version to 8.17.4 2025-03-25 17:59:44 +01:00
e6987ee55d
update(elasticsearch): bump version to 8.17.3 2025-03-04 21:06:54 +01:00
93bfb97b5a
update(elasticsearch): bump version to 8.17.28 2025-02-25 17:01:46 +01:00
4076a576cf
meta: add containers.podman@^1.16.0 as collection dependency 2025-02-14 22:29:06 +01:00
851f47beaf
feat(mariadb): support podman as deployment method 2025-02-14 21:32:27 +01:00
e5529a7102
feat(mariadb): check state and deployment method parameter 2025-02-13 20:33:03 +01:00
ce3f809397
meta: bump galaxy version to 0.1.3 2025-02-12 22:08:27 +01:00
39ad346e29
update(mariadb): bump version to 10.11.11 2025-02-12 22:07:23 +01:00
e30b283b77
update(elasticsearch): bump version to 8.17.2 2025-02-11 17:22:09 +01:00
26199f6859
update(elasticsearch): bump version to 8.17.1 2025-01-21 19:19:58 +01:00
815cfca718
update(valkey): bump version to 8.0.2 2025-01-08 17:18:25 +01:00
02cb20fcc6
meta: bump collection version to 0.1.2, require community.docker>=4.0.0, community.postgresql>=3.9.0 2025-01-05 17:46:02 +01:00
6f70e8c2bf
feat(postgresql): add ansible role for postgresql deployment 2025-01-04 11:04:55 +01:00
bff5cce7e9
fix(valkey): set container restart policy 2024-12-15 12:34:49 +01:00
2edb0eae52
fix(redis): set container restart policy 2024-12-15 12:34:40 +01:00
7c2f8277a7
update(elasticsearch): bump version to 8.17.0 2024-12-13 21:29:12 +01:00
96de942f51
update(mariadb): bump version to 10.11.10 2024-12-09 21:07:55 +01:00
6625557bfa
update(elasticsearch): bump version to 8.15.5 2024-12-09 21:06:43 +01:00
9b3af2f6d4
meta: bump galaxy version to 0.1.1 2024-11-30 19:21:55 +01:00
f2aa516b13
chore(elasticsearch): 'purge_networks' option for 'docker_container' module is removed 2024-11-30 19:21:18 +01:00
39fed04d33
chore(mariadb): 'purge_networks' option for 'docker_container' module is removed 2024-11-30 19:20:48 +01:00
383a89aef7
feat(valkey): add ansible role 2024-11-04 17:13:36 +01:00
ccc4f52d56
feat(redis): add ansible role 2024-11-02 09:57:00 +01:00
50 changed files with 1266 additions and 24 deletions

View File

@ -4,5 +4,16 @@
- [`elasticsearch`](roles/elasticsearch/README.md): deploy
elasticsearch (OSS) in a docker container
- [`redis`](roles/redis/README.md): deploy and configure redis,
a fast cache, vector search and NoSQL database.
- [`mariadb`](roles/mariadb/README.md): deploy mariadb
in a docker container
- [`postgresql`](roles/postgresql/README.md): deploy postgresql,
the worlds most advances open-source relational database
- [`valkey`](roles/valkey/README.md): deploy and configure valkey,
an open source in-memory data store under BSD license, forked
from redis.

View File

@ -1,12 +1,14 @@
namespace: finallycoffee
name: databases
version: 0.1.0
version: 0.1.4
readme: README.md
authors:
- transcaffeine <transcaffeine@finally.coffee>
description: Collection for deploying and configuring databases
dependencies:
"community.docker": "^3.0.0"
"community.docker": "^4.0.0"
"community.postgresql": "^3.9.0"
"containers.podman": "^1.16.0"
license_file: LICENSE.md
build_ignore:
- '*.tar.gz'
@ -14,5 +16,9 @@ repository: https://git.finally.coffee/finallycoffee/databases
issues: https://codeberg.org/finallycoffee/ansible-collection-databases/issues
tags:
- elasticsearch
- redis
- mariadb
- postgresql
- postgres
- valkey
- docker

6
playbooks/postgresql.yml Normal file
View File

@ -0,0 +1,6 @@
---
- name: Deploy and configure PostgreSQL
hosts: "{{ postgresql_hosts | default('postgresql', true) }}"
become: "{{ postgresql_become | default(true, true) }}"
roles:
- role: finallycoffee.databases.postgresql

View File

@ -0,0 +1,24 @@
---
- import_playbook: finallycoffee.databases.postgresql_user
vars:
postgresql_users:
- name: "{{ postgresql_client_username }}"
password: "{{ postgresql_client_password }}"
- import_playbook: finallycoffee.databases.postgresql_database
vars:
postgresql_databases:
- name: "{{ postgresql_client_database }}"
owner: "{{ postgresql_client_username }}"
encoding: "{{ postgresql_client_database_encoding | default('UTF8', true) }}"
lc_ctype: "{{ postgresql_client_database_lc_ctype | default('en_US.UTF-8', true) }}"
lc_collate: "{{ postgresql_client_database_lc_collate | default('en_US.UTF-8', true) }}"
- import_playbook: finallycoffee.databases.postgresql_host_based_authentication
vars:
postgresql_authentications:
- users: "{{ postgresql_client_username }}"
databases: "{{ postgresql_client_database }}"
contype: "{{ postgresql_client_database_contype | default('local') }}"
method: "{{ postgresql_client_database_auth_method | default('md5') }}"
options: "{{ postgresql_client_options | default(false, true) }}"
address: "{{ postgresql_client_address | default(false, true) }}"
netmask: "{{ postgresql_client_netmask | default(false, true) }}"

View File

@ -0,0 +1,4 @@
---
- import_playbook: finallycoffee.databases.postgresql_user
- import_playbook: finallycoffee.databases.postgresql_database
- import_playbook: finallycoffee.databases.postgresql_host_based_authentication

View File

@ -0,0 +1,26 @@
---
- name: Configure postgresql databases
hosts: "{{ postgresql_hosts | default('postgresql', true) }}"
become: "{{ postgresql_become | default(false, true) }}"
gather_facts: "{{ postgresql_gather_facts | default(false, true) }}"
tasks:
- name: Configure individual postgresql database
community.postgresql.postgresql_db:
name: "{{ postgresql_database.name }}"
owner: "{{ postgresql_database.owner | default(omit) }}"
state: "{{ postgresql_database_state }}"
template: "{{ postgresql_database.template | default(omit, true) }}"
encoding: "{{ postgresql_database.encoding | default(omit, true) }}"
lc_ctype: "{{ postgresql_database.lc_ctype | default(omit, true) }}"
lc_collate: "{{ postgresql_database.lc_collate | default(omit, true) }}"
login_host: "{{ postgresql_connection_host | default(omit, true) }}"
login_port: "{{ postgresql_connection_port | default(omit, true) }}"
login_unix_socket: "{{ postgresql_connection_unix_socket | default(omit, true) }}"
login_user: "{{ postgresql_connection_user | default(omit, true) }}"
login_password: "{{ postgresql_connection_password | default(omit, true) }}"
vars:
postgresql_database_state: "{{ postgresql_database.state | default('present', true) }}"
loop: "{{ postgresql_databases | default([]) }}"
loop_control:
loop_var: postgresql_database
label: "{{ postgresql_database.name }}"

View File

@ -0,0 +1,23 @@
---
- name: Configure postgresql host based authentications
hosts: "{{ postgresql_hosts | default('postgresql', true) }}"
become: "{{ postgresql_become | default(false, true) }}"
gather_facts: "{{ postgresql_gather_facts | default(false, true) }}"
tasks:
- name: Configure individual postgresql host based authentication
community.postgresql.postgresql_pg_hba:
dest: "{{ postgresql_pg_hba_conf_file }}"
users: "{{ postgresql_auth.users | default(omit) }}"
databases: "{{ postgresql_auth.databases | default(omit) }}"
contype: "{{ postgresql_auth.contype }}"
state: "{{ postgresql_auth_state }}"
method: "{{ postgresql_auth.method | default(omit, true) }}"
options: "{{ postgresql_auth.options | default(omit, true) }}"
address: "{{ postgresql_auth.address | default(omit, true) }}"
netmask: "{{ postgresql_auth.netmask | default(omit, true) }}"
vars:
postgresql_auth_state: "{{ postgresql_auth.state | default('present', true) }}"
loop: "{{ postgresql_authentications | default([]) }}"
loop_control:
loop_var: postgresql_auth
label: "{{ postgresql_auth.users }}@{{ postgresql_auth.databases }}"

View File

@ -0,0 +1,24 @@
---
- name: Configure postgresql users
hosts: "{{ postgresql_hosts | default('postgresql', true) }}"
become: "{{ postgresql_become | default(false, true) }}"
gather_facts: "{{ postgresql_gather_facts | default(false, true) }}"
tasks:
- name: Configure individual postgresql user
community.postgresql.postgresql_user:
name: "{{ postgresql_user.name }}"
state: "{{ postgresql_user_state }}"
password: "{{ postgresql_user_password }}"
login_host: "{{ postgresql_connection_host | default(omit, true) }}"
login_port: "{{ postgresql_connection_port | default(omit, true) }}"
login_unix_socket: "{{ postgresql_connection_unix_socket | default(omit, true) }}"
login_user: "{{ postgresql_connection_user | default(omit, true) }}"
login_password: "{{ postgresql_connection_password | default(omit, true) }}"
vars:
postgresql_user_state: "{{ postgresql_user.state | default('present', true) }}"
postgresql_user_password: >-2
{{ (postgresql_user_state != 'absent') | ternary(postgresql_user.password, omit) }}
loop: "{{ postgresql_users | default([]) }}"
loop_control:
loop_var: postgresql_user
label: "{{ postgresql_user.name }}"

6
playbooks/valkey.yml Normal file
View File

@ -0,0 +1,6 @@
---
- name: Deploy and configure valkey
hosts: "{{ valkey_hosts | default('valkey', true) }}"
become: "{{ valkey_become | default(true, true) }}"
roles:
- finallycoffee.databases.valkey

View File

@ -1,5 +1,5 @@
---
elasticsearch_version: 8.15.3
elasticsearch_version: "9.0.2"
elasticsearch_state: present
elasticsearch_base_path: /opt/elasticsearch

View File

@ -34,6 +34,5 @@
volumes: "{{ elasticsearch_container_volumes }}"
ulimits: "{{ elasticsearch_container_ulimits }}"
networks: "{{ elasticsearch_container_networks | default(omit, True) }}"
purge_networks: "{{ elasticsearch_container_purge_networks | default(omit, True) }}"
restart_policy: "{{ elasticsearch_container_restart_policy }}"
state: "{{ elasticsearch_container_state }}"

View File

@ -1,9 +1,10 @@
---
mariadb_version: "10.11.9"
mariadb_version: "10.11.11"
mariadb_base_path: /var/lib/mariadb
mariadb_data_path: >-2
{{ mariadb_base_path }}/{{ mariadb_version | split('.') | first }}
mariadb_state: present
mariadb_deployment_method: docker
mariadb_root_password: ~
mariadb_database: ~

View File

@ -0,0 +1,20 @@
---
- name: Ensure mariadb container image '{{ mariadb_container_image }}' is {{ mariadb_state }}
community.docker.docker_image:
name: "{{ mariadb_container_image }}"
state: "{{ mariadb_state }}"
source: "{{ mariadb_container_image_source }}"
force_source: "{{ mariadb_container_image_force_source }}"
- name: Ensure mariadb container '{{ mariadb_container_name }}' is {{ mariadb_container_state }}
community.docker.docker_container:
name: "{{ mariadb_container_name }}"
image: "{{ mariadb_container_image }}"
env: "{{ mariadb_container_environment }}"
ports: "{{ mariadb_container_ports | default(omit, true) }}"
labels: "{{ mariadb_container_labels | default(omit, true) }}"
volumes: "{{ mariadb_container_volumes }}"
networks: "{{ mariadb_container_networks | default(omit, true) }}"
etc_hosts: "{{ mariadb_container_etc_hosts | default(omit, true) }}"
restart_policy: "{{ mariadb_container_restart_policy }}"
state: "{{ mariadb_container_state }}"

View File

@ -0,0 +1,20 @@
---
- name: Ensure mariadb container image '{{ mariadb_container_image }}' is {{ mariadb_state }}
containers.podman.podman_image:
name: "{{ mariadb_container_image }}"
state: "{{ mariadb_state }}"
pull: "{{ (mariadb_container_image_source == 'pull') | bool }}"
force: "{{ mariadb_container_image_force_source }}"
- name: Ensure mariadb container '{{ mariadb_container_name }}' is {{ mariadb_container_state }}
containers.podman.podman_container:
name: "{{ mariadb_container_name }}"
image: "{{ mariadb_container_image }}"
env: "{{ mariadb_container_environment }}"
ports: "{{ mariadb_container_ports | default(omit, true) }}"
labels: "{{ mariadb_container_labels | default(omit, true) }}"
volumes: "{{ mariadb_container_volumes }}"
network: "{{ mariadb_container_networks | default(omit, true) }}"
etc_hosts: "{{ mariadb_container_etc_hosts | default(omit, true) }}"
restart_policy: "{{ mariadb_container_restart_policy }}"
state: "{{ mariadb_container_state }}"

View File

@ -1,21 +1,19 @@
---
- name: Ensure mariadb container image '{{ mariadb_container_image }}' is {{ mariadb_state }}
community.docker.docker_image:
name: "{{ mariadb_container_image }}"
state: "{{ mariadb_state }}"
source: "{{ mariadb_container_image_source }}"
force_source: "{{ mariadb_container_image_force_source }}"
- name: Ensure mariadb state parameter is valid
ansible.builtin.fail:
msg: >-2
Unknown state '{{ mariadb_state }}'!
Supported states are {{ mariadb_states | join(', ') }}
when: mariadb_state not in mariadb_states
- name: Ensure deployment method is valid
ansible.builtin.fail:
msg: >-2
Unknown deployment method '{{ mariadb_deployment_method }}'!
Supported deployment methods are {{ mariadb_deployment_methods | join(', ') }}
when: mariadb_deployment_method not in mariadb_deployment_methods
- name: Ensure mariadb is deployed using {{ mariadb_deployment_method }}
ansible.builtin.include_tasks:
file: "deploy-{{ mariadb_deployment_method }}.yml"
- name: Ensure mariadb container '{{ mariadb_container_name }}' is {{ mariadb_container_state }}
community.docker.docker_container:
name: "{{ mariadb_container_name }}"
image: "{{ mariadb_container_image }}"
env: "{{ mariadb_container_environment }}"
ports: "{{ mariadb_container_ports | default(omit, true) }}"
labels: "{{ mariadb_container_labels | default(omit, true) }}"
volumes: "{{ mariadb_container_volumes }}"
networks: "{{ mariadb_container_networks | default(omit, true) }}"
etc_hosts: "{{ mariadb_container_etc_hosts | default(omit, true) }}"
purge_networks: "{{ mariadb_container_purge_networks | default(omit, true) }}"
restart_policy: "{{ mariadb_container_restart_policy }}"
state: "{{ mariadb_container_state }}"

View File

@ -1,4 +1,10 @@
---
mariadb_states:
- present
- absent
mariadb_deployment_methods:
- docker
- podman
mariadb_container_database_environment:
MARIADB_DATABASE: "{{ mariadb_database }}"

View File

@ -0,0 +1,27 @@
# `finallycoffee.databases.postgresql` ansible role
PostgreSQL is the self proclaimed "world's most advanced" open source relational
database. This ansible role can deploy and configure postgresql.
By default, the role configures the remote's effective ansible user with
peer authentication for the (postgresql) role `postgres` on all databases (with all grants).
## Required configuration
Set `postgresql_superuser_password` to your superusers desired password.
## Optional configuration
Set `postgresql_major_version` to your desired postgresql major version,
for supported major versions see [`defaults/main/main.yml`](defaults/main/main.yml#L6).
This role can be executed multiple times with different
`postgresql_major_version` values to provide new database versions for up-to-
date applications and older versions for software which does not yet support
them. Container name and host mounts encode the major version to prevent
accidental usage of the 'wrong' `PGDATA` directory.
## Requirements
- `psycopg2` (pip) package
- `docker` (pip) package

View File

@ -0,0 +1,18 @@
---
postgresql_config_connect_socket: true
postgresql_config_unix_socket: "/var/run/postgresql"
postgresql_config_unix_socket_directories:
- "{{ postgresql_config_unix_socket }}"
postgresql_config_listen_addresses:
- '*'
postgresql_config_port: 5432
postgresql_base_config:
listen_addresses: "{{ postgresql_config_listen_addresses }}"
unix_socket_directories: "{{ postgresql_config_unix_socket_directories }}"
port: "{{ postgresql_config_port }}"
postgresql_merged_config: >-2
{{ postgresql_base_config | combine(
postgresql_config | default({}, true),
recursive=True
) }}

View File

@ -0,0 +1,75 @@
---
postgresql_container_image_registry: docker.io
postgresql_container_image_namespace: ~
postgresql_container_image_name: postgres
postgresql_container_image_tag: ~
postgresql_container_image_source: pull
postgresql_container_image_force_source: >-2
{{ postgresql_container_image_tag | default(false, true) | bool }}
postgresql_container_image: >-2
{{
([
postgresql_container_image_registry | default([], true),
postgresql_container_image_namespace | default([], true),
postgresql_container_image_name
] | flatten | join('/'))
+ ':' + postgresql_container_image_tag | default(
postgresql_version + (
((postgresql_container_image_flavour is string)
and (postgresql_container_image_flavour | length > 0))
| ternary(
'-' + postgresql_container_image_flavour | default('', true),
'',
)
),
true
)
}}
postgresql_container_name: "postgresql-{{ postgresql_major_version }}"
postgresql_container_env: ~
postgresql_container_user: >-2
{{ postgresql_user_id }}:{{ postgresql_user_group_id }}
postgresql_container_ports: ~
postgresql_container_labels: ~
postgresql_container_networks: ~
postgresql_container_recreate: ~
postgresql_container_etc_hosts: ~
postgresql_container_restart_policy: "on-failure"
postgresql_container_state: >-2
{{ (postgresql_state == 'present') | ternary('started', 'absent') }}
postgresql_container_volumes: ~
postgresql_container_unix_socket_path: >-2
{{ postgresql_config_unix_socket_directories | first }}
postgresql_container_base_volumes:
- "{{ postgresql_container_passwd_file }}:/etc/passwd:ro"
- "{{ postgresql_data_path }}:{{ postgresql_container_data_dir }}:Z"
postgresql_container_config_volumes:
- "{{ postgresql_pg_hba_conf_file }}:{{ postgresql_container_data_dir }}/pg_hba.conf:ro"
- "{{ postgresql_pg_ident_conf_file }}:{{ postgresql_container_data_dir }}/pg_ident.conf:ro"
postgresql_container_unix_socket_volumes:
- "{{ postgresql_unix_socket_path }}:{{ postgresql_container_unix_socket_path }}:rw,rshared"
postgresql_container_initdb_volumes: >-2
{{ postgresql_container_base_volumes
+ postgresql_container_unix_socket_volumes
+ (postgresql_container_volumes | default([], true)) }}
postgresql_container_merged_volumes: >-2
{{ postgresql_container_base_volumes
+ postgresql_container_config_volumes
+ (postgresql_container_unix_socket_volumes if postgresql_config_connect_socket else [])
+ (postgresql_container_volumes | default([], true)) }}
postgresql_systemd_tmpfile_socket_correction_unit_name: >-2
{{ postgresql_container_unix_socket_path | split('/') | reject('eq', '') | join('-') }}
# (Memory) performance tuning
postgresql_container_memory: ~
postgresql_container_memory_reservation: ~
postgresql_container_shm_size: ~
postgresql_container_oom_kill: ~
postgresql_container_oom_score_adj: ~
postgresql_container_ulimits: ~
postgresql_container_user_name: "postgres"
postgresql_unix_socket_path: "{{ postgresql_config_unix_socket }}"
postgresql_container_passwd_file: "{{ postgresql_config_path }}/passwd"
postgresql_container_data_dir: "/var/lib/postgresql/data"

View File

@ -0,0 +1,33 @@
---
postgresql_user: postgresql
postgresql_version: >-2
{{ postgresql_versions[postgresql_major_version | string] }}
postgresql_major_version: 16
postgresql_versions:
"17": "17.2"
"16": "16.6"
"15": "15.10"
"14": "14.15"
postgresql_config_path: >-2
/etc/postgresql/{{ postgresql_major_version }}
postgresql_data_path: >-2
/var/lib/postgresql/{{ postgresql_major_version }}
postgresql_pg_ident_conf_file: >-2
{{ postgresql_config_path }}/pg_ident.conf
postgresql_pg_hba_conf_file: >-2
{{ postgresql_config_path }}/pg_hba.conf
postgresql_admin_role: "postgres"
postgresql_admin_role_contype: local
postgresql_admin_role_method: peer
postgresql_admin_local_user: >-2
{{ ansible_facts['user_id'] }}
postgresql_admin_role_mapping_name: >-2
{{ postgresql_admin_local_user }}_{{ postgresql_admin_role }}
postgresql_admin_pg_ident_conf: "{{ postgresql_admin_role_mapping_name }}\t{{ postgresql_admin_local_user }}\t{{ postgresql_admin_role }}"
postgresql_admin_pg_hba_conf_options: >-2
map={{ postgresql_admin_role_mapping_name }}
postgresql_superuser_password: ~
postgresql_state: present
postgresql_deployment_method: docker

View File

@ -0,0 +1,10 @@
---
postgresql_user_system: true
postgresql_user_create_home: false
postgresql_user_groups: ~
postgresql_user_append: ~
postgresql_user_id: >-2
{{ postgresql_user_info.uid | default(postgresql_user, true) }}
postgresql_user_group_id: >-2
{{ postgresql_user_info.group | default(postgresql_user, true) }}

View File

@ -0,0 +1,12 @@
---
- name: Restart postgresql container '{{ postgresql_container_name }}' (docker)
community.docker.docker_container:
name: "{{ postgresql_container_name }}"
state: "{{ postgresql_container_state }}"
restart: true
comparisons:
'*': "ignore"
when:
- postgresql_deployment_method == 'docker'
- postgresql_container_state not in ['absent', 'stopped']
listen: postgresql_restart

View File

@ -0,0 +1,12 @@
---
allow_duplicates: true
dependencies: []
galaxy_info:
role_name: postgresql
description: >-2
PostgreSQL is the self-proclaimed 'worlds most advanced' open source relational database
galaxy_tags:
- postgresql
- postgres
- database
- docker

View File

@ -0,0 +1,66 @@
---
- name: Configure postgresql
block:
- name: Ensure postgresql superuser is set
community.postgresql.postgresql_user:
name: "{{ postgresql_admin_role }}"
password: "{{ postgresql_superuser_password }}"
login_host: "{{ postgresql_login_host }}"
register: postgresql_superuser_password_result
until: "postgresql_superuser_password_result is succeeded"
retries: 10
delay: 2
- name: Ensure postgresql configuration is set
community.postgresql.postgresql_set:
name: "{{ option.key }}"
value: "{{ pg_option_value }}"
login_host: "{{ postgresql_login_host }}"
login_port: "{{ postgresql_config_port }}"
login_password: "{{ postgresql_superuser_password }}"
loop: "{{ postgresql_merged_config | dict2items }}"
loop_control:
loop_var: option
vars:
pg_option_value: >-2
{{
(option.value | join(' '))
if (option.value is iterable
and option.value is not string
and option.value is not mapping)
else option.value
}}
register: postgresql_config_results
- name: Ensure postgresql configuration is reloaded
community.postgresql.postgresql_query:
db: "postgres"
query: "SELECT pg_reload_conf();"
login_host: "{{ postgresql_login_host }}"
login_port: "{{ postgresql_config_port }}"
login_password: "{{ postgresql_superuser_password }}"
- name: Ensure restart handler is fired if required
debug:
msg: "{{ result.option.key }} changed! Restart required: {{ result.restart_required }}"
when: result.changed
changed_when: "{{ result.restart_required }}"
notify: postgresql_restart
loop: "{{ postgresql_config_results.results }}"
loop_control:
loop_var: result
label: "{{ result.option.key }}"
when: postgresql_state == 'present'
vars:
postgresql_login_host: >-2
{{
(
(postgresql_deployment_method in ['docker'])
| ternary(
postgresql_unix_socket_path,
(postgresql_config_unix_socket_directories | first)
)
)
if postgresql_config_connect_socket else
(postgresql_container_info.container.NetworkSettings.IPAddress)
}}

View File

@ -0,0 +1,97 @@
---
- name: Ensure postgresql container image '{{ postgresql_container_image }}' is {{ postgresql_state }}
community.docker.docker_image:
name: "{{ postgresql_container_image }}"
state: "{{ postgresql_state }}"
source: "{{ postgresql_container_image_source }}"
force_source: "{{ postgresql_container_image_force_source }}"
register: postgresql_container_image_info
until: postgresql_container_image_info is success
retries: 5
delay: 4
- name: Ensure /etc/passwd for container is {{ postgresql_state }}
ansible.builtin.template:
src: "postgresql-passwd.j2"
dest: "{{ postgresql_container_passwd_file }}"
owner: "{{ postgresql_user_id }}"
group: "{{ postgresql_user_group_id }}"
mode: "0640"
when: postgresql_state == 'present'
- name: Ensure systemd unit to correct path permissions is {{ postgresql_state }}
ansible.builtin.copy:
dest: "/etc/systemd/system/{{ postgresql_systemd_tmpfile_socket_correction_unit_name }}.service"
content: |+2
[Unit]
Description="Ensure permissions on {{ postgresql_container_unix_socket_path }}"
After=systemd-tmpfiles-setup.service
Before=docker.service
[Service]
Type=exec
RemainAfterExit=yes
ExecStart=/bin/bash -c 'mkdir {{ postgresql_container_unix_socket_path }} ||:; chown {{ postgresql_user }}:{{ postgresql_user }} {{ postgresql_container_unix_socket_path }}'
[Install]
WantedBy=multi-user.target
when:
- ansible_facts['service_mgr'] == 'systemd'
- postgresql_state == 'present'
register: postgresql_systemd_tmpfile_correction_unit_info
- name: Ensure systemd is reloaded
ansible.builtin.systemd:
daemon_reload: true
when:
- postgresql_systemd_tmpfile_correction_unit_info.changed
- name: Ensure systemd unit {{ postgresql_systemd_tmpfile_socket_correction_unit_name }} is {{ postgresql_container_state }}
ansible.builtin.systemd:
name: "{{ postgresql_systemd_tmpfile_socket_correction_unit_name }}.service"
state: "{{ postgresql_container_state }}"
when: ansible_facts['service_mgr'] == 'systemd'
ignore_errors: "{{ ansible_check_mode }}"
- name: Ensure systemd unit {{ postgresql_systemd_tmpfile_socket_correction_unit_name }} is {{ postgresql_container_state }}
ansible.builtin.systemd:
name: "{{ postgresql_systemd_tmpfile_socket_correction_unit_name }}.service"
enabled: "{{ postgresql_state == 'present' }}"
when: ansible_facts['service_mgr'] == 'systemd'
ignore_errors: "{{ ansible_check_mode }}"
- name: Lookup {{ postgresql_data_path }}/global
ansible.builtin.stat:
path: "{{ postgresql_data_path }}/global"
get_checksum: false
register: postgresql_global_data_info
- name: Initialize database if empty
ansible.builtin.include_tasks:
file: "initialize-docker.yml"
when:
- postgresql_state == 'present'
- not postgresql_global_data_info.stat.exists
- postgresql_global_data_info.stat.isdir is defined
- not postgresql_global_data_info.stat.isdir
- name: Ensure postgresql container '{{ postgresql_container_name }}' is {{ postgresql_container_state }}
community.docker.docker_container:
name: "{{ postgresql_container_name }}"
image: "{{ postgresql_container_image }}"
env: "{{ postgresql_container_env | default(omit, true) }}"
user: "{{ postgresql_container_user | default(omit, true) }}"
ports: "{{ postgresql_container_ports | default(omit, true) }}"
labels: "{{ postgresql_container_labels | default(omit, true) }}"
volumes: "{{ postgresql_container_merged_volumes }}"
recreate: "{{ postgresql_container_recreate | default(omit, true) }}"
networks: "{{ postgresql_container_networks | default(omit, true) }}"
etc_hosts: "{{ postgresql_container_etc_hosts | default(omit, true) }}"
memory: "{{ postgresql_container_memory | default(omit, true) }}"
memory_reservation: "{{ postgresql_container_memory_reservation | default(omit, true) }}"
oom_killer: "{{ postgresql_container_oom_killer | default(omit, true) }}"
oom_score_adj: "{{ postgresql_container_oom_score_adj | default(omit, true) }}"
shm_size: "{{ postgresql_container_shm_size | default(omit, true) }}"
ulimits: "{{ postgresql_container_ulimits | default(omit, true) }}"
restart_policy: "{{ postgresql_container_restart_policy | default(omit, true) }}"
state: "{{ postgresql_container_state }}"

View File

@ -0,0 +1,47 @@
---
- name: Ensure container '{{ postgresql_container_name }}' is {{ postgresql_container_state }} to initialise the database
community.docker.docker_container:
name: "{{ postgresql_container_name }}"
image: "{{ postgresql_container_image }}"
env: >-2
{{ postgresql_container_env | default({}, true)
| combine({'POSTGRES_PASSWORD': postgresql_superuser_password}) }}
user: "{{ postgresql_container_user | default(omit, true) }}"
ports: "{{ postgresql_container_ports | default(omit, true) }}"
labels: "{{ postgresql_container_labels | default(omit, true) }}"
volumes: "{{ postgresql_container_initdb_volumes }}"
recreate: "{{ postgresql_container_recreate | default(omit, true) }}"
networks: "{{ postgresql_container_networks | default(omit, true) }}"
etc_hosts: "{{ postgresql_container_etc_hosts | default(omit, true) }}"
memory: "{{ postgresql_container_memory | default(omit, true) }}"
memory_reservation: "{{ postgresql_container_memory_reservation | default(omit, true) }}"
oom_killer: "{{ postgresql_container_oom_killer | default(omit, true) }}"
oom_score_adj: "{{ postgresql_container_oom_score_adj | default(omit, true) }}"
shm_size: "{{ postgresql_container_shm_size | default(omit, true) }}"
ulimits: "{{ postgresql_container_ulimits | default(omit, true) }}"
restart_policy: "{{ postgresql_container_restart_policy | default(omit, true) }}"
state: "{{ postgresql_container_state }}"
register: postgresql_container_info
- name: Wait for container startup
block:
- name: Wait for container startup (socket)
ansible.builtin.wait_for:
path: "{{ postgresql_config_unix_socket_directories | first }}/.s.PGSQL.{{ postgresql_config_port }}"
when: "postgresql_config_connect_socket | bool"
- name: Wait for container startup (port)
ansible.builtin.wait_for:
host: >-2
{{ (pg_addresses == '*') | ternary(
omit,
postgresql_config_listen_addresses | first
) }}
port: "{{ postgresql_config_port }}"
when: "not postgresql_config_connect_socket | bool"
vars:
pg_addresses: "{{ postgresql_config_listen_addresses | join(',') }}"
- name: Ensure init container '{{ postgresql_container_name }}' is removed
community.docker.docker_container:
name: "{{ postgresql_container_name }}"
state: absent

View File

@ -0,0 +1,72 @@
---
- name: Ensure state is valid
ansible.builtin.fail:
msg: >-2
Invalid state '{{ postgresql_state }}'! Supported
states are {{ postgresql_states | join(', ') }}.
when: postgresql_state not in postgresql_states
- name: Ensure deployment method is valid
ansible.builtin.fail:
msg: >-2
Unsupported deployment method '{{ postgresql_deployment_method }}!
Supported deployment methods are {{ postgresql_deployment_methods | join(', ') }}.
when: postgresql_deployment_method not in postgresql_deployment_methods
- name: Ensure postgresql user '{{ postgresql_user }}' is {{ postgresql_state }}
ansible.builtin.user:
name: "{{ postgresql_user }}"
state: "{{ postgresql_state }}"
system: "{{ postgresql_user_system | default(omit, true) }}"
create_home: "{{ postgresql_user_create_home | default(omit, true) }}"
groups: "{{ postgresql_user_groups | default(omit, true) }}"
append: "{{ postgresql_user_append | default(omit, true) }}"
register: postgresql_user_info
- name: Ensure directories are {{ postgresql_state }}
ansible.builtin.file:
path: "{{ path.name }}"
state: "{{ (postgresql_state == 'present') | ternary('directory', 'absent') }}"
owner: "{{ path.owner | default(postgresql_user_id, true) }}"
group: "{{ path.group | default(postgresql_user_group_id, true) }}"
mode: "{{ path.mode | default('0755', true) }}"
loop:
- name: "{{ postgresql_config_path }}"
- name: "{{ postgresql_data_path }}"
mode: "0700"
loop_control:
loop_var: path
label: "{{ path.name }}"
- name: Check for existing PG_VERSION file
ansible.builtin.stat:
path: "{{ postgresql_data_path }}/PG_VERSION"
register: postgresql_data_dir_version_info
- name: Read existing PG_VERSION file
ansible.builtin.slurp:
path: "{{ postgresql_data_path }}/PG_VERSION"
register: postgresql_data_dir_version_content
when:
- postgresql_data_dir_version_info.stat.exists
- name: Prevent major version changes
ansible.builtin.fail:
msg: >-2
Mismatched postgresql version for the data directory!
Aborting...
when:
- postgresql_data_dir_version_info.stat.exists
- "(postgresql_data_dir_version_content.content | b64decode | int) != (postgresql_major_version | int)"
- name: Prepare authentication and authorization for database admin role
ansible.builtin.include_tasks:
file: "prepare.yml"
- name: Deploy postgresql using {{ postgresql_deployment_method }}
ansible.builtin.include_tasks:
file: "deploy-{{ postgresql_deployment_method }}.yml"
- name: Configure postgresql
ansible.builtin.include_tasks:
file: "configure.yml"

View File

@ -0,0 +1,35 @@
---
- name: Ensure postgresql config files are {{ postgresql_state }}
ansible.builtin.lineinfile:
path: "{{ file.name }}"
insertafter: "{{ file.insert_after | default(omit) }}"
insertbefore: "{{ file.insert_before | default(omit) }}"
line: "{{ file.line }}"
owner: "{{ postgresql_user_id }}"
group: "{{ postgresql_user_group_id }}"
create: true
loop_control:
loop_var: file
label: "{{ file.name }}"
loop:
- name: "{{ postgresql_pg_hba_conf_file }}"
insert_before: "BOF"
line: "# Ansible managed"
- name: "{{ postgresql_pg_ident_conf_file }}"
insert_before: "BOF"
line: "# Ansible managed"
- name: "{{ postgresql_pg_ident_conf_file }}"
insert_after: "# Ansible managed"
line: "{{ postgresql_admin_pg_ident_conf }}"
when: postgresql_state == 'present'
notify: postgresql_restart
- name: Configure permissions for postgresql admin role
community.postgresql.postgresql_pg_hba:
dest: "{{ postgresql_pg_hba_conf_file }}"
contype: "{{ postgresql_admin_role_contype }}"
users: "{{ postgresql_admin_role }}"
method: "{{ postgresql_admin_role_method }}"
options: "{{ postgresql_admin_pg_hba_conf_options }}"
when: postgresql_state == 'present'
notify: postgresql_restart

View File

@ -0,0 +1,19 @@
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
{{ postgresql_container_user_name }}:x:{{ postgresql_user_id }}:{{ postgresql_user_group_id }}::/var/lib/postgresql:/bin/bash

View File

@ -0,0 +1,6 @@
---
postgresql_states:
- present
- absent
postgresql_deployment_methods:
- docker

47
roles/redis/README.md Normal file
View File

@ -0,0 +1,47 @@
# `finallycoffee.databases.redis` ansible role
Redis is the self-proclaimed world's fastest data platform for caching,
vector search and NoSQL databases. Since version 7.2.4, it is no longer
considered "Free and open source software" (FOSS), with redis switching
their license to the "Serverside public license" (SSPL).
Setting the `redis_version` to higher than `7.2.4` means you will deploy
the SSPL-licensed version to redis.
## Configuration
All container-related options to the `docker_container` ansible module
are available under the `redis_container_*` namespace, for example use
`redis_container_ports: [ '127.0.0.1:6379:6370/tcp' ]` to map the
containers port 6379 to the docker host.
Redis-related config options are either available in the `redis_config_*`
namespace or can be specified by setting them as a dictionary in
`redis_config`
### Authentication and authorization
Redis ACL can be specified as an array in the `redis_config_user` variable
- see [the redis documentation](https://github.com/redis/redis/blob/unstable/redis.conf#L869)
for the format. Per default, the `default` user is able to connect without
any password. To require a password and use a different user, override
the variable, for example `redis_config_user: [ 'username on +@all -DEBUG ~* >secret' ]`.
## Redis on a unix socket
To make redis available on a unix socket, a directory must be supplied in which the
socket lives:
```yaml
redis_container_socket: /var/run/redis.sock
redis_container_volumes:
- "/path/to/socket/on/host/redis.sock:{{ redis_container_socket }}:z"
redis_config_unixsocket: "{{ redis_container_socket }}"
```
## Container specific information
Redis publishes their official container image in both a debian-based and an
alpine-based variant. Which image should be used can be configured in
`redis_container_image_flavour`, which defaults to `alpine`, which is smaller
in size but also includes less related / debugging tools. To use the debian-
based image, unset the flavour using `redis_container_image_flavour: ~`.

View File

@ -0,0 +1,41 @@
---
redis_config_bind:
- "127.0.0.1"
- "-::1"
redis_config_protected_mode: true
redis_config_port: 6379
redis_config_unixsocket: ~
redis_config_unixsocketperm: '700'
redis_config_user:
- "default on +@all -DEBUG ~* nopass"
redis_config_databases: 16
redis_config_supervised: false
redis_config_daemonize: false
redis_config_dbfilename: dump.rdb
redis_config_dir: "{{ redis_data_path }}"
redis_config_save: "3600 1 300 100 60 10000"
redis_config_appendfsync: everysec
redis_base_config:
bind: "{{ redis_config_bind | join(' ') }}"
"protected-mode": "{{ redis_config_protected_mode | bool | ternary('yes', 'no') }}"
port: "{{ redis_config_port }}"
user: "{{ redis_config_user }}"
databases: "{{ redis_config_databases }}"
daemonize: "{{ redis_config_daemonize | bool | ternary('yes', 'no') }}"
supervised: "{{ redis_config_supervised | bool | ternary('yes', 'no') }}"
save: "{{ redis_config_save }}"
dbfilename: "{{ redis_config_dbfilename }}"
dir: "{{ redis_config_dir }}"
appendfsync: "{{ redis_config_appendfsync }}"
redis_config: ~
redis_merged_config: >-2
{{ redis_base_config
| combine(({
'unixsocket': redis_config_unixsocket,
'unixsocketperm': redis_config_unixsocketperm,
})
if (redis_config_unixsocket | default(false, true)) else {},
recursive=True)
| combine(redis_config | default({}, true), recursive=True) }}

View File

@ -0,0 +1,49 @@
---
redis_container_image_registry: docker.io
redis_container_image_namespace: ~
redis_container_image_name: redis
redis_container_image_tag: ~
redis_container_image_flavour: alpine
redis_container_image_source: pull
redis_container_image_force_source: >-2
{{ redis_container_image_tag | default(false, true) | bool }}
redis_container_image: >-2
{{
([
redis_container_image_registry | default([], true),
redis_container_image_namespace | default([], true),
redis_container_image_name,
] | flatten | join('/'))
+ ':' +
(redis_container_image_tag | default(
redis_version + (
((redis_container_image_flavour is string)
and (redis_container_image_flavour | length > 0))
| ternary('-' + (redis_container_image_flavour | default('')), '')
),
true,
))
}}
redis_container_name: "redis{{ redis_instance_suffix }}"
redis_container_env: ~
redis_container_user: >-2
{{ redis_run_user_id }}:{{ redis_run_group_id }}
redis_container_ports: ~
redis_container_labels: ~
redis_container_volumes: ~
redis_container_merged_volumes: >-2
{{ redis_container_base_volumes
+ redis_container_volumes | default([], true) }}
redis_container_command:
- "redis-server"
- "{{ redis_config_file }}"
redis_container_networks: ~
redis_container_etc_hosts: ~
redis_container_dns_servers: ~
redis_container_restart_policy: "unless-stopped"
redis_container_state: >-2
{{ (redis_state == 'present') | ternary('started', 'absent') }}
redis_container_base_volumes:
- "{{ redis_config_file }}:{{ redis_config_file }}:ro"
- "{{ redis_data_path }}:{{ redis_data_path }}:rw"

View File

@ -0,0 +1,15 @@
---
redis_version: "7.2.4"
redis_state: "present"
redis_instance: ~
redis_instance_suffix: >-2
{{ ((redis_instance is string) and (redis_instance | length > 0))
| ternary('-' + (redis_instance | default('', true)), '') }}
redis_user: >-2
redis{{ redis_instance_suffix }}
redis_config_path: "/etc/redis"
redis_config_file: >-2
{{ redis_config_path }}/redis{{ redis_instance_suffix }}.conf
redis_data_path: "/var/lib/redis{{ redis_instance_suffix }}"
redis_deployment_method: docker

View File

@ -0,0 +1,10 @@
---
redis_run_user_id: >-2
{{ redis_user_info.uid | default(redis_user, true) }}
redis_run_group_id: >-2
{{ redis_user_info.group | default(redis_user, true) }}
redis_user_system: true
redis_user_create_home: false
redis_user_groups: ~
redis_user_append_groups: >-2
{{ redis_user_groups | default(true, false) | bool }}

View File

@ -0,0 +1,11 @@
---
- name: Ensure redis container '{{ redis_container_name }}' is restarted
community.docker.docker_container:
name: "{{ redis_container_name }}"
state: "{{ redis_container_state }}"
restart: true
listen: redis-restart
when:
- redis_deployment_method == 'docker'
- redis_state == 'present'
ignore_errors: "{{ ansible_check_mode }}"

10
roles/redis/meta/main.yml Normal file
View File

@ -0,0 +1,10 @@
---
allow_duplicates: true
dependencies: []
galaxy_info:
role_name: redis
description: >-2
Deploy and configure redis, a fast caching, vector-search and NoSQL database.
galaxy_tags:
- redis
- docker

View File

@ -0,0 +1,27 @@
---
- name: Ensure container image '{{ redis_container_image }}' is {{ redis_state }}
community.docker.docker_image:
name: "{{ redis_container_image }}"
state: "{{ redis_state }}"
source: "{{ redis_container_image_source }}"
force_source: "{{ redis_container_image_force_source }}"
register: redis_container_image_info
until: redis_container_image_info is success
retries: 5
delay: 3
- name: Ensure container '{{ redis_container_name }}' is {{ redis_container_state }}
community.docker.docker_container:
name: "{{ redis_container_name }}"
image: "{{ redis_container_image }}"
env: "{{ redis_container_env | default(omit, true) }}"
user: "{{ redis_container_user }}"
ports: "{{ redis_container_ports | default(omit, true) }}"
labels: "{{ redis_container_labels | default(omit, true) }}"
command: "{{ redis_container_command }}"
volumes: "{{ redis_container_merged_volumes }}"
networks: "{{ redis_container_networks | default(omit, true) }}"
etc_hosts: "{{ redis_container_etc_hosts | default(omit, true) }}"
dns_servers: "{{ redis_container_dns_servers | default(omit, true) }}"
restart_policy: "{{ redis_container_restart_policy | default(omit, true) }}"
state: "{{ redis_container_state }}"

View File

@ -0,0 +1,68 @@
---
- name: Ensure state is valid
ansible.builtin.fail:
msg: >-2
Unsupported state '{{ redis_state }}'.
Supported states are {{ redis_states | join(', ') }}
when: redis_state not in redis_states
- name: Ensure deployment method is valid
ansible.builtin.fail:
msg: >-2
Unsupported deployment method '{{ redis_deployment_method }}'!
Supported methods are {{ redis_deployment_method | join(', ') }}
when: redis_deployment_method not in redis_deployment_methods
- name: Ensure redis user '{{ redis_user }}' is {{ redis_state }}
ansible.builtin.user:
name: "{{ redis_user }}"
state: "{{ redis_state }}"
system: "{{ redis_user_system }}"
create_home: "{{ redis_user_create_home }}"
groups: "{{ redis_user_groups | default(omit, true) }}"
append: "{{ redis_user_append_groups | default(omit, true) }}"
register: redis_user_info
- name: Ensure redis config file '{{ redis_config_file }}' is {{ redis_state }}
ansible.builtin.file:
path: "{{ redis_config_file }}"
state: "{{ redis_state }}"
when: redis_state == 'absent'
- name: Ensure redis host directories are {{ redis_state }}
ansible.builtin.file:
path: "{{ path.name }}"
state: >-2
{{ (redis_state == 'present') | ternary('directory', 'absent') }}
owner: "{{ path.owner | default(redis_run_user_id) }}"
group: "{{ path.group | default(redis_run_group_id) }}"
mode: "{{ path.mode | default('0755') }}"
loop:
- name: "{{ redis_config_path }}"
- name: "{{ redis_data_path }}"
loop_control:
loop_var: "path"
label: "{{ path.name }}"
- name: Ensure redis config file '{{ redis_config_file }}' is {{ redis_state }}
ansible.builtin.copy:
content: |+2
{% for tuple in (redis_merged_config | dict2items) %}
{% if tuple.value is string or tuple.value is number %}
{{ tuple.key }} {{ tuple.value }}
{% else %}
{% for value in tuple.value %}
{{ tuple.key }} {{ value }}
{% endfor %}
{% endif %}
{% endfor %}
dest: "{{ redis_config_file }}"
owner: "{{ redis_run_user_id }}"
group: "{{ redis_run_group_id }}"
mode: "0640"
when: redis_state == 'present'
notify: redis-restart
- name: Deploy redis using {{ redis_deployment_method }}
ansible.builtin.include_tasks:
file: "deploy-{{ redis_deployment_method }}.yml"

View File

@ -0,0 +1,6 @@
---
redis_states:
- present
- absent
redis_deployment_methods:
- docker

13
roles/valkey/README.md Normal file
View File

@ -0,0 +1,13 @@
# `finallycoffee.databases.valkey` ansible role
Valkey is an open source (BSD 3 licensed), high-performance in-memory key/value
data store, ideal for workloads like caching or message queues. It has been
forked from redis 7.2.4 before redis license was changed to SSPL.
Valkey offers compatibility to redis and can be used as a drop-in replacement
for redis.
## Configuration
For the configuration, see the [`redis` role configuration](../redis/README.md#configuration),
and swap the `redis_` prefix of all variables for the `valkey_` prefix.

View File

@ -0,0 +1,41 @@
---
valkey_config_bind:
- "127.0.0.1"
- "-::1"
valkey_config_protected_mode: true
valkey_config_port: 6379
valkey_config_unixsocket: ~
valkey_config_unixsocketperm: '700'
valkey_config_user:
- "default on +@all -DEBUG ~* nopass"
valkey_config_databases: 16
valkey_config_supervised: false
valkey_config_daemonize: false
valkey_config_dbfilename: dump.rdb
valkey_config_dir: "{{ valkey_data_path }}"
valkey_config_save: "3600 1 300 100 60 10000"
valkey_config_appendfsync: everysec
valkey_base_config:
bind: "{{ valkey_config_bind | join(' ') }}"
"protected-mode": "{{ valkey_config_protected_mode | bool | ternary('yes', 'no') }}"
port: "{{ valkey_config_port }}"
user: "{{ valkey_config_user }}"
databases: "{{ valkey_config_databases }}"
daemonize: "{{ valkey_config_daemonize | bool | ternary('yes', 'no') }}"
supervised: "{{ valkey_config_supervised | bool | ternary('yes', 'no') }}"
save: "{{ valkey_config_save }}"
dbfilename: "{{ valkey_config_dbfilename }}"
dir: "{{ valkey_config_dir }}"
appendfsync: "{{ valkey_config_appendfsync }}"
valkey_config: ~
valkey_merged_config: >-2
{{ valkey_base_config
| combine(({
'unixsocket': valkey_config_unixsocket,
'unixsocketperm': valkey_config_unixsocketperm,
})
if (valkey_config_unixsocket | default(false, true)) else {},
recursive=True)
| combine(valkey_config | default({}, true), recursive=True) }}

View File

@ -0,0 +1,49 @@
---
valkey_container_image_registry: docker.io
valkey_container_image_namespace: valkey
valkey_container_image_name: valkey
valkey_container_image_tag: ~
valkey_container_image_flavour: alpine
valkey_container_image_source: pull
valkey_container_image_force_source: >-2
{{ valkey_container_image_tag | default(false, true) | bool }}
valkey_container_image: >-2
{{
([
valkey_container_image_registry | default([], true),
valkey_container_image_namespace | default([], true),
valkey_container_image_name,
] | flatten | join('/'))
+ ':' +
(valkey_container_image_tag | default(
valkey_version + (
((valkey_container_image_flavour is string)
and (valkey_container_image_flavour | length > 0))
| ternary('-' + (valkey_container_image_flavour | default('')), '')
),
true,
))
}}
valkey_container_name: "valkey{{ valkey_instance_suffix }}"
valkey_container_env: ~
valkey_container_user: >-2
{{ valkey_run_user_id }}:{{ valkey_run_group_id }}
valkey_container_ports: ~
valkey_container_labels: ~
valkey_container_volumes: ~
valkey_container_merged_volumes: >-2
{{ valkey_container_base_volumes
+ valkey_container_volumes | default([], true) }}
valkey_container_command:
- "valkey-server"
- "{{ valkey_config_file }}"
valkey_container_networks: ~
valkey_container_etc_hosts: ~
valkey_container_dns_servers: ~
valkey_container_restart_policy: "unless-stopped"
valkey_container_state: >-2
{{ (valkey_state == 'present') | ternary('started', 'absent') }}
valkey_container_base_volumes:
- "{{ valkey_config_file }}:{{ valkey_config_file }}:ro"
- "{{ valkey_data_path }}:{{ valkey_data_path }}:rw"

View File

@ -0,0 +1,17 @@
---
valkey_version: "8.1.1"
valkey_state: "present"
valkey_instance: ~
valkey_instance_suffix: >-2
{{ ((valkey_instance is string) and (valkey_instance | length > 0))
| ternary('-' + (valkey_instance | default('', true)), '') }}
valkey_user: >-2
valkey{{ valkey_instance_suffix }}
valkey_config_path: "/etc/valkey"
valkey_config_path_owner: "root"
valkey_config_path_group: "root"
valkey_config_file: >-2
{{ valkey_config_path }}/valkey{{ valkey_instance_suffix }}.conf
valkey_data_path: "/var/lib/valkey{{ valkey_instance_suffix }}"
valkey_deployment_method: docker

View File

@ -0,0 +1,10 @@
---
valkey_run_user_id: >-2
{{ valkey_user_info.uid | default(valkey_user, true) }}
valkey_run_group_id: >-2
{{ valkey_user_info.group | default(valkey_user, true) }}
valkey_user_system: true
valkey_user_create_home: false
valkey_user_groups: ~
valkey_user_append_groups: >-2
{{ valkey_user_groups | default(true, false) | bool }}

View File

@ -0,0 +1,11 @@
---
- name: Ensure valkey container '{{ valkey_container_name }}' is restarted
community.docker.docker_container:
name: "{{ valkey_container_name }}"
state: "{{ valkey_container_state }}"
restart: true
listen: valkey-restart
when:
- valkey_deployment_method == 'docker'
- valkey_state == 'present'
ignore_errors: "{{ ansible_check_mode }}"

View File

@ -0,0 +1,11 @@
---
allow_duplicates: true
dependencies: []
galaxy_info:
role_name: valkey
description: >-2
An open source, in-memory datastore under BSD 3 license
galaxy_tags:
- valkey
- redis
- docker

View File

@ -0,0 +1,27 @@
---
- name: Ensure container image '{{ valkey_container_image }}' is {{ valkey_state }}
community.docker.docker_image:
name: "{{ valkey_container_image }}"
state: "{{ valkey_state }}"
source: "{{ valkey_container_image_source }}"
force_source: "{{ valkey_container_image_force_source }}"
register: valkey_container_image_info
until: valkey_container_image_info is success
retries: 5
delay: 3
- name: Ensure container '{{ valkey_container_name }}' is {{ valkey_container_state }}
community.docker.docker_container:
name: "{{ valkey_container_name }}"
image: "{{ valkey_container_image }}"
env: "{{ valkey_container_env | default(omit, true) }}"
user: "{{ valkey_container_user }}"
ports: "{{ valkey_container_ports | default(omit, true) }}"
labels: "{{ valkey_container_labels | default(omit, true) }}"
command: "{{ valkey_container_command }}"
volumes: "{{ valkey_container_merged_volumes }}"
networks: "{{ valkey_container_networks | default(omit, true) }}"
etc_hosts: "{{ valkey_container_etc_hosts | default(omit, true) }}"
dns_servers: "{{ valkey_container_dns_servers | default(omit, true) }}"
restart_policy: "{{ valkey_container_restart_policy | default(omit, true) }}"
state: "{{ valkey_container_state }}"

View File

@ -0,0 +1,70 @@
---
- name: Ensure state is valid
ansible.builtin.fail:
msg: >-2
Unsupported state '{{ valkey_state }}'.
Supported states are {{ valkey_states | join(', ') }}
when: valkey_state not in valkey_states
- name: Ensure deployment method is valid
ansible.builtin.fail:
msg: >-2
Unsupported deployment method '{{ valkey_deployment_method }}'!
Supported methods are {{ valkey_deployment_method | join(', ') }}
when: valkey_deployment_method not in valkey_deployment_methods
- name: Ensure valkey user '{{ valkey_user }}' is {{ valkey_state }}
ansible.builtin.user:
name: "{{ valkey_user }}"
state: "{{ valkey_state }}"
system: "{{ valkey_user_system }}"
create_home: "{{ valkey_user_create_home }}"
groups: "{{ valkey_user_groups | default(omit, true) }}"
append: "{{ valkey_user_append_groups | default(omit, true) }}"
register: valkey_user_info
- name: Ensure valkey config file '{{ valkey_config_file }}' is {{ valkey_state }}
ansible.builtin.file:
path: "{{ valkey_config_file }}"
state: "{{ valkey_state }}"
when: valkey_state == 'absent'
- name: Ensure valkey host directories are {{ valkey_state }}
ansible.builtin.file:
path: "{{ path.name }}"
state: >-2
{{ (valkey_state == 'present') | ternary('directory', 'absent') }}
owner: "{{ path.owner | default(valkey_run_user_id) }}"
group: "{{ path.group | default(valkey_run_group_id) }}"
mode: "{{ path.mode | default('0755') }}"
loop:
- name: "{{ valkey_config_path }}"
owner: "{{ valkey_config_path_owner }}"
group: "{{ valkey_config_path_group }}"
- name: "{{ valkey_data_path }}"
loop_control:
loop_var: "path"
label: "{{ path.name }}"
- name: Ensure valkey config file '{{ valkey_config_file }}' is {{ valkey_state }}
ansible.builtin.copy:
content: |+2
{% for tuple in (valkey_merged_config | dict2items) %}
{% if tuple.value is string or tuple.value is number %}
{{ tuple.key }} {{ tuple.value }}
{% else %}
{% for value in tuple.value %}
{{ tuple.key }} {{ value }}
{% endfor %}
{% endif %}
{% endfor %}
dest: "{{ valkey_config_file }}"
owner: "{{ valkey_run_user_id }}"
group: "{{ valkey_run_group_id }}"
mode: "0640"
when: valkey_state == 'present'
notify: valkey-restart
- name: Deploy valkey using {{ valkey_deployment_method }}
ansible.builtin.include_tasks:
file: "deploy-{{ valkey_deployment_method }}.yml"

View File

@ -0,0 +1,6 @@
---
valkey_states:
- present
- absent
valkey_deployment_methods:
- docker