From bdaab88f084068dc3eba684cef277c23d3943ec6 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 10 Mar 2026 19:22:12 +0000 Subject: [PATCH 01/12] Add renovate.json --- renovate.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..5db72dd --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ] +} From 2b721698b0ea9ab2d086c11664cb2e7fe0a80a3a Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 22 Oct 2026 14:15:36 +0000 Subject: [PATCH 02/12] chore(deps): update ghcr.io/mailu/admin docker tag to v2024.06.66 --- compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose.yml b/compose.yml index 26da957..909f86e 100644 --- a/compose.yml +++ b/compose.yml @@ -104,7 +104,7 @@ services: - "redis:/data" admin: - image: ghcr.io/mailu/admin:2024.06.61 + image: ghcr.io/mailu/admin:2024.06.66 environment: *default-env healthcheck: disable: true From 74e8c1a3ccab205f142e444d611752d7c997607c Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 22 Oct 2026 14:15:39 +0000 Subject: [PATCH 03/12] chore(deps): update ghcr.io/mailu/dovecot docker tag to v2024.06.66 --- compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose.yml b/compose.yml index 26da957..aec3567 100644 --- a/compose.yml +++ b/compose.yml @@ -117,7 +117,7 @@ services: - default imap: - image: ghcr.io/mailu/dovecot:2024.06.61 + image: ghcr.io/mailu/dovecot:2024.06.66 environment: *default-env secrets: - secret_key From 0f5ee292df570a83e5be20e70f7438fbc13bc5e8 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 22 Oct 2026 14:15:41 +0000 Subject: [PATCH 04/12] chore(deps): update ghcr.io/mailu/nginx docker tag to v2024.06.66 --- compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose.yml b/compose.yml index 26da957..afe051b 100644 --- a/compose.yml +++ b/compose.yml @@ -55,7 +55,7 @@ x-environment: services: app: - image: ghcr.io/mailu/nginx:2024.06.61 + image: ghcr.io/mailu/nginx:2024.06.66 logging: driver: json-file networks: From 57fadc2ea48ec0a368f9e6dcdce27fc2b1d621ce Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 22 Oct 2026 14:15:44 +0000 Subject: [PATCH 05/12] chore(deps): update ghcr.io/mailu/postfix docker tag to v2024.06.66 --- compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose.yml b/compose.yml index 26da957..a51f0dc 100644 --- a/compose.yml +++ b/compose.yml @@ -131,7 +131,7 @@ services: - default smtp: - image: ghcr.io/mailu/postfix:2024.06.61 + image: ghcr.io/mailu/postfix:2024.06.66 environment: *default-env secrets: - secret_key From 872e098bb9fb5c0e1ed9036e8d29c716b110c343 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 22 Oct 2026 14:15:46 +0000 Subject: [PATCH 06/12] chore(deps): update ghcr.io/mailu/rspamd docker tag to v2024.06.66 --- compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose.yml b/compose.yml index 26da957..c30f013 100644 --- a/compose.yml +++ b/compose.yml @@ -143,7 +143,7 @@ services: - app antispam: - image: ghcr.io/mailu/rspamd:2024.06.61 + image: ghcr.io/mailu/rspamd:2024.06.66 environment: *default-env secrets: - secret_key From 88f6f0b876c43b967e7d712c9a01f377ee5bc5ba Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 22 Oct 2026 14:15:50 +0000 Subject: [PATCH 07/12] chore(deps): update ghcr.io/mailu/webmail docker tag to v2024.06.66 --- compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose.yml b/compose.yml index 26da957..1c787fa 100644 --- a/compose.yml +++ b/compose.yml @@ -154,7 +154,7 @@ services: disable: true webmail: - image: ghcr.io/mailu/webmail:2024.06.61 + image: ghcr.io/mailu/webmail:2024.06.66 # entrypoint: "tail -f /dev/null" environment: *default-env networks: From 19afffd8cd46188ae617edefcd4a712ad48fdf2c Mon Sep 17 00:00:00 2001 From: kawaiipunk Date: Thu, 22 Oct 2026 16:14:31 +0100 Subject: [PATCH 08/12] chore: publish 3.2.0+2024.06.61 release --- compose.yml | 2 +- release/3.2.0+2024.06.61 | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 release/3.2.0+2024.06.61 diff --git a/compose.yml b/compose.yml index 1c787fa..abd1520 100644 --- a/compose.yml +++ b/compose.yml @@ -96,7 +96,7 @@ services: - "traefik.http.routers.${STACK_NAME}.rule=Host(`${DOMAIN}`)" - "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}" - "traefik.http.routers.${STACK_NAME}.entrypoints=web-secure" - - "coop-cloud.${STACK_NAME}.version=3.1.5+2024.06.61" + - "coop-cloud.${STACK_NAME}.version=3.2.0+2024.06.61" db: image: redis:8.10.2-alpine diff --git a/release/3.2.0+2024.06.61 b/release/3.2.0+2024.06.61 new file mode 100644 index 0000000..83d1d51 --- /dev/null +++ b/release/3.2.0+2024.06.61 @@ -0,0 +1 @@ +Contains mitigation measures for php2shell \ No newline at end of file From ebe01e00cc9d98539870b27b265c9122d05b0bbc Mon Sep 17 00:00:00 2001 From: kawaiipunk Date: Thu, 22 Oct 2026 16:36:00 +0100 Subject: [PATCH 09/12] chore: publish 3.2.1+2024.06.66 release --- compose.yml | 2 +- release/3.2.1+2024.06.66 | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 release/3.2.1+2024.06.66 diff --git a/compose.yml b/compose.yml index 65bd69d..3eef13d 100644 --- a/compose.yml +++ b/compose.yml @@ -96,7 +96,7 @@ services: - "traefik.http.routers.${STACK_NAME}.rule=Host(`${DOMAIN}`)" - "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}" - "traefik.http.routers.${STACK_NAME}.entrypoints=web-secure" - - "coop-cloud.${STACK_NAME}.version=3.2.0+2024.06.61" + - "coop-cloud.${STACK_NAME}.version=3.2.1+2024.06.66" db: image: redis:8.10.2-alpine diff --git a/release/3.2.1+2024.06.66 b/release/3.2.1+2024.06.66 new file mode 100644 index 0000000..8314bc6 --- /dev/null +++ b/release/3.2.1+2024.06.66 @@ -0,0 +1 @@ +Actual mitigation for php2shell pending further alpine image upgrades \ No newline at end of file From 77659e75c3ca5ce33b6e0e63bfa8253dfc93e4d8 Mon Sep 17 00:00:00 2001 From: Ammar Hussein Date: Fri, 23 Oct 2026 18:37:30 -0700 Subject: [PATCH 10/12] add backup support --- .env.sample | 2 ++ README.md | 4 ++-- abra.sh | 1 + backup_sqlite.py | 36 ++++++++++++++++++++++++++++++++++++ compose.yml | 14 ++++++++++++++ 5 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 backup_sqlite.py diff --git a/.env.sample b/.env.sample index cd1d23f..577bcfb 100644 --- a/.env.sample +++ b/.env.sample @@ -198,3 +198,5 @@ REJECT_UNLISTED_RECIPIENT= # NOTE(3wc): Other values are not supported, as compose.yml does not contain # configuration for them. Pull requests welcome! DB_FLAVOR=sqlite + +ENABLE_BACKUPS=true \ No newline at end of file diff --git a/README.md b/README.md index b246f37..c120be2 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,10 @@ Coöp Cloud + [Mailu][Mailu] = 🥳 * **Category**: Apps -* **Status**: 1, alpha +* **Status**: 2, beta * **Image**: [`mailu/*`](https://hub.docker.com/r/mailu/), 4, upstream * **Healthcheck**: No -* **Backups**: No +* **Backups**: Yes * **Email**: N/A * **Tests**: No * **SSO**: No diff --git a/abra.sh b/abra.sh index 43a8597..ebf8add 100644 --- a/abra.sh +++ b/abra.sh @@ -1,3 +1,4 @@ export CERTDUMPER_POST_VERSION=v1 export POSTFIX_OVERRIDE_VERSION=v17 export SENDER_LOGIN_VERSIONS=v2 +export BACKUP_SQLITE_VERSION=v1 diff --git a/backup_sqlite.py b/backup_sqlite.py new file mode 100644 index 0000000..972a7df --- /dev/null +++ b/backup_sqlite.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +import os +import sqlite3 +from pathlib import Path + +source_path = Path("/data/main.db") +backup_dir = Path("/data/backup") +temporary_path = backup_dir / "main.db.tmp" +backup_path = backup_dir / "main.db" + +os.umask(0o077) +backup_dir.mkdir(mode=0o700, parents=True, exist_ok=True) +temporary_path.unlink(missing_ok=True) + +try: + # Read-only mode prevents silently creating an empty source database. + source = sqlite3.connect( + f"{source_path.as_uri()}?mode=ro", + uri=True, + timeout=60, + ) + destination = sqlite3.connect(temporary_path) + try: + source.backup(destination, pages=256, sleep=0.1) + result = destination.execute("PRAGMA integrity_check").fetchall() + if result != [("ok",)]: + raise RuntimeError(f"SQLite integrity check failed: {result}") + finally: + destination.close() + source.close() + # Only publish a fully written, verified snapshot. + os.replace(temporary_path, backup_path) + print(f"SQLite backup ready: {backup_path}", flush=True) +except Exception: + temporary_path.unlink(missing_ok=True) + raise diff --git a/compose.yml b/compose.yml index 3eef13d..643f4a0 100644 --- a/compose.yml +++ b/compose.yml @@ -97,6 +97,9 @@ services: - "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}" - "traefik.http.routers.${STACK_NAME}.entrypoints=web-secure" - "coop-cloud.${STACK_NAME}.version=3.2.1+2024.06.66" + - "backupbot.backup=${ENABLE_BACKUPS:-true}" + - "backupbot.backup.volumes.traefik_letsencrypt=false" + - "backupbot.backup.volumes.mailu.path=backup" db: image: redis:8.10.2-alpine @@ -115,6 +118,13 @@ services: - "mailu:/data" networks: - default + configs: + - source: backup_sqlite + target: /usr/local/bin/backup_sqlite.py + mode: 0444 + deploy: + labels: + backupbot.backup.pre-hook: "python3 /usr/local/bin/backup_sqlite.py" imap: image: ghcr.io/mailu/dovecot:2024.06.66 @@ -221,6 +231,10 @@ configs: certdumper_post: name: ${STACK_NAME}_certdumper_post_${CERTDUMPER_POST_VERSION} file: certdumper_post.sh + backup_sqlite: + name: ${STACK_NAME}_backup_sqlite_${BACKUP_SQLITE_VERSION} + file: backup_sqlite.py + secrets: secret_key: From 5b6328b68f200fd1feb114ce0616e44816e13848 Mon Sep 17 00:00:00 2001 From: Ammar Hussein Date: Fri, 23 Oct 2026 18:39:10 -0700 Subject: [PATCH 11/12] chore: update image tags --- compose.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compose.yml b/compose.yml index 643f4a0..4a8d499 100644 --- a/compose.yml +++ b/compose.yml @@ -55,7 +55,7 @@ x-environment: services: app: - image: ghcr.io/mailu/nginx:2024.06.66 + image: ghcr.io/mailu/nginx:2024.06.67 logging: driver: json-file networks: @@ -107,7 +107,7 @@ services: - "redis:/data" admin: - image: ghcr.io/mailu/admin:2024.06.66 + image: ghcr.io/mailu/admin:2024.06.67 environment: *default-env healthcheck: disable: true @@ -127,7 +127,7 @@ services: backupbot.backup.pre-hook: "python3 /usr/local/bin/backup_sqlite.py" imap: - image: ghcr.io/mailu/dovecot:2024.06.66 + image: ghcr.io/mailu/dovecot:2024.06.67 environment: *default-env secrets: - secret_key @@ -141,7 +141,7 @@ services: - default smtp: - image: ghcr.io/mailu/postfix:2024.06.66 + image: ghcr.io/mailu/postfix:2024.06.67 environment: *default-env secrets: - secret_key @@ -153,7 +153,7 @@ services: - app antispam: - image: ghcr.io/mailu/rspamd:2024.06.66 + image: ghcr.io/mailu/rspamd:2024.06.67 environment: *default-env secrets: - secret_key @@ -164,7 +164,7 @@ services: disable: true webmail: - image: ghcr.io/mailu/webmail:2024.06.66 + image: ghcr.io/mailu/webmail:2024.06.67 # entrypoint: "tail -f /dev/null" environment: *default-env networks: From 78421d9c5a2f640dfa27dae1f429e176373a31fc Mon Sep 17 00:00:00 2001 From: Ammar Hussein Date: Fri, 23 Oct 2026 18:45:57 -0700 Subject: [PATCH 12/12] release 4.0.0+2024.06.67 --- compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose.yml b/compose.yml index 4a8d499..79ed03b 100644 --- a/compose.yml +++ b/compose.yml @@ -96,7 +96,7 @@ services: - "traefik.http.routers.${STACK_NAME}.rule=Host(`${DOMAIN}`)" - "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}" - "traefik.http.routers.${STACK_NAME}.entrypoints=web-secure" - - "coop-cloud.${STACK_NAME}.version=3.2.1+2024.06.66" + - "coop-cloud.${STACK_NAME}.version=4.0.0+2024.06.67" - "backupbot.backup=${ENABLE_BACKUPS:-true}" - "backupbot.backup.volumes.traefik_letsencrypt=false" - "backupbot.backup.volumes.mailu.path=backup"