Compare commits

..

7 Commits

Author SHA1 Message Date
uumas
accd5ece14 small improvements 2026-02-13 02:00:55 +02:00
uumas
58ff2f6217 service: Add support for native sockets for http 2026-02-13 02:00:44 +02:00
uumas
4079b69338 Add gitignore for release archives 2026-02-12 20:05:09 +02:00
uumas
c7e26555b7 v0.1.1 2026-02-12 20:04:38 +02:00
uumas
07925caa95 Rename runtime.yaml to runtime.yml 2026-02-12 20:02:12 +02:00
uumas
de707b4e71 service: Add support for mariadb 2026-02-12 20:01:52 +02:00
uumas
0ee8e9b254 Add support for container devices 2026-01-24 17:12:57 +02:00
23 changed files with 131 additions and 15 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
uumas-podman-*.tar.gz

View File

@@ -3,7 +3,7 @@ namespace: uumas
name: podman
description: Roles for installing services in podman containers
readme: README.md
version: 0.1.0
version: 0.1.1
repository: "https://git.uumas.fi/uumas/ansible-podman"
license_file: LICENSE
authors:

View File

@@ -3,6 +3,7 @@ container_command: []
container_entrypoint: ""
container_user: ""
container_mounts: []
container_devices: []
container_publish_ports: []
container_networks: []
container_ip: ""

View File

@@ -92,6 +92,21 @@ argument_specs:
required: false
default: []
container_devices:
description: List of devices to be added inside the container.
type: list
required: false
default: []
elements: dict
options:
source:
description: Device path on host
type: str
required: true
destination:
description: Device path inside the container. Defaults to same as host.
type: str
required: false
container_publish_ports:
description: "A list of published ports in docker format (<host listen address>:<host port>:<container port>)"
type: list

View File

@@ -48,6 +48,7 @@
entrypoint: "{{ container_entrypoint or omit }}"
user: "{{ container_user or omit }}"
mount: "{{ _container_mounts | map('items') | map('map', 'join', '=') | map('join', ',') }}"
device: "{{ _container_devices }}"
network: "{{ _container_networks_with_ip }}"
publish: "{{ container_publish_ports }}"
secrets: "{{ _container_secrets }}"

View File

@@ -49,6 +49,25 @@ _container_mounts: >-
| zip(_container_volume_mount_sources) | map('combine')
}}
_container_devices_withdefaults: >-
{{
container_devices
| map(attribute='source')
| map('community.general.dict_kv', 'destination')
| zip(container_devices)
| map('combine')
}}
_container_devices: >-
{{
_container_devices_withdefaults
| map(attribute='source')
| zip(
_container_devices_withdefaults
| map(attribute='destination')
)
| map('join', ':')
}}
_container_secrets: >-
{{
container_secrets

View File

@@ -1,5 +1,5 @@
---
- name: Hello world container
- name: Hello world service
ansible.builtin.import_role:
name: service
vars:
@@ -27,6 +27,9 @@
- network-online.target
service_container_env:
TZ: "Etc/UTC"
DB_HOST: hello-world-db
DB_USER: hello-world
DB_PASSWORD__FILE: /run/secrets/postgres
service_additional_containers:
- name: worker
# image: "docker.io/library/hello-world:latest"

View File

@@ -9,7 +9,7 @@
ip_range: "{{ network_range if network_range | length > 0 else omit }}"
quadlet_options: >-
{{
['Options=parent=' ~ ansible_default_ipv4.interface]
['Options=parent=' ~ ansible_facts.default_ipv4.interface]
if network_driver == 'macvlan' else []
}}
notify: Restart network service {{ network_name }}

View File

@@ -10,6 +10,7 @@
name: podman-auto-update.timer
state: started
enabled: true
ignore_errors: "{{ ansible_check_mode }}"
- name: Login to registries
containers.podman.podman_login:

View File

@@ -13,6 +13,7 @@ service_container_additional_networks: []
service_container_user: ""
service_container_publish_ports: []
service_container_mounts: []
service_container_devices: []
service_container_secrets: []
service_container_env: {}

View File

@@ -1,4 +1,11 @@
---
- name: Restart socket for {{ service_name }}
ansible.builtin.systemd_service:
name: "{{ service_name }}.socket"
state: restarted
daemon_reload: true
ignore_errors: '{{ ansible_check_mode }}'
- name: Restart socat socket for {{ service_name }}
ansible.builtin.systemd_service:
name: "{{ service_name }}-socat.socket"

View File

@@ -28,8 +28,10 @@ argument_specs:
elements: str
service_container_http_port:
description:
- Port inside the container where http requests will be proxied to.
- Required if service_domains is not empty.
- Port inside the container where http requests are proxied to.
- >-
If set to 0, /run/{{ service_name }}.sock on the host is bind mounted to /run/{{ service_name }}.sock inside the container
and http requests are proxied to it.
type: int
required: false
default: 0
@@ -169,6 +171,21 @@ argument_specs:
elements: str
required: false
default: []
service_container_devices:
description: List of devices to be added inside the service main container.
type: list
required: false
default: []
elements: dict
options:
source:
description: Device path on host
type: str
required: true
destination:
description: Device path inside the container. Defaults to same as host.
type: str
required: false
service_container_secrets:
description:
- >
@@ -236,6 +253,7 @@ argument_specs:
type: str
choices:
- postgres
- mariadb
- none
required: false
default: none

View File

@@ -1,22 +1,23 @@
---
- name: Incude variables for database {{ service_database_type }}
ansible.builtin.include_vars:
file: database/{{ service_database_type }}.yaml
- name: Database container for {{ service_name }}
ansible.builtin.import_role:
name: container
vars:
container_name: "{{ service_name }}-{{ service_database_type }}" # This doesn't use _service_database_name to allow container role handlers to work
container_image: "{{ service_postgres_image }}:{{ service_postgres_tag }}"
container_image: "{{ _service_database_image }}"
container_mounts:
- type: volume
source: "{{ _service_database_name }}"
destination: /var/lib/postgresql/data
destination: "{{ _service_database_mount_destination }}"
container_networks: "{{ _service_database_networks }}"
container_ip: >-
{{ service_container_ip | ansible.utils.ipmath(1) if _service_static_ip else '' }}
container_secrets:
- name: "{{ _service_database_name }}"
target: "{{ service_database_type }}"
container_env:
POSTGRES_USER: "{{ service_name | replace('-', '_') }}"
POSTGRES_PASSWORD_FILE: "/run/secrets/{{ service_database_type }}"
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
container_env: "{{ _service_database_env }}"
container_auto_update: "{{ service_auto_update }}"

View File

@@ -22,6 +22,10 @@
ansible.builtin.include_tasks: additional.yaml
when: _service_additional_containers | length > 0
- name: Native socket for {{ service_name }}
ansible.builtin.include_tasks: native_socket.yaml
when: _service_native_socket
- name: Main container for {{ service_name }}
ansible.builtin.import_role:
name: container
@@ -32,6 +36,7 @@
container_entrypoint: "{{ service_container_entrypoint }}"
container_user: "{{ service_container_user }}"
container_mounts: "{{ _service_container_mounts }}"
container_devices: "{{ service_container_devices }}"
container_publish_ports: "{{ service_container_publish_ports }}"
container_networks: "{{ _service_container_networks }}"
container_ip: "{{ service_container_ip }}"

View File

@@ -0,0 +1,7 @@
---
- name: Socket for {{ service_name }}
ansible.builtin.template:
src: service.socket.j2
dest: /etc/systemd/system/{{ service_name }}.socket
mode: "0644"
notify: Restart socket for {{ service_name }}

View File

@@ -11,7 +11,7 @@
vhost_id: "{{ service_name }}"
vhost_domains: "{{ service_domains }}"
vhost_proxy_target_netproto: unix
vhost_proxy_target_socket: "/run/{{ service_name }}-socat.sock"
vhost_proxy_target_socket: "{{ _service_socket_path }}"
vhost_proxy_headers: "{{ _service_proxy_headers }}"
vhost_proxy_auth_socket: "{{ _service_oauth2_socket }}"
vhost_proxy_auth_uri: /oauth2/auth

View File

@@ -0,0 +1,6 @@
# {{ ansible_managed }}
[Unit]
Description={{ service_name }} socket
[Socket]
ListenStream=/run/{{ service_name }}.sock

View File

@@ -0,0 +1,8 @@
---
_service_database_image: docker.io/library/mariadb:lts
_service_database_mount_destination: /var/lib/mysql
_service_database_env:
MARIADB_RANDOM_ROOT_PASSWORD: "1"
MARIADB_USER: "{{ service_name | replace('-', '_') }}"
MARIADB_DATABASE: "{{ service_name | replace('-', '_') }}"
MARIADB_PASSWORD_FILE: "/run/secrets/{{ service_database_type }}"

View File

@@ -0,0 +1,7 @@
---
_service_database_image: "{{ service_postgres_image }}:{{ service_postgres_tag }}"
_service_database_mount_destination: /var/lib/postgresql/data
_service_database_env:
POSTGRES_USER: "{{ service_name | replace('-', '_') }}"
POSTGRES_PASSWORD_FILE: "/run/secrets/{{ service_database_type }}"
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"

View File

@@ -5,8 +5,9 @@ _service_static_ip: "{{ service_container_ip | length > 0 }}"
_service_container_requires: >-
{{
service_requires
+ ([_service_database_name + '.service'] if _service_setup_database else [])
+ ([service_name + '-redis.service'] if service_redis else [])
+ ([_service_database_name ~ '.service'] if _service_setup_database else [])
+ ([service_name ~ '-redis.service'] if service_redis else [])
+ ([service_name ~ '.socket'] if _service_native_socket else [])
}}
_service_container_wants: >-
{{

View File

@@ -1,4 +1,9 @@
---
_service_container_socket_mount:
type: bind
source: /run/{{ service_name }}
destination: /run/{{ service_name }}
_service_volume_mounts: "{{ service_container_mounts | selectattr('type', '==', 'volume') }}"
_service_template_mounts: "{{ service_container_mounts | selectattr('type', '==', 'template') }}"
_service_copy_mounts: "{{ service_container_mounts | selectattr('type', '==', 'copy') }}"
@@ -15,7 +20,11 @@ _service_container_volume_mounts: >-
) |
map('combine')
}}
_service_container_bind_mounts: "{{ service_container_mounts | selectattr('type', '==', 'bind') }}"
_service_container_bind_mounts: >-
{{
service_container_mounts | selectattr('type', '==', 'bind') +
([ _service_container_socket_mount ] if _service_native_socket else [])
}}
_service_container_template_mounts: >-
{{
([{'readonly': true}] * _service_template_mounts | length) |

View File

@@ -1,4 +1,9 @@
---
_service_native_socket: "{{ service_domains | length > 0 and service_container_http_port == 0 }}"
_service_socket_path: >-
/run/{{ service_name ~ ('-socat' if not _service_native_socket else '' ) }}.sock
_service_replacement_host_header:
Host: "{{ service_name }}:{{ service_container_http_port }}"
_service_proxy_headers: "{{ _service_replacement_host_header if not service_proxy_pass_host_header else {} }}"