From 4c3bfb3d02a6a4b0bfe307c9a76d0e21edc93757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro=20Agostinho=20de=20Sousa?= Date: Tue, 4 Aug 2026 14:55:59 +0200 Subject: [PATCH 01/28] add tubulin.xyz --- conf.d/tubulinxyz.conf | 29 ++++++++ docker-compose.yaml | 154 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 conf.d/tubulinxyz.conf diff --git a/conf.d/tubulinxyz.conf b/conf.d/tubulinxyz.conf new file mode 100644 index 0000000..7f2094b --- /dev/null +++ b/conf.d/tubulinxyz.conf @@ -0,0 +1,29 @@ +server { + listen 80; + server_name tubulin.xyz; + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl; + server_name tubulin.xyz; + + ssl_certificate /etc/nginx/certs/tubulin.xyz.crt; + ssl_certificate_key /etc/nginx/private/tubulin.xyz.key; + + location /api/ { + proxy_pass http://backend:8000/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location / { + proxy_pass http://frontend:3000; + proxy_set_header Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_cache_bypass $http_upgrade; + } +} diff --git a/docker-compose.yaml b/docker-compose.yaml index afea22b..aec6620 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -225,9 +225,163 @@ services: networks: - leaps_db + # João Pedro Agostinho de Sousa + # tubulin.xyz + neo4j: + image: neo4j:5 + environment: + NEO4J_AUTH: neo4j/${NEO4J_PASSWORD} + NEO4J_server_memory_heap_initial__size: 1G + NEO4J_server_memory_heap_max__size: 2G + NEO4J_server_memory_pagecache_size: 1G + volumes: + - /opt/webcontent/tubulin/neo4j/data:/data + - /opt/webcontent/tubulin/neo4j/logs:/logs + healthcheck: + test: ["CMD", "cypher-shell", "-u", "neo4j", "-p", "${NEO4J_PASSWORD}", "RETURN 1"] + interval: 10s + timeout: 5s + retries: 10 + start_period: 30s + restart: always + networks: + - tubulinxyz_backend + stop_grace_period: 60s + logging: + driver: json-file + options: + max-size: "50m" + max-file: "5" + deploy: + resources: + limits: + memory: 4G + + bootstrap: + image: ghcr.io/rtviii/tubulinxyz:latest + pull_policy: always + environment: + NEO4J_URI: bolt://neo4j:7687 + NEO4J_USER: neo4j + NEO4J_PASSWORD: ${NEO4J_PASSWORD} + NEO4J_CURRENTDB: neo4j + TUBXZ_ROOT: /app + TUBETL_DATA: /mnt/tubetl_data + NCBI_TAXA_SQLITE: /app/.etetoolkit/taxa.sqlite + volumes: + - /opt/webcontent/tubulin/data:/mnt/tubetl_data + - /opt/webcontent/tubulin/log:/var/log/tubxz + depends_on: + neo4j: + condition: service_healthy + entrypoint: ["/bin/sh", "/app/scripts/init_and_seed.sh"] + restart: always + networks: + - tubulinxyz_backend + logging: + driver: json-file + options: + max-size: "50m" + max-file: "3" + deploy: + resources: + limits: + memory: 4G + + backend: + image: ghcr.io/rtviii/tubulinxyz:latest + pull_policy: always + environment: + NEO4J_URI: bolt://neo4j:7687 + NEO4J_USER: neo4j + NEO4J_PASSWORD: ${NEO4J_PASSWORD} + NEO4J_CURRENTDB: neo4j + SECRET_KEY: ${SECRET_KEY} + TUBXZ_ROOT: /app + TUBETL_DATA: /mnt/tubetl_data + NCBI_TAXA_SQLITE: /app/.etetoolkit/taxa.sqlite + volumes: + - /opt/webcontent/tubulin/data:/mnt/tubetl_data + - /opt/webcontent/tubulin/log:/var/log/tubxz:ro + depends_on: + neo4j: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/health"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 15s + restart: always + networks: + - backend + - tubulinxyz_backend + stop_grace_period: 30s + logging: + driver: json-file + options: + max-size: "50m" + max-file: "5" + deploy: + resources: + limits: + memory: 2G + + scheduler: + image: ghcr.io/rtviii/tubulinxyz:latest + pull_policy: always + environment: + NEO4J_URI: bolt://neo4j:7687 + NEO4J_USER: neo4j + NEO4J_PASSWORD: ${NEO4J_PASSWORD} + NEO4J_CURRENTDB: neo4j + TUBXZ_ROOT: /app + TUBETL_DATA: /mnt/tubetl_data + NCBI_TAXA_SQLITE: /app/.etetoolkit/taxa.sqlite + volumes: + - /opt/webcontent/tubulin/data:/mnt/tubetl_data + - /opt/webcontent/tubulin/log:/var/log/tubxz + depends_on: + neo4j: + condition: service_healthy + entrypoint: ["/bin/sh", "/app/scripts/start_scheduler.sh"] + restart: always + networks: + - tubulinxyz_backend + logging: + driver: json-file + options: + max-size: "50m" + max-file: "5" + deploy: + resources: + limits: + memory: 4G + + frontend: + image: ghcr.io/rtviii/tubulinxyz-frontend:latest + pull_policy: always + depends_on: + backend: + condition: service_healthy + restart: always + networks: + - backend + - tubulinxyz_backend + logging: + driver: json-file + options: + max-size: "50m" + max-file: "3" + deploy: + resources: + limits: + memory: 512M + networks: public: backend: up_mavt_suite_network: rhodo_network: leaps_db: + tubulinxyz_backend: From 5abb92e1535e2bd1cdfe93046371accbd8842bb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro=20Agostinho=20de=20Sousa?= Date: Thu, 10 Sep 2026 08:23:47 +0200 Subject: [PATCH 02/28] Replace /opt mount point with /mount/webhosting_dmz mount --- docker-compose.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index aec6620..b2404a8 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -235,8 +235,8 @@ services: NEO4J_server_memory_heap_max__size: 2G NEO4J_server_memory_pagecache_size: 1G volumes: - - /opt/webcontent/tubulin/neo4j/data:/data - - /opt/webcontent/tubulin/neo4j/logs:/logs + - /mount/webhosting_dmz_write/tubulin/neo4j/data:/data + - /mount/webhosting_dmz_write/tubulin/neo4j/logs:/logs healthcheck: test: ["CMD", "cypher-shell", "-u", "neo4j", "-p", "${NEO4J_PASSWORD}", "RETURN 1"] interval: 10s @@ -269,8 +269,8 @@ services: TUBETL_DATA: /mnt/tubetl_data NCBI_TAXA_SQLITE: /app/.etetoolkit/taxa.sqlite volumes: - - /opt/webcontent/tubulin/data:/mnt/tubetl_data - - /opt/webcontent/tubulin/log:/var/log/tubxz + - /mount/webhosting_dmz_write/tubulin/data:/mnt/tubetl_data + - /mount/webhosting_dmz_write/tubulin/log:/var/log/tubxz depends_on: neo4j: condition: service_healthy @@ -301,8 +301,8 @@ services: TUBETL_DATA: /mnt/tubetl_data NCBI_TAXA_SQLITE: /app/.etetoolkit/taxa.sqlite volumes: - - /opt/webcontent/tubulin/data:/mnt/tubetl_data - - /opt/webcontent/tubulin/log:/var/log/tubxz:ro + - /mount/webhosting_dmz_write/tubulin/data:/mnt/tubetl_data + - /mount/webhosting_dmz_write/tubulin/log:/var/log/tubxz:ro depends_on: neo4j: condition: service_healthy @@ -339,8 +339,8 @@ services: TUBETL_DATA: /mnt/tubetl_data NCBI_TAXA_SQLITE: /app/.etetoolkit/taxa.sqlite volumes: - - /opt/webcontent/tubulin/data:/mnt/tubetl_data - - /opt/webcontent/tubulin/log:/var/log/tubxz + - /mount/webhosting_dmz_write/tubulin/data:/mnt/tubetl_data + - /mount/webhosting_dmz_write/tubulin/log:/var/log/tubxz depends_on: neo4j: condition: service_healthy From 99bbd877cb644765d35d28b15621897dcd73d655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro=20Agostinho=20de=20Sousa?= Date: Thu, 10 Sep 2026 08:37:02 +0200 Subject: [PATCH 03/28] Replace certificate name to lx-docker-dmz-01.psi.ch --- conf.d/tubulinxyz.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf.d/tubulinxyz.conf b/conf.d/tubulinxyz.conf index 7f2094b..940b412 100644 --- a/conf.d/tubulinxyz.conf +++ b/conf.d/tubulinxyz.conf @@ -8,8 +8,8 @@ server { listen 443 ssl; server_name tubulin.xyz; - ssl_certificate /etc/nginx/certs/tubulin.xyz.crt; - ssl_certificate_key /etc/nginx/private/tubulin.xyz.key; + ssl_certificate /etc/nginx/certs/lx-docker-dmz-01.psi.ch.crt; + ssl_certificate_key /etc/nginx/private/lx-docker-dmz-01.psi.ch.key; location /api/ { proxy_pass http://backend:8000/; From eddce140e3da1d822799151e6bba40f7adab1551 Mon Sep 17 00:00:00 2001 From: fpotier Date: Thu, 10 Sep 2026 10:10:35 +0200 Subject: [PATCH 04/28] bump scicat-rocrate-qa --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 09d4efe..c79928f 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -362,7 +362,7 @@ services: - backend scicat-rocrate-qa: - image: gitea.psi.ch/data-catalog-services/scicat-rocrate:2.6.5-rc-ra-ingest.1 + image: gitea.psi.ch/data-catalog-services/scicat-rocrate:2.6.10-rc-openbis-doi.1 container_name: scicat-rocrate-qa restart: always networks: From 23d8cf84867fc777ac7fe300b4fcde4c08bd0442 Mon Sep 17 00:00:00 2001 From: Basil Bruhn Date: Thu, 10 Sep 2026 13:56:13 +0200 Subject: [PATCH 05/28] update tubulin env var Signed-off-by: Basil Bruhn --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 6dee55e..3627135 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -436,7 +436,7 @@ services: neo4j: image: neo4j:5 environment: - NEO4J_AUTH: neo4j/${NEO4J_PASSWORD} + NEO4J_AUTH: ${NEO4J_PASSWORD} NEO4J_server_memory_heap_initial__size: 1G NEO4J_server_memory_heap_max__size: 2G NEO4J_server_memory_pagecache_size: 1G From f84b744cb7e33b7392bf8f2d4ca7b6490163613e Mon Sep 17 00:00:00 2001 From: Basil Bruhn Date: Thu, 10 Sep 2026 15:56:17 +0200 Subject: [PATCH 06/28] add username to tubulindb Signed-off-by: Basil Bruhn --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 3627135..6dee55e 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -436,7 +436,7 @@ services: neo4j: image: neo4j:5 environment: - NEO4J_AUTH: ${NEO4J_PASSWORD} + NEO4J_AUTH: neo4j/${NEO4J_PASSWORD} NEO4J_server_memory_heap_initial__size: 1G NEO4J_server_memory_heap_max__size: 2G NEO4J_server_memory_pagecache_size: 1G From dbc0487c479215455539963c36bfa23cdba5821b Mon Sep 17 00:00:00 2001 From: River Date: Fri, 11 Sep 2026 17:06:00 +0200 Subject: [PATCH 07/28] SRF software bug fix --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 6dee55e..97bdcc0 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -57,7 +57,7 @@ services: # MCDA SRF Huang He mcda-srf: - image: gitea.psi.ch/images/mcda-srf:1.0.0 + image: gitea.psi.ch/images/mcda-srf:1.0.1 container_name: mcda-srf restart: always networks: From 778bcb865cda5159f8e5d2535afcc702f53c8ea9 Mon Sep 17 00:00:00 2001 From: River Date: Mon, 14 Sep 2026 09:46:15 +0200 Subject: [PATCH 08/28] SRF software small update --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 97bdcc0..28f7c47 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -57,7 +57,7 @@ services: # MCDA SRF Huang He mcda-srf: - image: gitea.psi.ch/images/mcda-srf:1.0.1 + image: gitea.psi.ch/images/mcda-srf:1.0.2 container_name: mcda-srf restart: always networks: From 496ba2fb500b47f317af311763d2a55717313abd Mon Sep 17 00:00:00 2001 From: Basil Bruhn Date: Mon, 14 Sep 2026 15:49:45 +0200 Subject: [PATCH 09/28] update felira web Signed-off-by: Basil Bruhn --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 28f7c47..5f09ea0 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -402,7 +402,7 @@ services: # LEAPS ultrafast frithjof.nolting@psi.ch felira-web: - image: gitea.psi.ch/leaps/leaps-felira:3.1.18 + image: gitea.psi.ch/leaps/leaps-felira:3.1.39 container_name: felira-web restart: always # volumes: From 6356ae4abc9b13cc175381e2b30db6e6a5545990 Mon Sep 17 00:00:00 2001 From: huang_h Date: Wed, 16 Sep 2026 10:59:02 +0200 Subject: [PATCH 10/28] MCDA software update (#45) Co-authored-by: River Reviewed-on: https://gitea.psi.ch/linux/WebHosting_DMZ/pulls/45 Co-authored-by: huang_h --- docker-compose.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 5f09ea0..4c0e1cd 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -57,7 +57,7 @@ services: # MCDA SRF Huang He mcda-srf: - image: gitea.psi.ch/images/mcda-srf:1.0.2 + image: gitea.psi.ch/images/mcda-srf:1.0.3 container_name: mcda-srf restart: always networks: @@ -269,7 +269,7 @@ services: # Enea Zeolla drsa-tiermaker: - image: gitea.psi.ch/images/drsa-tiermaker:0.2.3 + image: gitea.psi.ch/images/drsa-tiermaker:0.2.4 container_name: drsa-tiermaker restart: always depends_on: From f421394fcbf3ba8cbfa23a7ed6f8c9eda58049c7 Mon Sep 17 00:00:00 2001 From: Basil Bruhn Date: Wed, 16 Sep 2026 12:48:12 +0200 Subject: [PATCH 11/28] undeploy tubulin Signed-off-by: Basil Bruhn --- docker-compose.yaml | 324 ++++++++++++++++++++++---------------------- 1 file changed, 162 insertions(+), 162 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 4c0e1cd..c25291d 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -431,168 +431,168 @@ services: networks: - leaps_db - # João Pedro Agostinho de Sousa - # tubulin.xyz - neo4j: - image: neo4j:5 - environment: - NEO4J_AUTH: neo4j/${NEO4J_PASSWORD} - NEO4J_server_memory_heap_initial__size: 1G - NEO4J_server_memory_heap_max__size: 2G - NEO4J_server_memory_pagecache_size: 1G - volumes: - - /mount/webhosting_dmz_write/tubulin/neo4j/data:/data - - /mount/webhosting_dmz_write/tubulin/neo4j/logs:/logs - healthcheck: - test: - [ - "CMD", - "cypher-shell", - "-u", - "neo4j", - "-p", - "${NEO4J_PASSWORD}", - "RETURN 1", - ] - interval: 10s - timeout: 5s - retries: 10 - start_period: 30s - restart: always - networks: - - tubulinxyz_backend - stop_grace_period: 60s - logging: - driver: json-file - options: - max-size: "50m" - max-file: "5" - deploy: - resources: - limits: - memory: 4G - - bootstrap: - image: ghcr.io/rtviii/tubulinxyz:latest - pull_policy: always - environment: - NEO4J_URI: bolt://neo4j:7687 - NEO4J_USER: neo4j - NEO4J_PASSWORD: ${NEO4J_PASSWORD} - NEO4J_CURRENTDB: neo4j - TUBXZ_ROOT: /app - TUBETL_DATA: /mnt/tubetl_data - NCBI_TAXA_SQLITE: /app/.etetoolkit/taxa.sqlite - volumes: - - /mount/webhosting_dmz_write/tubulin/data:/mnt/tubetl_data - - /mount/webhosting_dmz_write/tubulin/log:/var/log/tubxz - depends_on: - neo4j: - condition: service_healthy - entrypoint: ["/bin/sh", "/app/scripts/init_and_seed.sh"] - restart: always - networks: - - tubulinxyz_backend - logging: - driver: json-file - options: - max-size: "50m" - max-file: "3" - deploy: - resources: - limits: - memory: 4G - - backend: - image: ghcr.io/rtviii/tubulinxyz:latest - pull_policy: always - environment: - NEO4J_URI: bolt://neo4j:7687 - NEO4J_USER: neo4j - NEO4J_PASSWORD: ${NEO4J_PASSWORD} - NEO4J_CURRENTDB: neo4j - SECRET_KEY: ${SECRET_KEY} - TUBXZ_ROOT: /app - TUBETL_DATA: /mnt/tubetl_data - NCBI_TAXA_SQLITE: /app/.etetoolkit/taxa.sqlite - volumes: - - /mount/webhosting_dmz_write/tubulin/data:/mnt/tubetl_data - - /mount/webhosting_dmz_write/tubulin/log:/var/log/tubxz:ro - depends_on: - neo4j: - condition: service_healthy - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8000/health"] - interval: 30s - timeout: 5s - retries: 3 - start_period: 15s - restart: always - networks: - - backend - - tubulinxyz_backend - stop_grace_period: 30s - logging: - driver: json-file - options: - max-size: "50m" - max-file: "5" - deploy: - resources: - limits: - memory: 2G - - scheduler: - image: ghcr.io/rtviii/tubulinxyz:latest - pull_policy: always - environment: - NEO4J_URI: bolt://neo4j:7687 - NEO4J_USER: neo4j - NEO4J_PASSWORD: ${NEO4J_PASSWORD} - NEO4J_CURRENTDB: neo4j - TUBXZ_ROOT: /app - TUBETL_DATA: /mnt/tubetl_data - NCBI_TAXA_SQLITE: /app/.etetoolkit/taxa.sqlite - volumes: - - /mount/webhosting_dmz_write/tubulin/data:/mnt/tubetl_data - - /mount/webhosting_dmz_write/tubulin/log:/var/log/tubxz - depends_on: - neo4j: - condition: service_healthy - entrypoint: ["/bin/sh", "/app/scripts/start_scheduler.sh"] - restart: always - networks: - - tubulinxyz_backend - logging: - driver: json-file - options: - max-size: "50m" - max-file: "5" - deploy: - resources: - limits: - memory: 4G - - frontend: - image: ghcr.io/rtviii/tubulinxyz-frontend:latest - pull_policy: always - depends_on: - backend: - condition: service_healthy - restart: always - networks: - - backend - - tubulinxyz_backend - logging: - driver: json-file - options: - max-size: "50m" - max-file: "3" - deploy: - resources: - limits: - memory: 512M - +# # João Pedro Agostinho de Sousa +# # tubulin.xyz +# neo4j: +# image: neo4j:5 +# environment: +# NEO4J_AUTH: neo4j/${NEO4J_PASSWORD} +# NEO4J_server_memory_heap_initial__size: 1G +# NEO4J_server_memory_heap_max__size: 2G +# NEO4J_server_memory_pagecache_size: 1G +# volumes: +# - /mount/webhosting_dmz_write/tubulin/neo4j/data:/data +# - /mount/webhosting_dmz_write/tubulin/neo4j/logs:/logs +# healthcheck: +# test: +# [ +# "CMD", +# "cypher-shell", +# "-u", +# "neo4j", +# "-p", +# "${NEO4J_PASSWORD}", +# "RETURN 1", +# ] +# interval: 10s +# timeout: 5s +# retries: 10 +# start_period: 30s +# restart: always +# networks: +# - tubulinxyz_backend +# stop_grace_period: 60s +# logging: +# driver: json-file +# options: +# max-size: "50m" +# max-file: "5" +# deploy: +# resources: +# limits: +# memory: 4G +# +# bootstrap: +# image: ghcr.io/rtviii/tubulinxyz:latest +# pull_policy: always +# environment: +# NEO4J_URI: bolt://neo4j:7687 +# NEO4J_USER: neo4j +# NEO4J_PASSWORD: ${NEO4J_PASSWORD} +# NEO4J_CURRENTDB: neo4j +# TUBXZ_ROOT: /app +# TUBETL_DATA: /mnt/tubetl_data +# NCBI_TAXA_SQLITE: /app/.etetoolkit/taxa.sqlite +# volumes: +# - /mount/webhosting_dmz_write/tubulin/data:/mnt/tubetl_data +# - /mount/webhosting_dmz_write/tubulin/log:/var/log/tubxz +# depends_on: +# neo4j: +# condition: service_healthy +# entrypoint: ["/bin/sh", "/app/scripts/init_and_seed.sh"] +# restart: always +# networks: +# - tubulinxyz_backend +# logging: +# driver: json-file +# options: +# max-size: "50m" +# max-file: "3" +# deploy: +# resources: +# limits: +# memory: 4G +# +# backend: +# image: ghcr.io/rtviii/tubulinxyz:latest +# pull_policy: always +# environment: +# NEO4J_URI: bolt://neo4j:7687 +# NEO4J_USER: neo4j +# NEO4J_PASSWORD: ${NEO4J_PASSWORD} +# NEO4J_CURRENTDB: neo4j +# SECRET_KEY: ${SECRET_KEY} +# TUBXZ_ROOT: /app +# TUBETL_DATA: /mnt/tubetl_data +# NCBI_TAXA_SQLITE: /app/.etetoolkit/taxa.sqlite +# volumes: +# - /mount/webhosting_dmz_write/tubulin/data:/mnt/tubetl_data +# - /mount/webhosting_dmz_write/tubulin/log:/var/log/tubxz:ro +# depends_on: +# neo4j: +# condition: service_healthy +# healthcheck: +# test: ["CMD", "curl", "-f", "http://localhost:8000/health"] +# interval: 30s +# timeout: 5s +# retries: 3 +# start_period: 15s +# restart: always +# networks: +# - backend +# - tubulinxyz_backend +# stop_grace_period: 30s +# logging: +# driver: json-file +# options: +# max-size: "50m" +# max-file: "5" +# deploy: +# resources: +# limits: +# memory: 2G +# +# scheduler: +# image: ghcr.io/rtviii/tubulinxyz:latest +# pull_policy: always +# environment: +# NEO4J_URI: bolt://neo4j:7687 +# NEO4J_USER: neo4j +# NEO4J_PASSWORD: ${NEO4J_PASSWORD} +# NEO4J_CURRENTDB: neo4j +# TUBXZ_ROOT: /app +# TUBETL_DATA: /mnt/tubetl_data +# NCBI_TAXA_SQLITE: /app/.etetoolkit/taxa.sqlite +# volumes: +# - /mount/webhosting_dmz_write/tubulin/data:/mnt/tubetl_data +# - /mount/webhosting_dmz_write/tubulin/log:/var/log/tubxz +# depends_on: +# neo4j: +# condition: service_healthy +# entrypoint: ["/bin/sh", "/app/scripts/start_scheduler.sh"] +# restart: always +# networks: +# - tubulinxyz_backend +# logging: +# driver: json-file +# options: +# max-size: "50m" +# max-file: "5" +# deploy: +# resources: +# limits: +# memory: 4G +# +# frontend: +# image: ghcr.io/rtviii/tubulinxyz-frontend:latest +# pull_policy: always +# depends_on: +# backend: +# condition: service_healthy +# restart: always +# networks: +# - backend +# - tubulinxyz_backend +# logging: +# driver: json-file +# options: +# max-size: "50m" +# max-file: "3" +# deploy: +# resources: +# limits: +# memory: 512M +# networks: public: backend: From edd3bb328d57d80efadddcede165659f8bca8d95 Mon Sep 17 00:00:00 2001 From: pombas_n Date: Wed, 16 Sep 2026 14:48:50 +0200 Subject: [PATCH 12/28] Update docker-compose.yaml --- docker-compose.yaml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docker-compose.yaml b/docker-compose.yaml index c25291d..5b5e7fb 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -431,6 +431,27 @@ services: networks: - leaps_db + # Noah Pombas Teixeira De Freitas / + # PSI Trail - psitrail.psi.ch + # Image: gitea.psi.ch/bb_if_produktiv/psitrail:181 + psitrail: + image: gitea.psi.ch/bb_if_produktiv/psitrail:181 + container_name: psitrail + restart: always + networks: + - backend + + # Noah Pombas Teixeira De Freitas / + # Pocket App - pocket.psi.ch + # Image: gitea.psi.ch/bb_if_produktiv/pocketapp:17 + pocketapp: + image: gitea.psi.ch/bb_if_produktiv/pocketapp:17 + container_name: pocketapp + restart: always + networks: + - backend + + # # João Pedro Agostinho de Sousa # # tubulin.xyz # neo4j: From 4d47a6154e4c05301af2ea6c10f72f139fb05cd7 Mon Sep 17 00:00:00 2001 From: pombas_n Date: Wed, 16 Sep 2026 14:49:28 +0200 Subject: [PATCH 13/28] Add conf.d/psitrail.conf --- conf.d/psitrail.conf | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 conf.d/psitrail.conf diff --git a/conf.d/psitrail.conf b/conf.d/psitrail.conf new file mode 100644 index 0000000..c9104b5 --- /dev/null +++ b/conf.d/psitrail.conf @@ -0,0 +1,23 @@ +server { + listen 80; + server_name psitrail.psi.ch; + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl; + server_name psitrail.psi.ch; + + ssl_certificate /etc/nginx/certs/lx-docker-dmz-01.psi.ch.crt; + ssl_certificate_key /etc/nginx/private/lx-docker-dmz-01.psi.ch.key; + + location / { + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_pass http://psitrail:4200; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} \ No newline at end of file From 499caabe8ad59960b8cfe265cde2d70ec058ca0e Mon Sep 17 00:00:00 2001 From: pombas_n Date: Wed, 16 Sep 2026 14:49:42 +0200 Subject: [PATCH 14/28] Add conf.d/pocketapp.conf --- conf.d/pocketapp.conf | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 conf.d/pocketapp.conf diff --git a/conf.d/pocketapp.conf b/conf.d/pocketapp.conf new file mode 100644 index 0000000..67c6bab --- /dev/null +++ b/conf.d/pocketapp.conf @@ -0,0 +1,23 @@ +server { + listen 80; + server_name pocket.psi.ch; + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl; + server_name pocket.psi.ch; + + ssl_certificate /etc/nginx/certs/lx-docker-dmz-01.psi.ch.crt; + ssl_certificate_key /etc/nginx/private/lx-docker-dmz-01.psi.ch.key; + + location / { + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_pass http://pocket:4200; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} \ No newline at end of file From f343d801330f544c232d4170b8fcc819ffabea8a Mon Sep 17 00:00:00 2001 From: pombas_n Date: Wed, 16 Sep 2026 14:51:23 +0200 Subject: [PATCH 15/28] Update conf.d/pocketapp.conf --- conf.d/pocketapp.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.d/pocketapp.conf b/conf.d/pocketapp.conf index 67c6bab..b43abd0 100644 --- a/conf.d/pocketapp.conf +++ b/conf.d/pocketapp.conf @@ -14,7 +14,7 @@ server { location / { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; - proxy_pass http://pocket:4200; + proxy_pass http://pocketapp:4200; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; From 49febaef19807942436770a3a2329e99609c6d2a Mon Sep 17 00:00:00 2001 From: Basil Bruhn Date: Thu, 17 Sep 2026 10:11:00 +0200 Subject: [PATCH 16/28] tubulin decom Signed-off-by: Basil Bruhn --- conf.d/{tubulinxyz.conf => tubulinxyz.conf.bak} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename conf.d/{tubulinxyz.conf => tubulinxyz.conf.bak} (100%) diff --git a/conf.d/tubulinxyz.conf b/conf.d/tubulinxyz.conf.bak similarity index 100% rename from conf.d/tubulinxyz.conf rename to conf.d/tubulinxyz.conf.bak From c09f51f774079aa624f469625da732a98da4b1d6 Mon Sep 17 00:00:00 2001 From: Basil Bruhn Date: Thu, 17 Sep 2026 11:30:41 +0200 Subject: [PATCH 17/28] update felira web Signed-off-by: Basil Bruhn --- docker-compose.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 5b5e7fb..5d1703b 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -402,7 +402,7 @@ services: # LEAPS ultrafast frithjof.nolting@psi.ch felira-web: - image: gitea.psi.ch/leaps/leaps-felira:3.1.39 + image: gitea.psi.ch/leaps/leaps-felira:3.1.45 container_name: felira-web restart: always # volumes: @@ -450,7 +450,6 @@ services: restart: always networks: - backend - # # João Pedro Agostinho de Sousa # # tubulin.xyz From e651c810c9ab0dd63f5d947a0d1522abd2fa4d6d Mon Sep 17 00:00:00 2001 From: Basil Bruhn Date: Thu, 17 Sep 2026 13:18:23 +0200 Subject: [PATCH 18/28] update db name for felira Signed-off-by: Basil Bruhn --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 5d1703b..f47bec8 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -416,7 +416,7 @@ services: - DB_DATABASE=felira_leaps_ultrafast - DB_USERNAME=felira_leaps_ultrafast - DB_PASSWORD=${LEAPS_DB_PW} - felira-db: + felira-database: image: mariadb:latest container_name: felira-db restart: always From b93a6a96139efbbb6359fc8a4bbb4eccca3523d4 Mon Sep 17 00:00:00 2001 From: Basil Bruhn Date: Thu, 17 Sep 2026 13:18:57 +0200 Subject: [PATCH 19/28] db name Signed-off-by: Basil Bruhn --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index f47bec8..40cdb8f 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -408,7 +408,7 @@ services: # volumes: # - /mount/webhosting_dmz_write/leaps/web:/var/www/html:rw depends_on: - - felira-db + - felira-database networks: - backend - leaps_db From 8562d2c9cb96bff664e4079166a919d5fe4ebd8b Mon Sep 17 00:00:00 2001 From: Basil Bruhn Date: Thu, 17 Sep 2026 13:20:22 +0200 Subject: [PATCH 20/28] wer lesen kann Signed-off-by: Basil Bruhn --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 40cdb8f..cd5073b 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -418,7 +418,7 @@ services: - DB_PASSWORD=${LEAPS_DB_PW} felira-database: image: mariadb:latest - container_name: felira-db + container_name: felira-database restart: always environment: - MARIADB_ROOT_PASSWORD=${LEAPS_DB_PW} From 9bdaa10ef1954696c9be63e2cd61267a24d4bd9e Mon Sep 17 00:00:00 2001 From: romainsacchi Date: Thu, 17 Sep 2026 21:56:59 +0200 Subject: [PATCH 21/28] Fix CLIC package worker unsupported skip-checks argument --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index cd5073b..d1d9ef5 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -199,7 +199,7 @@ services: - /mount/webhosting_dmz_write/clic/media:/app/media - /mount/webhosting_dmz_write/clic/impact_factors:/app/data/impact_factors:ro entrypoint: ["python"] - command: ["manage.py", "process_package_exports", "--skip-checks"] + command: ["manage.py", "process_package_exports"] depends_on: clic-db: condition: service_healthy From 0004e37bf2d55fa70ec588a5c6cf0cc2a4e5997a Mon Sep 17 00:00:00 2001 From: Gitea Actions Date: Fri, 18 Sep 2026 19:11:47 +0000 Subject: [PATCH 22/28] Update psitrail and pocketapp versions --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index d1d9ef5..cf60dd1 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -445,7 +445,7 @@ services: # Pocket App - pocket.psi.ch # Image: gitea.psi.ch/bb_if_produktiv/pocketapp:17 pocketapp: - image: gitea.psi.ch/bb_if_produktiv/pocketapp:17 + image: gitea.psi.ch/bb_if_produktiv/pocketapp:21 container_name: pocketapp restart: always networks: From 634c045523f63be135a3d874b624a86df70ee3e0 Mon Sep 17 00:00:00 2001 From: romainsacchi Date: Sat, 19 Sep 2026 22:35:13 +0200 Subject: [PATCH 23/28] Update CLIC image to reviewed archive release 5bbfcaf --- docker-compose.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index cf60dd1..35cc312 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -147,7 +147,7 @@ services: # Romain Sacchi # CLIC Django platform clic-web: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:754f9f8} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:5bbfcaf} container_name: clic-web restart: always env_file: @@ -183,7 +183,7 @@ services: - clic_backend clic-package-exports: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:754f9f8} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:5bbfcaf} container_name: clic-package-exports restart: always env_file: @@ -209,7 +209,7 @@ services: - clic_backend clic-brightway-json-exports: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:754f9f8} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:5bbfcaf} container_name: clic-brightway-json-exports restart: always env_file: From 64959d3d29dbb1d625a271a678449fdb119ff658 Mon Sep 17 00:00:00 2001 From: romainsacchi Date: Sat, 19 Sep 2026 23:40:38 +0200 Subject: [PATCH 24/28] Update CLIC image for verified Zenodo nightly uploads --- docker-compose.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 35cc312..bb8309b 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -147,7 +147,7 @@ services: # Romain Sacchi # CLIC Django platform clic-web: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:5bbfcaf} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:58e902a} container_name: clic-web restart: always env_file: @@ -183,7 +183,7 @@ services: - clic_backend clic-package-exports: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:5bbfcaf} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:58e902a} container_name: clic-package-exports restart: always env_file: @@ -209,7 +209,7 @@ services: - clic_backend clic-brightway-json-exports: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:5bbfcaf} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:58e902a} container_name: clic-brightway-json-exports restart: always env_file: From fea43ce1cbef61f64f510b5ce1c651a7ee0d53f3 Mon Sep 17 00:00:00 2001 From: romainsacchi Date: Sun, 20 Sep 2026 20:17:35 +0200 Subject: [PATCH 25/28] Automate CLIC archive recovery and nightly backups in Compose --- CLIC-ARCHIVE.md | 61 ++++++++++++++++++++++++++++++++++++++ docker-compose.yaml | 71 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 127 insertions(+), 5 deletions(-) create mode 100644 CLIC-ARCHIVE.md diff --git a/CLIC-ARCHIVE.md b/CLIC-ARCHIVE.md new file mode 100644 index 0000000..2d6464e --- /dev/null +++ b/CLIC-ARCHIVE.md @@ -0,0 +1,61 @@ +# CLIC archive cutover: operator actions + +This deployment enables the approved inventory-only Zenodo recovery and nightly backup route. +Heroku is frozen; its database and media are retained for rollback. Do not reopen its writers +or enable another archive publisher while PSI is authoritative. + +1. Add `INVENTORY_ARCHIVE_TOKEN` to the existing protected + `/mount/webhosting_dmz_write/clic/clic.env`, using the production Zenodo token supplied + securely by Romain. Keep all existing database, Django and SMTP settings. Do not attach the + filled env file or token to this repository, pull request or issue. +2. Merge/deploy the Compose change and recreate all four CLIC application services. Ensure + any host `CLIC_IMAGE` override selects `gitea.psi.ch/images/clic:ae59c15` or is removed. + No metadata-file copy, new host mount, cron job or systemd archive timer is required. +3. Check web and archive-worker health, the public catalog and SMTP delivery. Monitor unhealthy + containers and host outages through normal PSI monitoring. Create local admin credentials + separately; accounts and private data are not in the public archive. + +## Automatic behavior + +- Web applies migrations and restores only an empty inventory catalog, from the latest + published record owned by `86122` in series `22850223`. It verifies checksums/schema and + imports atomically. A failure prevents web startup; existing catalogs are not overwritten. +- Current cutover record: https://zenodo.org/records/22850224, containing **3,377 datasets and + 3,916 versions**. SHA-256: + `169fe991599e138ddd15eae7aa56b2c58ab80bf865e8087dfd4c303f868386ea`. +- Both bootstrap pins are intentionally empty. After future nightly uploads, an empty database + must recover the latest trusted version, not the original cutover snapshot. +- Both export workers and `clic-inventory-archive` wait for web readiness before starting; + the web healthcheck allows ten minutes for first bootstrap. +- Approved collection metadata is bundled at `/app/config/inventory-archive-metadata.json`. + Restored per-version redistribution approvals require no separate authorization file. +- Only the archive application service receives the publisher token. Its first check must + match the trusted archive and report `unchanged`; a mismatch creates no draft and alerts. + After that handover, daily checks start at **03:00 UTC**, polling every five minutes with + catch-up/retry. Unchanged inventories produce no new Zenodo version. +- Its independent healthcheck emails `romain.sacchi@psi.ch` through the existing SMTP settings + on publication failure or checks older than 26 hours. A down host or broken SMTP needs + external monitoring; Docker does not automatically restart an unhealthy running process. + +The image is built from application revision `ae59c154309d4c4ccd44ae2b22f6e81a7e0dcffb`. +Registry digest: `sha256:a3cba10de3822b848cadbbedfd2ec63f70c94f580ae585ca8ff50d8250528374` +(`linux/amd64`). Full verification passed: 855 backend tests, 20 browser tests and 108 +PostgreSQL archive/worker tests. The exact image passed token-free production restoration, +restart idempotence, a real automatic sandbox upload (record `606103`), unchanged-content +skipping and recovery of that new snapshot into a second empty database. +Archive migrations `0041` and `0042` run automatically; this scheduler adds no migration. +Private users, uploaded originals, reviews and impact scores are not restored. Keep ordinary +private operational backups and provision licensed impact factors independently if required. + +From the existing hosting project, inspect: + +```sh +docker compose logs --tail=100 clic-web clic-inventory-archive +docker compose exec -T clic-inventory-archive python manage.py inventory_archive_status +``` + +Old restoration-only/combined env overlays and host-timer instructions are superseded by this +Compose configuration. Do not enable legacy archive timers alongside this container. Env changes +require recreation, not just restart. Before rollback, stop all PSI application services including +the archive publisher, remove its token, and coordinate with Romain before reopening Heroku. +Independent PSI edits must be reconciled before any rollback. diff --git a/docker-compose.yaml b/docker-compose.yaml index bb8309b..1d33573 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -147,7 +147,7 @@ services: # Romain Sacchi # CLIC Django platform clic-web: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:58e902a} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:ae59c15} container_name: clic-web restart: always env_file: @@ -159,6 +159,15 @@ services: - CLIC_CACHE_BACKEND=redis - CLIC_REDIS_URL=redis://clic-redis:6379/0 - CLIC_REQUIRE_SHARED_CACHE=1 + - INVENTORY_ARCHIVE_ENVIRONMENT=production + - INVENTORY_ARCHIVE_AUTO_RESTORE=1 + - INVENTORY_ARCHIVE_PUBLISH_MODE=off + - INVENTORY_ARCHIVE_TERMS_REVIEWED=0 + - INVENTORY_ARCHIVE_TOKEN= + - INVENTORY_ARCHIVE_OWNER_ID=86122 + - INVENTORY_ARCHIVE_SERIES_ID=22850223 + - INVENTORY_ARCHIVE_BOOTSTRAP_RECORD_ID= + - INVENTORY_ARCHIVE_BOOTSTRAP_SHA256= volumes: - /mount/webhosting_dmz_write/clic/media:/app/media - /mount/webhosting_dmz_write/clic/impact_factors:/app/data/impact_factors:ro @@ -173,17 +182,17 @@ services: - CMD - python - -c - - "import urllib.request; r = urllib.request.Request('http://127.0.0.1:8000/health/live/', headers={'Host': 'clic.psi.ch', 'X-Forwarded-Proto': 'https'}); urllib.request.urlopen(r, timeout=5)" + - "import urllib.request; r = urllib.request.Request('http://127.0.0.1:8000/health/ready/', headers={'Host': 'clic.psi.ch', 'X-Forwarded-Proto': 'https'}); urllib.request.urlopen(r, timeout=5)" interval: 30s timeout: 5s retries: 5 - start_period: 30s + start_period: 10m networks: - backend - clic_backend clic-package-exports: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:58e902a} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:ae59c15} container_name: clic-package-exports restart: always env_file: @@ -195,12 +204,17 @@ services: - CLIC_CACHE_BACKEND=redis - CLIC_REDIS_URL=redis://clic-redis:6379/0 - CLIC_REQUIRE_SHARED_CACHE=1 + - INVENTORY_ARCHIVE_AUTO_RESTORE=0 + - INVENTORY_ARCHIVE_PUBLISH_MODE=off + - INVENTORY_ARCHIVE_TOKEN= volumes: - /mount/webhosting_dmz_write/clic/media:/app/media - /mount/webhosting_dmz_write/clic/impact_factors:/app/data/impact_factors:ro entrypoint: ["python"] command: ["manage.py", "process_package_exports"] depends_on: + clic-web: + condition: service_healthy clic-db: condition: service_healthy clic-redis: @@ -209,7 +223,7 @@ services: - clic_backend clic-brightway-json-exports: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:58e902a} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:ae59c15} container_name: clic-brightway-json-exports restart: always env_file: @@ -221,6 +235,9 @@ services: - CLIC_CACHE_BACKEND=redis - CLIC_REDIS_URL=redis://clic-redis:6379/0 - CLIC_REQUIRE_SHARED_CACHE=1 + - INVENTORY_ARCHIVE_AUTO_RESTORE=0 + - INVENTORY_ARCHIVE_PUBLISH_MODE=off + - INVENTORY_ARCHIVE_TOKEN= volumes: - /mount/webhosting_dmz_write/clic/media:/app/media - /mount/webhosting_dmz_write/clic/impact_factors:/app/data/impact_factors:ro @@ -234,6 +251,8 @@ services: "${CLIC_API_EXPORT_POLL_SECONDS:-2}", ] depends_on: + clic-web: + condition: service_healthy clic-db: condition: service_healthy clic-redis: @@ -241,12 +260,54 @@ services: networks: - clic_backend + clic-inventory-archive: + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:ae59c15} + container_name: clic-inventory-archive + restart: always + env_file: + - /mount/webhosting_dmz_write/clic/clic.env + environment: + - DJANGO_SETTINGS_MODULE=config.settings.production + - POSTGRES_HOST=clic-db + - POSTGRES_PORT=5432 + - CLIC_CACHE_BACKEND=redis + - CLIC_REDIS_URL=redis://clic-redis:6379/0 + - CLIC_REQUIRE_SHARED_CACHE=1 + - IMPACT_SCORES_ENABLED=0 + - INVENTORY_ARCHIVE_ENVIRONMENT=production + - INVENTORY_ARCHIVE_AUTO_RESTORE=0 + - INVENTORY_ARCHIVE_PUBLISH_MODE=scheduled + - INVENTORY_ARCHIVE_TERMS_REVIEWED=1 + - INVENTORY_ARCHIVE_OWNER_ID=86122 + - INVENTORY_ARCHIVE_SERIES_ID=22850223 + - INVENTORY_ARCHIVE_BOOTSTRAP_RECORD_ID= + - INVENTORY_ARCHIVE_BOOTSTRAP_SHA256= + - INVENTORY_ARCHIVE_METADATA_FILE=/app/config/inventory-archive-metadata.json + - INVENTORY_ARCHIVE_REDISTRIBUTION_FILE= + - INVENTORY_ARCHIVE_ALERT_EMAIL=romain.sacchi@psi.ch + entrypoint: ["python"] + command: ["manage.py", "run_inventory_archive_worker"] + depends_on: + clic-web: + condition: service_healthy + healthcheck: + test: ["CMD", "python", "manage.py", "inventory_archive_status", "--alert"] + interval: 5m + timeout: 60s + retries: 1 + start_period: 10m + stop_grace_period: 3m + networks: + - clic_backend + clic-db: image: postgres:16 container_name: clic-db restart: always env_file: - /mount/webhosting_dmz_write/clic/clic.env + environment: + - INVENTORY_ARCHIVE_TOKEN= volumes: - /mount/webhosting_dmz_write/clic/postgres:/var/lib/postgresql/data healthcheck: From cedd87127c6e238d170afcf0dab9af1cd26643da Mon Sep 17 00:00:00 2001 From: romainsacchi Date: Mon, 21 Sep 2026 13:11:22 +0200 Subject: [PATCH 26/28] Remove CLIC archive handoff document from PR --- CLIC-ARCHIVE.md | 61 ------------------------------------------------- 1 file changed, 61 deletions(-) delete mode 100644 CLIC-ARCHIVE.md diff --git a/CLIC-ARCHIVE.md b/CLIC-ARCHIVE.md deleted file mode 100644 index 2d6464e..0000000 --- a/CLIC-ARCHIVE.md +++ /dev/null @@ -1,61 +0,0 @@ -# CLIC archive cutover: operator actions - -This deployment enables the approved inventory-only Zenodo recovery and nightly backup route. -Heroku is frozen; its database and media are retained for rollback. Do not reopen its writers -or enable another archive publisher while PSI is authoritative. - -1. Add `INVENTORY_ARCHIVE_TOKEN` to the existing protected - `/mount/webhosting_dmz_write/clic/clic.env`, using the production Zenodo token supplied - securely by Romain. Keep all existing database, Django and SMTP settings. Do not attach the - filled env file or token to this repository, pull request or issue. -2. Merge/deploy the Compose change and recreate all four CLIC application services. Ensure - any host `CLIC_IMAGE` override selects `gitea.psi.ch/images/clic:ae59c15` or is removed. - No metadata-file copy, new host mount, cron job or systemd archive timer is required. -3. Check web and archive-worker health, the public catalog and SMTP delivery. Monitor unhealthy - containers and host outages through normal PSI monitoring. Create local admin credentials - separately; accounts and private data are not in the public archive. - -## Automatic behavior - -- Web applies migrations and restores only an empty inventory catalog, from the latest - published record owned by `86122` in series `22850223`. It verifies checksums/schema and - imports atomically. A failure prevents web startup; existing catalogs are not overwritten. -- Current cutover record: https://zenodo.org/records/22850224, containing **3,377 datasets and - 3,916 versions**. SHA-256: - `169fe991599e138ddd15eae7aa56b2c58ab80bf865e8087dfd4c303f868386ea`. -- Both bootstrap pins are intentionally empty. After future nightly uploads, an empty database - must recover the latest trusted version, not the original cutover snapshot. -- Both export workers and `clic-inventory-archive` wait for web readiness before starting; - the web healthcheck allows ten minutes for first bootstrap. -- Approved collection metadata is bundled at `/app/config/inventory-archive-metadata.json`. - Restored per-version redistribution approvals require no separate authorization file. -- Only the archive application service receives the publisher token. Its first check must - match the trusted archive and report `unchanged`; a mismatch creates no draft and alerts. - After that handover, daily checks start at **03:00 UTC**, polling every five minutes with - catch-up/retry. Unchanged inventories produce no new Zenodo version. -- Its independent healthcheck emails `romain.sacchi@psi.ch` through the existing SMTP settings - on publication failure or checks older than 26 hours. A down host or broken SMTP needs - external monitoring; Docker does not automatically restart an unhealthy running process. - -The image is built from application revision `ae59c154309d4c4ccd44ae2b22f6e81a7e0dcffb`. -Registry digest: `sha256:a3cba10de3822b848cadbbedfd2ec63f70c94f580ae585ca8ff50d8250528374` -(`linux/amd64`). Full verification passed: 855 backend tests, 20 browser tests and 108 -PostgreSQL archive/worker tests. The exact image passed token-free production restoration, -restart idempotence, a real automatic sandbox upload (record `606103`), unchanged-content -skipping and recovery of that new snapshot into a second empty database. -Archive migrations `0041` and `0042` run automatically; this scheduler adds no migration. -Private users, uploaded originals, reviews and impact scores are not restored. Keep ordinary -private operational backups and provision licensed impact factors independently if required. - -From the existing hosting project, inspect: - -```sh -docker compose logs --tail=100 clic-web clic-inventory-archive -docker compose exec -T clic-inventory-archive python manage.py inventory_archive_status -``` - -Old restoration-only/combined env overlays and host-timer instructions are superseded by this -Compose configuration. Do not enable legacy archive timers alongside this container. Env changes -require recreation, not just restart. Before rollback, stop all PSI application services including -the archive publisher, remove its token, and coordinate with Romain before reopening Heroku. -Independent PSI edits must be reconciled before any rollback. From 1f58c8d2892def887941d6d872354e31972241b9 Mon Sep 17 00:00:00 2001 From: romainsacchi Date: Tue, 22 Sep 2026 13:39:07 +0200 Subject: [PATCH 27/28] Update CLIC services to reviewed export release 1a5d217 --- docker-compose.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 1d33573..7f2be00 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -147,7 +147,7 @@ services: # Romain Sacchi # CLIC Django platform clic-web: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:ae59c15} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:1a5d217@sha256:ecd9b2fd234cf381b6026a3fef18a54f6b597133a53fbb608793c4fc26582fa6} container_name: clic-web restart: always env_file: @@ -192,7 +192,7 @@ services: - clic_backend clic-package-exports: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:ae59c15} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:1a5d217@sha256:ecd9b2fd234cf381b6026a3fef18a54f6b597133a53fbb608793c4fc26582fa6} container_name: clic-package-exports restart: always env_file: @@ -223,7 +223,7 @@ services: - clic_backend clic-brightway-json-exports: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:ae59c15} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:1a5d217@sha256:ecd9b2fd234cf381b6026a3fef18a54f6b597133a53fbb608793c4fc26582fa6} container_name: clic-brightway-json-exports restart: always env_file: @@ -261,7 +261,7 @@ services: - clic_backend clic-inventory-archive: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:ae59c15} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:1a5d217@sha256:ecd9b2fd234cf381b6026a3fef18a54f6b597133a53fbb608793c4fc26582fa6} container_name: clic-inventory-archive restart: always env_file: From 51fb3a5de31a9be4e2ad75882a113a1efc020d6f Mon Sep 17 00:00:00 2001 From: romainsacchi Date: Tue, 22 Sep 2026 15:46:00 +0200 Subject: [PATCH 28/28] Fix CLIC 502 by deploying startup permission repair a3b90f8 --- docker-compose.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 7f2be00..a083463 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -147,7 +147,7 @@ services: # Romain Sacchi # CLIC Django platform clic-web: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:1a5d217@sha256:ecd9b2fd234cf381b6026a3fef18a54f6b597133a53fbb608793c4fc26582fa6} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:a3b90f8@sha256:84c0da77b8aab3a31391e3f713ef3ae701e08824ae4036ffe634105968f581e0} container_name: clic-web restart: always env_file: @@ -192,7 +192,7 @@ services: - clic_backend clic-package-exports: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:1a5d217@sha256:ecd9b2fd234cf381b6026a3fef18a54f6b597133a53fbb608793c4fc26582fa6} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:a3b90f8@sha256:84c0da77b8aab3a31391e3f713ef3ae701e08824ae4036ffe634105968f581e0} container_name: clic-package-exports restart: always env_file: @@ -223,7 +223,7 @@ services: - clic_backend clic-brightway-json-exports: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:1a5d217@sha256:ecd9b2fd234cf381b6026a3fef18a54f6b597133a53fbb608793c4fc26582fa6} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:a3b90f8@sha256:84c0da77b8aab3a31391e3f713ef3ae701e08824ae4036ffe634105968f581e0} container_name: clic-brightway-json-exports restart: always env_file: @@ -261,7 +261,7 @@ services: - clic_backend clic-inventory-archive: - image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:1a5d217@sha256:ecd9b2fd234cf381b6026a3fef18a54f6b597133a53fbb608793c4fc26582fa6} + image: ${CLIC_IMAGE:-gitea.psi.ch/images/clic:a3b90f8@sha256:84c0da77b8aab3a31391e3f713ef3ae701e08824ae4036ffe634105968f581e0} container_name: clic-inventory-archive restart: always env_file: