From 9386a6d00cdeab2c4b32256e0e0876741adfdf7e Mon Sep 17 00:00:00 2001 From: Menno van Leeuwen Date: Mon, 17 Mar 2025 13:41:22 +0100 Subject: [PATCH] feat: add Seafile service deployment and configuration with Caddy integration --- .../tasks/servers/services/caddy/Caddyfile.j2 | 5 ++ .../tasks/servers/services/seafile/.env.j2 | 29 +++++++++ .../servers/services/seafile/caddy.yml.j2 | 26 ++++++++ .../services/seafile/docker-compose.yml.j2 | 63 ++++++++++++------- .../servers/services/seafile/seadoc.yml.j2 | 24 +++++++ .../servers/services/seafile/seafile.yml | 59 +++++++++++++++-- 6 files changed, 179 insertions(+), 27 deletions(-) create mode 100644 config/ansible/tasks/servers/services/seafile/.env.j2 create mode 100644 config/ansible/tasks/servers/services/seafile/caddy.yml.j2 create mode 100644 config/ansible/tasks/servers/services/seafile/seadoc.yml.j2 diff --git a/config/ansible/tasks/servers/services/caddy/Caddyfile.j2 b/config/ansible/tasks/servers/services/caddy/Caddyfile.j2 index 08cb303..b6480ba 100644 --- a/config/ansible/tasks/servers/services/caddy/Caddyfile.j2 +++ b/config/ansible/tasks/servers/services/caddy/Caddyfile.j2 @@ -22,3 +22,8 @@ status.vleeuwen.me status.mvl.sh { reverse_proxy uptime-kuma:3001 tls {{ caddy_email }} } + +sf.vleeuwen.me sf.mvl.sh { + reverse_proxy seafile:80 + tls {{ caddy_email }} +} diff --git a/config/ansible/tasks/servers/services/seafile/.env.j2 b/config/ansible/tasks/servers/services/seafile/.env.j2 new file mode 100644 index 0000000..b94983a --- /dev/null +++ b/config/ansible/tasks/servers/services/seafile/.env.j2 @@ -0,0 +1,29 @@ +SEAFILE_IMAGE={{ seafile_image | default('seafileltd/seafile-mc:12.0-latest') }} +SEAFILE_DB_IMAGE={{ seafile_db_image | default('mariadb:10.11') }} +SEAFILE_MEMCACHED_IMAGE={{ seafile_memcached_image | default('memcached:1.6.29') }} + +SEAFILE_VOLUME={{ seafile_volume | default('/opt/seafile-data') }} +SEAFILE_MYSQL_VOLUME={{ seafile_mysql_volume | default('/opt/seafile-mysql/db') }} + +SEAFILE_MYSQL_DB_HOST={{ seafile_mysql_db_host | default('db') }} +INIT_SEAFILE_MYSQL_ROOT_PASSWORD={{ seafile_mysql_root_password | default('ROOT_PASSWORD') }} +SEAFILE_MYSQL_DB_USER={{ seafile_mysql_db_user | default('seafile') }} +SEAFILE_MYSQL_DB_PASSWORD={{ seafile_mysql_db_password | default('PASSWORD') }} + +TIME_ZONE={{ time_zone | default('Europe/Amsterdam') }} + +JWT_PRIVATE_KEY={{ jwt_private_key | default('') }} + +SEAFILE_SERVER_HOSTNAME={{ seafile_server_hostname | default('sf.mvl.sh') }} +SEAFILE_SERVER_PROTOCOL={{ seafile_server_protocol | default('http') }} + +INIT_SEAFILE_ADMIN_EMAIL={{ seafile_admin_email | default('menno@vleeuwen.me') }} +INIT_SEAFILE_ADMIN_PASSWORD={{ seafile_admin_password | default('WIP123') }} + +SEADOC_IMAGE={{ seadoc_image | default('seafileltd/sdoc-server:1.0-latest') }} +SEADOC_VOLUME={{ seadoc_volume | default('/opt/seadoc-data') }} + +ENABLE_SEADOC={{ enable_seadoc | default('true') }} + +NOTIFICATION_SERVER_IMAGE={{ notification_server_image | default('seafileltd/notification-server:12.0-latest') }} +NOTIFICATION_SERVER_VOLUME={{ notification_server_volume | default('/opt/notification-data') }} diff --git a/config/ansible/tasks/servers/services/seafile/caddy.yml.j2 b/config/ansible/tasks/servers/services/seafile/caddy.yml.j2 new file mode 100644 index 0000000..2321ed1 --- /dev/null +++ b/config/ansible/tasks/servers/services/seafile/caddy.yml.j2 @@ -0,0 +1,26 @@ +services: + + caddy: + image: ${SEAFILE_CADDY_IMAGE:-lucaslorentz/caddy-docker-proxy:2.9-alpine} + restart: unless-stopped + container_name: seafile-caddy + ports: + - 80:80 + - 443:443 + environment: + - CADDY_INGRESS_NETWORKS=seafile-net + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ${SEAFILE_CADDY_VOLUME:-/opt/seafile-caddy}:/data/caddy + networks: + - seafile-net + healthcheck: + test: ["CMD-SHELL", "curl --fail http://localhost:2019/metrics || exit 1"] + start_period: 20s + interval: 20s + timeout: 5s + retries: 3 + +networks: + seafile-net: + name: seafile-net diff --git a/config/ansible/tasks/servers/services/seafile/docker-compose.yml.j2 b/config/ansible/tasks/servers/services/seafile/docker-compose.yml.j2 index c5cb8c1..c3b7a00 100644 --- a/config/ansible/tasks/servers/services/seafile/docker-compose.yml.j2 +++ b/config/ansible/tasks/servers/services/seafile/docker-compose.yml.j2 @@ -1,47 +1,68 @@ +version: '3.8' + services: db: - image: mariadb:10.11 + image: ${SEAFILE_DB_IMAGE} container_name: seafile-mysql environment: - - MYSQL_ROOT_PASSWORD={{ lookup('community.general.onepassword', 'bbzudwdo3byqs4pscd2wy7qsn4', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='MYSQL_ROOT_PASSWORD') }} + - MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD} - MYSQL_LOG_CONSOLE=true - - MARIADB_AUTO_UPGRADE=1 volumes: - - {{ seafile_data_dir }}/db:/var/lib/mysql + - ${SEAFILE_MYSQL_VOLUME}:/var/lib/mysql networks: - seafile-net + - caddy_default + restart: unless-stopped memcached: - image: memcached:1.6.18 + image: ${SEAFILE_MEMCACHED_IMAGE} container_name: seafile-memcached entrypoint: memcached -m 256 networks: - seafile-net - + restart: unless-stopped + seafile: - image: seafileltd/seafile-mc:11.0-latest - ports: - - "8001:80" - volumes: - - {{ seafile_data_dir }}/shared:/shared + image: ${SEAFILE_IMAGE} + container_name: seafile environment: - - DB_HOST=db - - DB_ROOT_PASSWD={{ lookup('community.general.onepassword', 'bbzudwdo3byqs4pscd2wy7qsn4', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='MYSQL_ROOT_PASSWORD') }} - - TIME_ZONE=Europe/Amsterdam - - SEAFILE_ADMIN_EMAIL=menno@vleeuwen.me - - SEAFILE_ADMIN_PASSWORD={{ lookup('community.general.onepassword', 'bbzudwdo3byqs4pscd2wy7qsn4', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='password') }} + - DB_HOST=${SEAFILE_MYSQL_DB_HOST} + - DB_ROOT_PASSWD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD} + - TIME_ZONE=${TIME_ZONE} + - SEAFILE_ADMIN_EMAIL=${INIT_SEAFILE_ADMIN_EMAIL} + - SEAFILE_ADMIN_PASSWORD=${INIT_SEAFILE_ADMIN_PASSWORD} + - SEAFILE_SERVER_HOSTNAME=${SEAFILE_SERVER_HOSTNAME} - SEAFILE_SERVER_LETSENCRYPT=false - - SEAFILE_SERVER_HOSTNAME=sf.mvl.sh:8001 + - SEADRIVE_SERVER_LETSENCRYPT=false + - SEAFILE_SERVER_PROTOCOL=${SEAFILE_SERVER_PROTOCOL} + volumes: + - ${SEAFILE_VOLUME}:/shared + networks: + - seafile-net + - caddy_default + restart: unless-stopped depends_on: - db - memcached + + notification-server: + image: ${NOTIFICATION_SERVER_IMAGE} + container_name: notification-server + environment: + - DB_HOST=${SEAFILE_MYSQL_DB_HOST} + - DB_ROOT_PASSWD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD} + - TIME_ZONE=${TIME_ZONE} + volumes: + - ${NOTIFICATION_SERVER_VOLUME}:/shared + - ${SEAFILE_VOLUME}:/shared/seafile networks: - seafile-net - - caddy_network + depends_on: + - db + - seafile + restart: unless-stopped networks: seafile-net: - caddy_network: + caddy_default: external: true - name: caddy_default - diff --git a/config/ansible/tasks/servers/services/seafile/seadoc.yml.j2 b/config/ansible/tasks/servers/services/seafile/seadoc.yml.j2 new file mode 100644 index 0000000..129d735 --- /dev/null +++ b/config/ansible/tasks/servers/services/seafile/seadoc.yml.j2 @@ -0,0 +1,24 @@ +version: '3.8' + +services: + seadoc-server: + image: ${SEADOC_IMAGE} + container_name: seadoc-server + environment: + - DB_HOST=${SEAFILE_MYSQL_DB_HOST} + - DB_ROOT_PASSWD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD} + - TIME_ZONE=${TIME_ZONE} + - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY} + volumes: + - ${SEADOC_VOLUME}:/shared + - ${SEAFILE_VOLUME}:/shared/seafile + networks: + - seafile-net + depends_on: + - db + - seafile + restart: unless-stopped + +networks: + seafile-net: + name: seafile-net diff --git a/config/ansible/tasks/servers/services/seafile/seafile.yml b/config/ansible/tasks/servers/services/seafile/seafile.yml index 66201a5..98aa783 100644 --- a/config/ansible/tasks/servers/services/seafile/seafile.yml +++ b/config/ansible/tasks/servers/services/seafile/seafile.yml @@ -6,6 +6,40 @@ seafile_data_dir: "/mnt/object_storage/services/seafile" seafile_service_dir: "{{ ansible_env.HOME }}/services/seafile" + - name: Set Seafile configuration variables + ansible.builtin.set_fact: + # Docker images + seafile_image: "seafileltd/seafile-mc:12.0-latest" + seafile_db_image: "mariadb:10.11" + seafile_memcached_image: "memcached:1.6.29" + seadoc_image: "seafileltd/sdoc-server:1.0-latest" + notification_server_image: "seafileltd/notification-server:12.0-latest" + + # Volume paths + seafile_volume: "{{ seafile_data_dir }}/seafile-data" + seafile_mysql_volume: "{{ seafile_data_dir }}/seafile-mysql/db" + seadoc_volume: "{{ seafile_data_dir }}/seadoc-data" + notification_server_volume: "{{ seafile_data_dir }}/notification-data" + + # Database settings + seafile_mysql_db_host: "db" + seafile_mysql_root_password: "{{ lookup('community.general.onepassword', 'bbzudwdo3byqs4pscd2wy7qsn4', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='MYSQL_ROOT_PASSWORD') }}" + seafile_mysql_db_user: "seafile" + seafile_mysql_db_password: "{{ lookup('community.general.onepassword', 'bbzudwdo3byqs4pscd2wy7qsn4', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='MYSQL_PASSWORD') }}" + + # Server settings + time_zone: "Europe/Amsterdam" + jwt_private_key: "{{ lookup('community.general.onepassword', 'bbzudwdo3byqs4pscd2wy7qsn4', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='jwt_private_key') }}" + seafile_server_hostname: "sf.mvl.sh" + seafile_server_protocol: "https" + + # Admin credentials + seafile_admin_email: "menno@vleeuwen.me" + seafile_admin_password: "{{ lookup('community.general.onepassword', 'bbzudwdo3byqs4pscd2wy7qsn4', vault='j7nmhqlsjmp2r6umly5t75hzb4', field='password') }}" + + # Features + enable_seadoc: "true" + - name: Create Seafile directories ansible.builtin.file: path: "{{ seafile_dir }}" @@ -17,17 +51,30 @@ loop_control: loop_var: seafile_dir - - name: Deploy Seafile docker-compose.yml + - name: Deploy Seafile configuration files ansible.builtin.template: - src: docker-compose.yml.j2 - dest: "{{ seafile_service_dir }}/docker-compose.yml" + src: "{{ item }}" + dest: "{{ seafile_service_dir }}/{{ item | replace('.j2', '') }}" mode: "0644" - register: seafile_compose + loop: + - docker-compose.yml.j2 + - seadoc.yml.j2 + - .env.j2 + register: seafile_configs + - name: Ensure containers are on the caddy network + ansible.builtin.command: docker network connect caddy_default seafile + register: connect_network + changed_when: connect_network.rc == 0 + failed_when: + - connect_network.rc != 0 + - "'already exists' not in connect_network.stderr" + when: seafile_configs.changed + - name: Stop Seafile service ansible.builtin.command: docker compose -f "{{ seafile_service_dir }}/docker-compose.yml" down --remove-orphans - when: seafile_compose.changed or seafile_act_runner_config.changed + when: seafile_configs.changed - name: Start Seafile service ansible.builtin.command: docker compose -f "{{ seafile_service_dir }}/docker-compose.yml" up -d - when: seafile_compose.changed or seafile_act_runner_config.changed + when: seafile_configs.changed