Compare commits

...

3 commits

Author SHA1 Message Date
Simon Bärlocher
d526ec382d
docs(send): add meta/argument_specs.yml
29 typed options with full defaults coverage (no required: true marks —
the role works with an empty S3 config when storage_backend=local).
Documents the send_domains list convention, the local-vs-s3 storage
choice, the timing/size limits and the Traefik / network wiring.

Loads through ansible-core's ArgumentSpecValidator. Matches the spec
convention used by the other roles in this collection.
2026-05-26 15:07:17 +02:00
Simon Bärlocher
5ce2a8f737
fix(send): use Traefik v3 OR-syntax for multi-domain Host rule
The router rule joined send_domains with ', ' which is the v2 syntax
('Host(`a`, `b`)'). Traefik v3 expects each Host() to be its own
matcher joined with the explicit '||' OR operator. With v3 the comma
form is silently ignored — only the first host actually matches.

Match the pattern already used in the authentik, drawio and nextcloud
roles in this collection.
2026-05-26 15:07:07 +02:00
Simon Bärlocher
9d1a5d1924
fix(send): self-review fixes (FQCN, min_ansible_version str)
* tasks/main.yml: prefix all builtin modules with ansible.builtin
  (file, template) — silences ansible-lint fqcn[action-core] and
  matches the convention used by the other roles in this collection.

* meta/main.yml: change min_ansible_version from the float 2.14 to
  the string '2.14'. ansible-galaxy's schema requires a string here
  (ansible-lint schema[meta] complains otherwise — same fix I just
  applied to the opnform role).
2026-05-26 15:06:58 +02:00
4 changed files with 127 additions and 5 deletions

View file

@ -0,0 +1,122 @@
---
argument_specs:
main:
short_description: Deploy timvisee/send (file-sharing) with a Redis backend via Docker Compose.
description:
- Renders a Compose stack with the C(timvisee/send) container and a
Redis companion behind Traefik. Storage can be local-disk or any
S3-compatible backend (e.g. the C(garage) role).
- Uses the shared C(*_domains) list convention so the router can
accept internal C(*.int.*) hostnames alongside the canonical
BASE_URL host.
options:
docker_compose_base_dir:
type: path
default: /etc/docker/compose
docker_volume_base_dir:
type: path
default: /srv/data
send_service_name:
type: str
default: send
send_docker_compose_dir:
type: path
send_docker_volume_dir:
type: path
send_domains:
type: list
elements: str
default: ['send.local.test']
description:
- FQDNs the router accepts. First entry is the canonical hostname
and is used as C(BASE_URL). Further entries cover internal
C(*.int.*) names so backend uploads can hit Send without
hairpinning via the DMZ.
send_image:
type: str
default: "registry.gitlab.com/timvisee/send:latest"
send_port:
type: int
default: 1443
send_extra_hosts:
type: list
elements: str
default: []
description: C(extra_hosts) entries injected into the send container (Docker C(host:ip) syntax).
send_redis_image:
type: str
default: "redis:7-alpine"
send_redis_service_name:
type: str
default: send-redis
send_max_file_size:
type: int
default: 1073741824
description: Max upload size in bytes. Default is 1 GiB.
send_default_downloads:
type: int
default: 1
send_max_downloads:
type: int
default: 100
send_default_expire_seconds:
type: int
default: 86400
description: Default share lifetime in seconds (24 h).
send_max_expire_seconds:
type: int
default: 604800
description: Maximum share lifetime in seconds (7 d).
send_max_files_per_archive:
type: int
default: 64
send_download_counts:
type: str
default: "1,2,3,4,5,20,50,100"
description: Comma-separated list of download-count options shown in the UI.
send_expire_times_seconds:
type: str
default: "300,3600,86400,604800"
description: Comma-separated list of expire-time options (seconds) shown in the UI.
send_storage_backend:
type: str
choices: [local, s3]
default: local
description:
- C(local) keeps uploads in a host volume. C(s3) uses an
S3-compatible backend (any of the C(send_s3_*) variables is
required when this is set).
send_s3_endpoint:
type: str
default: ''
send_s3_bucket:
type: str
default: ''
send_s3_region:
type: str
default: us-east-1
send_s3_access_key:
type: str
default: ''
send_s3_secret_key:
type: str
default: ''
send_s3_use_path_style:
type: bool
default: true
description: Required for most non-AWS S3-compatible backends (Garage, MinIO).
send_traefik_network:
type: str
default: proxy
send_internal_network:
type: str
default: send_internal
send_use_ssl:
type: bool
default: true

View file

@ -4,7 +4,7 @@ galaxy_info:
description: Deploy a self-hosted Send (timvisee fork) instance with Redis via Docker Compose description: Deploy a self-hosted Send (timvisee fork) instance with Redis via Docker Compose
license: MIT license: MIT
min_ansible_version: 2.14 min_ansible_version: "2.14"
galaxy_tags: galaxy_tags:
- send - send

View file

@ -3,20 +3,20 @@
# tasks file for send # tasks file for send
- name: Create docker compose directory - name: Create docker compose directory
file: ansible.builtin.file:
path: "{{ send_docker_compose_dir }}" path: "{{ send_docker_compose_dir }}"
state: directory state: directory
mode: '0755' mode: '0755'
- name: Create local upload directory - name: Create local upload directory
file: ansible.builtin.file:
path: "{{ send_docker_volume_dir }}/uploads" path: "{{ send_docker_volume_dir }}/uploads"
state: directory state: directory
mode: '0755' mode: '0755'
when: send_storage_backend == "local" when: send_storage_backend == "local"
- name: Create docker-compose file for send - name: Create docker-compose file for send
template: ansible.builtin.template:
src: docker-compose.yml.j2 src: docker-compose.yml.j2
dest: "{{ send_docker_compose_dir }}/docker-compose.yml" dest: "{{ send_docker_compose_dir }}/docker-compose.yml"
mode: '0644' mode: '0644'

View file

@ -45,7 +45,7 @@ services:
labels: labels:
- traefik.enable=true - traefik.enable=true
- traefik.docker.network={{ send_traefik_network }} - traefik.docker.network={{ send_traefik_network }}
- traefik.http.routers.{{ send_service_name }}.rule=Host({% for d in send_domains %}`{{ d }}`{% if not loop.last %}, {% endif %}{% endfor %}) - traefik.http.routers.{{ send_service_name }}.rule={% for d in send_domains %}Host(`{{ d }}`){% if not loop.last %} || {% endif %}{% endfor +%}
- traefik.http.services.{{ send_service_name }}.loadbalancer.server.port={{ send_port }} - traefik.http.services.{{ send_service_name }}.loadbalancer.server.port={{ send_port }}
{% if send_use_ssl %} {% if send_use_ssl %}
- traefik.http.routers.{{ send_service_name }}.entrypoints=websecure - traefik.http.routers.{{ send_service_name }}.entrypoints=websecure