Compare commits

...

2 Commits

Author SHA1 Message Date
uumas
11e22ed34a service: Support connecting containers to tailscale network 2026-08-04 05:00:34 +03:00
uumas
ffa970eced container: Support referring to container files by network name 2026-08-02 04:49:27 +03:00
10 changed files with 134 additions and 28 deletions

View File

@@ -16,7 +16,9 @@
network_name: "{{ network.name }}"
network_subnet: "{{ _container_network_subnet }}"
network_range: "{{ _container_network_range }}"
when: network_created_networks is not defined or network.name not in network_created_networks
when:
- "'.' not in network.name"
- network_created_networks is not defined or network.name not in network_created_networks
loop: "{{ container_networks }}"
loop_control:
loop_var: network

View File

@@ -3,7 +3,7 @@ _container_networks: >-
{{
container_networks
| map(attribute='name')
| map('regex_replace', '$', '.network')
| map('regex_replace', '^(?!.*\.)(.*)$', '\1.network')
| zip(container_networks | map(attribute='ip', default=''))
| map('reject', 'equalto', '')
| map('join', ':ip=')

View File

@@ -28,6 +28,9 @@ service_database_secret_target: "{{ service_database_type }}"
service_postgres_image: docker.io/pgautoupgrade/pgautoupgrade
service_postgres_tag: alpine
service_redis: false
service_tailscale: false
service_tailscale_login_server: ""
service_tailscale_apikey: ""
service_additional_containers: []

View File

@@ -377,6 +377,23 @@ argument_specs:
type: bool
required: false
default: false
service_tailscale:
description: >-
Whether to install tailscale in a container and have the service container use its
network. This will make the container accessible over tailscale.
type: bool
required: false
default: false
service_tailscale_login_server:
description: Tailscale login server. Required if tailscale is enabled.
type: str
required: false
default: ""
service_tailscale_apikey:
description: Tailscale API key. Required if tailscale is enabled.
type: str
required: false
default: ""
service_additional_containers:
description:
@@ -592,6 +609,13 @@ argument_specs:
type: str
required: false
default: ""
tailscale:
description: >-
Whether to install tailscale in a container and this container use its
network. This will make the container accessible over tailscale.
type: bool
required: false
default: false
secrets:
description:
- >

View File

@@ -1,5 +1,5 @@
---
- name: Additional containers for {{ service_name }}
- name: Additional container {{ _service_additional_container.name }}
ansible.builtin.include_role:
name: container
vars:
@@ -11,7 +11,11 @@
container_mounts: "{{ _service_additional_container_mounts }}"
container_devices: "{{ _service_additional_container.devices }}"
container_publish_ports: "{{ _service_additional_container_publish_ports }}"
container_networks: "{{ _service_additional_container_networks }}"
container_networks: >-
{{
_service_additional_container_networks if not _service_additional_container.tailscale
else [{'name': _service_additional_container.name ~ '-tailscale.container'}]
}}
container_hostname: "{{ _service_additional_container.name | regex_replace('^' ~ service_name ~ '-', '') }}"
container_secrets: "{{ _service_additional_container_secrets }}"
container_env: "{{ _service_additional_container.env }}"
@@ -21,13 +25,23 @@
container_requires: "{{ _service_additional_container_requires }}"
container_wants: "{{ _service_additional_container_wants }}"
container_auto_update: "{{ service_auto_update }}"
loop: "{{ _service_additional_containers }}"
loop_control:
loop_var: _service_additional_container
index_var: _service_additional_container_index
- name: Socat sockets for additional containers of {{ service_name }}
ansible.builtin.include_tasks: additional_socat.yaml
loop: "{{ _service_additional_containers }}"
- name: Socat for socket published ports of {{ _service_additional_container.name }}
ansible.builtin.include_role:
name: socat
loop: "{{ _service_additional_container_publish_socket_ports }}"
loop_control:
loop_var: _service_additional_container
loop_var: publish_port
vars:
socat_service_name: "{{ service_name }}-{{ publish_port.name }}"
socat_target_container: "{{ _service_additional_container.name }}"
socat_target_http_port: "{{ publish_port.container_port }}"
socat_auto_update: "{{ service_auto_update }}"
- name: Tailscale for {{ _service_additional_container.name }}
ansible.builtin.include_tasks: tailscale.yaml
when: _service_additional_container.tailscale
vars:
_service_tailscale_container_name: "{{ _service_additional_container.name }}"
_service_tailscale_networks: "{{ _service_additional_container_networks }}"
_service_tailscale_hostname: "{{ _service_additional_container.name | regex_replace('^' ~ service_name ~ '-', '') }}"

View File

@@ -1,12 +0,0 @@
---
- name: Socat for socket published ports of {{ service_name }}
ansible.builtin.include_role:
name: socat
loop: "{{ _service_additional_container_publish_socket_ports }}"
loop_control:
loop_var: publish_port
vars:
socat_service_name: "{{ service_name }}-{{ publish_port.name }}"
socat_target_container: "{{ _service_additional_container.name }}"
socat_target_http_port: "{{ publish_port.container_port }}"
socat_auto_update: "{{ service_auto_update }}"

View File

@@ -5,14 +5,21 @@
- name: Database for {{ service_name }}
ansible.builtin.include_tasks: database.yaml
when: _service_setup_database
- name: Redis for {{ service_name }}
ansible.builtin.include_tasks: redis.yaml
when: service_redis
- name: Secrets for {{ service_name }}
ansible.builtin.include_tasks: secrets.yaml
when: _service_container_secrets | length > 0
when: _service_container_secrets | length > 0 or service_tailscale
- name: Tailscale for {{ service_name }}
ansible.builtin.include_tasks: tailscale.yaml
when: service_tailscale
vars:
_service_tailscale_container_name: "{{ service_name }}"
_service_tailscale_networks: "{{ _service_networks }}"
_service_tailscale_hostname: "{{ service_name }}"
- name: Template mounts for {{ service_name }}
ansible.builtin.include_tasks: host_mounts.yaml
@@ -20,7 +27,10 @@
- name: Additional containers for {{ service_name }}
ansible.builtin.include_tasks: additional.yaml
when: _service_additional_containers | length > 0
loop: "{{ _service_additional_containers }}"
loop_control:
loop_var: _service_additional_container
index_var: _service_additional_container_index
- name: Native socket for {{ service_name }}
ansible.builtin.include_role:

View File

@@ -0,0 +1,60 @@
---
- name: Create tailscale preauthkey secret for {{ _service_tailscale_container_name }}
when:
- not ansible_check_mode
- "_service_tailscale_container_name ~ '-tailscale-preauthkey' not in service_podman_secrets"
block:
- name: Get preauthkey from tailscale API
ansible.builtin.uri:
url: "{{ service_tailscale_login_server }}/api/v1/preauthkey"
headers:
Authorization: Bearer {{ service_tailscale_apikey }}
method: POST
body:
expiration: >-
{{
now(utc=true).replace(
day=now(utc=true).day if now(utc=true).hour != 23 else now(utc=true).day + 1,
hour=now(utc=true).hour + 1 if now(utc=true).hour != 23 else 0
).isoformat()
}}Z
aclTags:
- tag:container
- "tag:{{ _service_tailscale_container_name }}"
body_format: json
register: _service_tailscale_preauthkey
- name: Create preauthkey secret
containers.podman.podman_secret:
name: "{{ _service_tailscale_container_name }}-tailscale-preauthkey"
data: "{{ _service_tailscale_preauthkey.json.preAuthKey.key }}"
no_log: true
- name: Tailscale container for {{ _service_tailscale_container_name }}
ansible.builtin.import_role:
name: container
vars:
container_name: "{{ _service_tailscale_container_name }}-tailscale"
container_image: docker.io/tailscale/tailscale:latest
container_networks: "{{ _service_tailscale_networks }}"
container_hostname: "{{ _service_tailscale_hostname }}"
container_add_capabilities:
- NET_ADMIN
container_devices:
- source: /dev/net/tun
container_mounts:
- type: volume
source: "{{ _service_tailscale_container_name }}-tailscale"
destination: /var/lib/tailscale
container_auto_update: "{{ service_auto_update }}"
container_secrets:
- name: "{{ _service_tailscale_container_name }}-tailscale-preauthkey"
target: preauthkey
container_env:
TS_STATE_DIR: /var/lib/tailscale
TS_AUTHKEY: file:/run/secrets/preauthkey
TS_EXTRA_ARGS: --login-server={{ service_tailscale_login_server }}
TS_HOSTNAME: "{{ _service_tailscale_container_name }}"
TS_AUTH_ONCE: "true"
TS_NO_LOGS_NO_SUPPORT: "true"
TS_USERSPACE: "false"
TS_ACCEPT_DNS: "true"

View File

@@ -1,6 +1,7 @@
---
_service_additional_container_defaults:
image: "{{ service_container_image }}"
tailscale: false
requires: []
wants: []

View File

@@ -1,5 +1,5 @@
---
_service_container_networks: >-
_service_networks: >-
{{
[{
'name': service_name,
@@ -21,6 +21,10 @@ _service_container_networks: >-
)
) | map('community.general.dict_kv', 'name')
}}
_service_container_networks: >-
{{
[{'name': service_name ~ '-tailscale.container'}] if service_tailscale else _service_networks
}}
_service_static_ip: "{{ service_container_ip | length > 0 }}"
_service_container_requires: >-