Compare commits
5 commits
9a9039c4d3
...
c11f019aae
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c11f019aae | ||
|
|
a492c3ee04 | ||
|
|
b19ac2270a | ||
|
|
e1d604effc | ||
|
|
4655c8f037 |
8 changed files with 372 additions and 0 deletions
60
roles/send/README.md
Normal file
60
roles/send/README.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
Send
|
||||
====
|
||||
|
||||
Deploys a self-hosted [Send](https://github.com/timvisee/send) instance
|
||||
(timvisee fork of the discontinued Mozilla Send) with a Redis backend
|
||||
behind Traefik, using Docker Compose.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
- Docker + `docker compose` plugin on the target host
|
||||
- Traefik (role `digitalboard.core.traefik`) reachable via an external
|
||||
Docker network named `proxy` (default)
|
||||
- DNS for each entry in `send_domains` pointing at the reverse proxy
|
||||
- Optional: a Garage S3 bucket if `send_storage_backend: s3`
|
||||
|
||||
Role Variables
|
||||
--------------
|
||||
|
||||
Important defaults (see `defaults/main.yml` for the full list):
|
||||
|
||||
| Variable | Default | Description |
|
||||
|---|---|---|
|
||||
| `send_domains` | `["send.local.test"]` | FQDNs the router accepts; first entry is the canonical BASE_URL |
|
||||
| `send_image` | `registry.gitlab.com/timvisee/send:latest` | Send container image |
|
||||
| `send_max_file_size` | `1073741824` | Max upload size in bytes (1 GiB) |
|
||||
| `send_max_expire_seconds` | `604800` | Max share lifetime (7 d) |
|
||||
| `send_storage_backend` | `local` | `local` (volume) or `s3` |
|
||||
| `send_s3_*` | `""` | S3 endpoint/bucket/key/secret (when backend is `s3`) |
|
||||
| `send_use_ssl` | `true` | Issue Traefik labels for the `websecure` entrypoint |
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
None.
|
||||
|
||||
Example Playbook
|
||||
----------------
|
||||
|
||||
```yaml
|
||||
- hosts: send_servers
|
||||
become: true
|
||||
roles:
|
||||
- digitalboard.core.send
|
||||
```
|
||||
|
||||
With S3 (Garage) backend:
|
||||
|
||||
```yaml
|
||||
send_storage_backend: s3
|
||||
send_s3_endpoint: "http://{{ hostvars['backend']['garage_s3_domain'] }}"
|
||||
send_s3_bucket: "send"
|
||||
send_s3_access_key: "{{ lookup('digitalboard.core.garage_credentials', 'send', host='backend')['key_id'] }}"
|
||||
send_s3_secret_key: "{{ lookup('digitalboard.core.garage_credentials', 'send', host='backend')['secret_key'] }}"
|
||||
```
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
MIT
|
||||
53
roles/send/defaults/main.yml
Normal file
53
roles/send/defaults/main.yml
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
# defaults file for send
|
||||
|
||||
# Base directory configuration (inherited from base role or defined here)
|
||||
docker_compose_base_dir: /etc/docker/compose
|
||||
docker_volume_base_dir: /srv/data
|
||||
|
||||
# Send-specific configuration
|
||||
send_service_name: send
|
||||
send_docker_compose_dir: "{{ docker_compose_base_dir }}/{{ send_service_name }}"
|
||||
send_docker_volume_dir: "{{ docker_volume_base_dir }}/{{ send_service_name }}"
|
||||
|
||||
# Service configuration
|
||||
# FQDNs the send router accepts. The first entry is the canonical
|
||||
# domain (used as BASE_URL); further entries cover internal *.int.*
|
||||
# names so backend uploads can hit us without hairpinning via DMZ.
|
||||
send_domains:
|
||||
- "send.local.test"
|
||||
send_image: "registry.gitlab.com/timvisee/send:latest"
|
||||
send_port: 1443
|
||||
send_extra_hosts: []
|
||||
|
||||
# Redis backend
|
||||
send_redis_image: "redis:7-alpine"
|
||||
send_redis_service_name: "send-redis"
|
||||
|
||||
# Send application configuration
|
||||
# https://github.com/timvisee/send/blob/master/server/config.js
|
||||
send_max_file_size: 1073741824 # 1 GiB in bytes
|
||||
send_default_downloads: 1
|
||||
send_max_downloads: 100
|
||||
send_default_expire_seconds: 86400 # 24h
|
||||
send_max_expire_seconds: 604800 # 7d
|
||||
send_max_files_per_archive: 64
|
||||
send_download_counts: "1,2,3,4,5,20,50,100"
|
||||
send_expire_times_seconds: "300,3600,86400,604800"
|
||||
|
||||
# Storage backend: "local" (volume) or "s3"
|
||||
send_storage_backend: "local"
|
||||
|
||||
# S3 backend (only used when send_storage_backend == "s3")
|
||||
send_s3_endpoint: ""
|
||||
send_s3_bucket: ""
|
||||
send_s3_region: "us-east-1"
|
||||
send_s3_access_key: ""
|
||||
send_s3_secret_key: ""
|
||||
send_s3_use_path_style: true
|
||||
|
||||
# Traefik configuration
|
||||
send_traefik_network: "proxy"
|
||||
send_internal_network: "send_internal"
|
||||
send_use_ssl: true
|
||||
9
roles/send/handlers/main.yml
Normal file
9
roles/send/handlers/main.yml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
# handlers file for send
|
||||
|
||||
- name: restart send
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ send_docker_compose_dir }}"
|
||||
state: present
|
||||
recreate: always
|
||||
122
roles/send/meta/argument_specs.yml
Normal file
122
roles/send/meta/argument_specs.yml
Normal 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
|
||||
14
roles/send/meta/main.yml
Normal file
14
roles/send/meta/main.yml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
galaxy_info:
|
||||
author: digitalboard
|
||||
description: Deploy a self-hosted Send (timvisee fork) instance with Redis via Docker Compose
|
||||
license: MIT
|
||||
|
||||
min_ansible_version: "2.14"
|
||||
|
||||
galaxy_tags:
|
||||
- send
|
||||
- filesharing
|
||||
- docker
|
||||
|
||||
dependencies: []
|
||||
42
roles/send/tasks/main.yml
Normal file
42
roles/send/tasks/main.yml
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
# tasks file for send
|
||||
|
||||
- name: Assert S3 backend configuration when enabled
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- send_s3_endpoint | length > 0
|
||||
- send_s3_bucket | length > 0
|
||||
- send_s3_access_key | length > 0
|
||||
- send_s3_secret_key | length > 0
|
||||
fail_msg: >-
|
||||
send_storage_backend is 's3' but one or more of send_s3_endpoint,
|
||||
send_s3_bucket, send_s3_access_key, send_s3_secret_key is unset.
|
||||
Provide via OpenBao, Ansible Vault or extra-vars — or switch
|
||||
send_storage_backend to 'local'.
|
||||
when: send_storage_backend == "s3"
|
||||
|
||||
- name: Create docker compose directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ send_docker_compose_dir }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Create local upload directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ send_docker_volume_dir }}/uploads"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
when: send_storage_backend == "local"
|
||||
|
||||
- name: Create docker-compose file for send
|
||||
ansible.builtin.template:
|
||||
src: docker-compose.yml.j2
|
||||
dest: "{{ send_docker_compose_dir }}/docker-compose.yml"
|
||||
mode: '0644'
|
||||
notify: restart send
|
||||
|
||||
- name: Start send container
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ send_docker_compose_dir }}"
|
||||
state: present
|
||||
69
roles/send/templates/docker-compose.yml.j2
Normal file
69
roles/send/templates/docker-compose.yml.j2
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
services:
|
||||
{{ send_service_name }}:
|
||||
image: {{ send_image }}
|
||||
container_name: {{ send_service_name }}
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- {{ send_redis_service_name }}
|
||||
networks:
|
||||
- {{ send_traefik_network }}
|
||||
- {{ send_internal_network }}
|
||||
{% if send_extra_hosts is defined and send_extra_hosts | length > 0 %}
|
||||
extra_hosts:
|
||||
{% for host in send_extra_hosts %}
|
||||
- "{{ host }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
environment:
|
||||
{% if send_use_ssl %}
|
||||
BASE_URL: "https://{{ send_domains[0] }}"
|
||||
{% else %}
|
||||
BASE_URL: "http://{{ send_domains[0] }}"
|
||||
{% endif %}
|
||||
REDIS_HOST: "{{ send_redis_service_name }}"
|
||||
REDIS_PORT: "6379"
|
||||
MAX_FILE_SIZE: "{{ send_max_file_size }}"
|
||||
DEFAULT_DOWNLOADS: "{{ send_default_downloads }}"
|
||||
MAX_DOWNLOADS: "{{ send_max_downloads }}"
|
||||
DEFAULT_EXPIRE_SECONDS: "{{ send_default_expire_seconds }}"
|
||||
MAX_EXPIRE_SECONDS: "{{ send_max_expire_seconds }}"
|
||||
MAX_FILES_PER_ARCHIVE: "{{ send_max_files_per_archive }}"
|
||||
DOWNLOAD_COUNTS: "{{ send_download_counts }}"
|
||||
EXPIRE_TIMES_SECONDS: "{{ send_expire_times_seconds }}"
|
||||
{% if send_storage_backend == "s3" %}
|
||||
S3_BUCKET: "{{ send_s3_bucket }}"
|
||||
S3_ENDPOINT: "{{ send_s3_endpoint }}"
|
||||
S3_USE_PATH_STYLE_ENDPOINT: "{{ 'true' if send_s3_use_path_style else 'false' }}"
|
||||
AWS_ACCESSKEYID: "{{ send_s3_access_key }}"
|
||||
AWS_SECRETACCESSKEY: "{{ send_s3_secret_key }}"
|
||||
AWS_REGION: "{{ send_s3_region }}"
|
||||
{% else %}
|
||||
FILE_DIR: "/uploads"
|
||||
volumes:
|
||||
- {{ send_docker_volume_dir }}/uploads:/uploads
|
||||
{% endif %}
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.docker.network={{ send_traefik_network }}
|
||||
- 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 }}
|
||||
{% if send_use_ssl %}
|
||||
- traefik.http.routers.{{ send_service_name }}.entrypoints=websecure
|
||||
- traefik.http.routers.{{ send_service_name }}.tls=true
|
||||
{% else %}
|
||||
- traefik.http.routers.{{ send_service_name }}.entrypoints=web
|
||||
{% endif %}
|
||||
|
||||
{{ send_redis_service_name }}:
|
||||
image: {{ send_redis_image }}
|
||||
container_name: {{ send_redis_service_name }}
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- {{ send_internal_network }}
|
||||
volumes:
|
||||
- {{ send_docker_volume_dir }}/redis:/data
|
||||
|
||||
networks:
|
||||
{{ send_internal_network }}:
|
||||
{{ send_traefik_network }}:
|
||||
external: true
|
||||
3
roles/send/vars/main.yml
Normal file
3
roles/send/vars/main.yml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
# vars file for send
|
||||
Loading…
Add table
Add a link
Reference in a new issue