Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71b98922af | ||
|
|
a6bf651b5c | ||
|
|
6a39984ed6 | ||
|
|
cf0b65feb5 | ||
|
|
0998a98df5 | ||
|
|
2fb279d96a
|
||
|
|
5d923d343f | ||
|
|
14ec244f97
|
||
|
|
abd102e3a8 |
@@ -69,6 +69,13 @@ DEFAULT_QUOTA="10 GB"
|
||||
# APPS="$APPS onlyoffice"
|
||||
# SECRET_ONLYOFFICE_JWT_VERSION=v1
|
||||
|
||||
# Euro-Office runs its own document server in this stack; EUROOFFICE_DOMAIN
|
||||
# needs its own DNS record pointing at this host.
|
||||
# COMPOSE_FILE="$COMPOSE_FILE:compose.eurooffice.yml"
|
||||
# EUROOFFICE_DOMAIN=eurooffice.example.com
|
||||
# APPS="$APPS eurooffice"
|
||||
# SECRET_EUROOFFICE_JWT_VERSION=v1
|
||||
|
||||
# COMPOSE_FILE="$COMPOSE_FILE:compose.bbb.yml"
|
||||
# BBB_URL=https://talk.example.org/bigbluebutton/ # trailing slash!
|
||||
# SECRET_BBB_SECRET_VERSION=v1
|
||||
|
||||
@@ -44,6 +44,40 @@ Then set the onlyoffice JWT secret from the onlyoffice installation:
|
||||
* `abra app secret insert <app-name> onlyoffice_jwt v1 <jwt_secret>`
|
||||
* `abra app cmd <app-name> app install_onlyoffice`
|
||||
|
||||
### Euro-Office Integration
|
||||
|
||||
Euro-Office is the AGPL fork of OnlyOffice that powers "Nextcloud Office" from
|
||||
Nextcloud 34 onwards. Like OnlyOffice it uses a client-side document-server
|
||||
architecture, so a separate document server is required — but this overlay runs
|
||||
that document server **inside the same stack**, so there is no external host to
|
||||
manage. The browser talks to it directly, so it needs its own public HTTPS
|
||||
domain (`EUROOFFICE_DOMAIN`) with a DNS record pointing at this host.
|
||||
|
||||
`abra app config <app-name>`
|
||||
|
||||
Enable the overlay and set the document server's domain:
|
||||
```
|
||||
COMPOSE_FILE="$COMPOSE_FILE:compose.eurooffice.yml"
|
||||
EUROOFFICE_DOMAIN=eurooffice.example.com
|
||||
APPS="$APPS eurooffice"
|
||||
SECRET_EUROOFFICE_JWT_VERSION=v1
|
||||
```
|
||||
|
||||
The overlay runs the document server with its own Postgres and RabbitMQ services
|
||||
(the image's bundled Postgres is unreliable). The document server schema is
|
||||
seeded into that Postgres automatically on first init (see
|
||||
`eurooffice-createdb.sql`). The Postgres is internal-only and uses trust auth, so
|
||||
the only secret to manage is the JWT; generate it, deploy, then wire up the
|
||||
Nextcloud app:
|
||||
|
||||
* `abra app secret generate -a <app-name>`
|
||||
* `abra app deploy <app-name>`
|
||||
* `abra app cmd <app-name> app install_eurooffice`
|
||||
|
||||
> Note: the document server needs ~4 GB RAM (8 GB for multi-user) and pulls the
|
||||
> `ghcr.io/euro-office/documentserver` image, which currently only publishes a
|
||||
> `latest` tag (no semver / Renovate pinning yet).
|
||||
|
||||
### BBB Integration
|
||||
|
||||
`abra app config <app-name>`
|
||||
@@ -130,9 +164,49 @@ To disable dashboard app (since it is so corporate):
|
||||
- Configure a `defaultapp` in your `config.php` or use [apporder](https://apps.nextcloud.com/apps/apporder)
|
||||
|
||||
## Upgrading Nextcloud
|
||||
Upgrading Nextcloud can be a hair raising experiance. They [don't support downgrading](https://docs.nextcloud.com/server/latest/admin_manual/maintenance/upgrade.html) even for minor versions.
|
||||
|
||||
Many of us have found that jumping major versions when upgrading is also a bad idea. We have however found that it's ok to skip minor version upgrades and go to the last minor version before a major version (e.g. 24.0.0 to 24.9.9 before going to 25.0.0). To extra cautious just upgrade one release at a time. Read the release notes and check your logs.
|
||||
Upgrading Nextcloud can be a hair raising experiance. They
|
||||
[don't support downgrading](https://docs.nextcloud.com/server/latest/admin_manual/maintenance/upgrade.html)
|
||||
even for minor versions.
|
||||
|
||||
### Upgrade path
|
||||
|
||||
Many of us have found that jumping major versions when upgrading is a bad idea.
|
||||
We have however found that it's ok to skip minor version upgrades and go to the
|
||||
last minor version before a major version (e.g. 24.0.0 to 24.9.9 before going to
|
||||
25.0.0). To be extra cautious just upgrade one release at a time. Read the
|
||||
release notes and check your logs.
|
||||
|
||||
### Checking upgrade readiness
|
||||
|
||||
Before upgrading to a new major, check whether the instance (and its enabled
|
||||
apps) look ready:
|
||||
|
||||
`abra app cmd <app-name> app check_major_upgrade`
|
||||
|
||||
This checks that you're not skipping a major version, that there's no pending DB
|
||||
upgrade left over from a previous update, and that every enabled non-shipped app
|
||||
declares support for the target major (falling back to an apps.nextcloud.com
|
||||
lookup to see if an app update would fix it). Shipped apps (`files`, `settings`,
|
||||
etc.) are skipped since they come bundled and are upgraded within the Docker
|
||||
image. Pass an explicit target major as the first argument (e.g.
|
||||
`check_major_upgrade 33`) to check readiness for a specific major, or it
|
||||
defaults to current major + 1. This is a sanity check, not a guarantee. Still
|
||||
read Nextcloud's release notes for any
|
||||
[critical changes between major versions](https://docs.nextcloud.com/server/stable/admin_manual/release_notes/index.html#critical-changes).
|
||||
|
||||
### Staying on an old major version
|
||||
|
||||
If you're not able to move to a new major version yet (e.g. because of app
|
||||
incompatibility), note that (starting from v32) before we release a recipe
|
||||
container a new major Nextcloud version, we also publish one more release of the
|
||||
previous major that points its image at the floating `nextcloud:XX-fpm` tag
|
||||
(e.g. `nextcloud:32-fpm`) instead of a pinned patch version. Deploying that
|
||||
release is less predictable: every redeploy pulls whatever the latest `32-fpm`
|
||||
build happens to be at that moment, rather than a fixed, reproducible version.
|
||||
But it means you keep getting security patches for the old major if you can't
|
||||
move to the next major. See [MAINTENANCE.md](./MAINTENANCE.md#release-cadence)
|
||||
for how this fits into our release process.
|
||||
|
||||
## Upgrading Nextcloud apps (plug-ins)
|
||||
|
||||
|
||||
@@ -6,11 +6,14 @@ export MY_CNF_VERSION=v6
|
||||
export ENTRYPOINT_VERSION=v3
|
||||
export ENTRYPOINT_WHITEBOARD_VERSION=v1
|
||||
export ENTRYPOINT_TALK_VERSION=v1
|
||||
export ENTRYPOINT_EUROOFFICE_VERSION=v3
|
||||
export EUROOFFICE_CREATEDB_VERSION=v1
|
||||
export CRONTAB_VERSION=v1
|
||||
export PG_BACKUP_VERSION=v2
|
||||
|
||||
run_occ() {
|
||||
su -p www-data -s /bin/sh -c "/var/www/html/occ $@"
|
||||
# NOTE: uses $* (not $@) so this still works when called with multiple args as seperate words.
|
||||
su -p www-data -s /bin/sh -c "/var/www/html/occ $*"
|
||||
}
|
||||
|
||||
install_apps() {
|
||||
@@ -83,6 +86,13 @@ install_onlyoffice() {
|
||||
set_app_config onlyoffice customizationForcesave true
|
||||
}
|
||||
|
||||
install_eurooffice() {
|
||||
install_apps eurooffice
|
||||
set_app_config eurooffice DocumentServerUrl "https://${EUROOFFICE_DOMAIN}"
|
||||
set_app_config eurooffice jwt_secret "$(cat /run/secrets/eurooffice_jwt)"
|
||||
set_app_config eurooffice customizationForcesave true
|
||||
}
|
||||
|
||||
install_collabora() {
|
||||
install_apps richdocuments
|
||||
set_app_config richdocuments wopi_url "$COLLABORA_URL"
|
||||
@@ -193,3 +203,159 @@ set_windowsfriendly_filenames() {
|
||||
upgrade_mariadb() {
|
||||
mariadb-upgrade -p`cat /run/secrets/db_root_password`
|
||||
}
|
||||
|
||||
# Checks whether this instance looks ready to update to the next Nextcloud
|
||||
# major version.
|
||||
#
|
||||
# Usage:
|
||||
# abra app cmd <app-name> app check_major_upgrade
|
||||
# abra app cmd <app-name> app check_major_upgrade 33 # check readiness for a specific target
|
||||
#
|
||||
# What it checks:
|
||||
# - current version is exactly one major behind the target
|
||||
# - no pending DB upgrade from a previous, unfinished update
|
||||
# - whether a newer release is available on the current major
|
||||
# (recommended before upgradeing to the next major)
|
||||
# - every enabled, non-shipped app's compatibility with the target major
|
||||
# - for apps that don't, whether apps.nextcloud.com already has a newer
|
||||
# release that does
|
||||
#
|
||||
# It does NOT check every precondition, always read the release notes
|
||||
# from Nextcloud too.
|
||||
check_major_upgrade() {
|
||||
target_major=$1
|
||||
|
||||
echo "=== Nextcloud major upgrade readiness check ==="
|
||||
|
||||
status_json=$(run_occ status --output=json 2>/dev/null)
|
||||
if [ -z "$status_json" ]; then
|
||||
echo "[FAIL] Could not read 'occ status' - is Nextcloud installed and reachable?"
|
||||
return 1
|
||||
fi
|
||||
|
||||
current_version=$(echo "$status_json" | php -r '$d=json_decode(stream_get_contents(STDIN),true); echo $d["versionstring"] ?? "";')
|
||||
current_major=${current_version%%.*}
|
||||
needs_db_upgrade=$(echo "$status_json" | php -r '$d=json_decode(stream_get_contents(STDIN),true); echo ($d["needsDbUpgrade"] ?? false) ? "true" : "false";')
|
||||
|
||||
if [ -z "$current_major" ]; then
|
||||
echo "[FAIL] Could not determine the current Nextcloud version from 'occ status'."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$target_major" ]; then
|
||||
target_major=$((current_major + 1))
|
||||
fi
|
||||
|
||||
echo "Current version: $current_version"
|
||||
echo "Target major version: $target_major"
|
||||
|
||||
ok=true
|
||||
|
||||
if [ "$target_major" -le "$current_major" ]; then
|
||||
echo "[FAIL] Target major ($target_major) is not newer than the current major ($current_major)."
|
||||
ok=false
|
||||
elif [ "$target_major" -gt "$((current_major + 1))" ]; then
|
||||
echo "[FAIL] Cannot skip major versions. Upgrade to $((current_major + 1)) first."
|
||||
ok=false
|
||||
fi
|
||||
|
||||
if [ "$needs_db_upgrade" = "true" ]; then
|
||||
echo "[FAIL] A pending database upgrade was detected. Run 'occ upgrade' for the current version first."
|
||||
ok=false
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "--- occ update:check ---"
|
||||
update_check_output=$(run_occ "update:check" 2>&1)
|
||||
if [ -z "$update_check_output" ]; then
|
||||
echo "[WARN] 'occ update:check' produced no output, could not verify."
|
||||
elif echo "$update_check_output" | grep -q "Everything up to date"; then
|
||||
echo "[OK] Everything up to date."
|
||||
else
|
||||
available_version=$(echo "$update_check_output" | grep -oE 'Nextcloud [0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?' | head -n1 | awk '{print $2}')
|
||||
available_major=${available_version%%.*}
|
||||
if [ -z "$available_major" ]; then
|
||||
echo "[WARN] Could not parse 'occ update:check' output to determine the available version."
|
||||
elif [ "$available_major" = "$current_major" ]; then
|
||||
echo "[WARN] $available_version is available on the current major. Recommended to update to that before upgrading to $target_major."
|
||||
else
|
||||
echo "[OK] Already on the latest release of major $current_major (next available update is $available_version)."
|
||||
fi
|
||||
fi
|
||||
echo
|
||||
|
||||
echo "--- Non-shipped app compatibility with Nextcloud $target_major ---"
|
||||
echo "(shipped apps are skipped, they come bundled with the docker image)"
|
||||
apps_json=$(run_occ "app:list --shipped=false --enabled --output=json" 2>/dev/null)
|
||||
|
||||
if [ -z "$apps_json" ]; then
|
||||
echo "[WARN] 'occ app:list' returned no output, could not check non-shipped app compatibility."
|
||||
enabled_apps=""
|
||||
else
|
||||
apps_json_valid=$(echo "$apps_json" | php -r '$d=json_decode(stream_get_contents(STDIN),true); echo (json_last_error() === JSON_ERROR_NONE && is_array($d)) ? "1" : "0";')
|
||||
if [ "$apps_json_valid" != "1" ]; then
|
||||
echo "[WARN] Could not parse 'occ app:list' output, could not check non-shipped app compatibility."
|
||||
enabled_apps=""
|
||||
else
|
||||
enabled_apps=$(echo "$apps_json" | php -r '$d=json_decode(stream_get_contents(STDIN),true); foreach(array_keys($d["enabled"] ?? []) as $a) echo $a."\n";')
|
||||
if [ -z "$enabled_apps" ]; then
|
||||
echo "No non-shipped apps are enabled - nothing to check here."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
compatible_apps=""
|
||||
compatible_apps_fetched=0
|
||||
|
||||
for app in $enabled_apps; do
|
||||
info_file=$(find /var/www/html/apps /var/www/html/custom_apps -maxdepth 3 -type f -ipath "*/$app/appinfo/info.xml" 2>/dev/null | head -n1)
|
||||
|
||||
if [ -z "$info_file" ]; then
|
||||
echo "[WARN] $app: could not locate appinfo/info.xml, skipping"
|
||||
continue
|
||||
fi
|
||||
|
||||
max_version=$(php -r '
|
||||
$x = @simplexml_load_file($argv[1]);
|
||||
$dep = $x ? ($x->dependencies->nextcloud ?? null) : null;
|
||||
echo $dep !== null ? (string)$dep["max-version"] : "";
|
||||
' "$info_file")
|
||||
|
||||
if [ -z "$max_version" ]; then
|
||||
echo "[WARN] $app: no max-version declared in info.xml, assume compatible but verify manually"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${max_version%%.*}" -ge "$target_major" ] 2>/dev/null; then
|
||||
echo "[OK] $app: installed version supports up to Nextcloud $max_version"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "[INFO] $app: installed version only supports up to Nextcloud $max_version"
|
||||
|
||||
if [ "$compatible_apps_fetched" != "1" ]; then
|
||||
compatible_apps_fetched=1
|
||||
compatible_apps=$(curl -fsSL --max-time 30 "https://apps.nextcloud.com/api/v1/platform/${target_major}.0.0/apps.json" 2>/dev/null \
|
||||
| php -r '$d=json_decode(stream_get_contents(STDIN),true); if(is_array($d)) foreach($d as $a) echo $a["id"]."\n";')
|
||||
fi
|
||||
|
||||
if [ -z "$compatible_apps" ]; then
|
||||
echo "[FAIL] $app: could not reach apps.nextcloud.com to check for a newer compatible release, verify manually"
|
||||
ok=false
|
||||
elif echo "$compatible_apps" | grep -qxF "$app"; then
|
||||
echo "[WARN] $app: apps.nextcloud.com has a release that supports $target_major. It may not update until Nextcloud is upgraded, occ upgrade will try to update it automatically"
|
||||
else
|
||||
echo "[FAIL] $app: no apps.nextcloud.com release supports $target_major yet, it will be disabled during the upgrade"
|
||||
ok=false
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
if [ "$ok" = true ]; then
|
||||
echo "=== READY: no blocking issues found for upgrade to major $target_major ==="
|
||||
return 0
|
||||
else
|
||||
echo "=== NOT READY: resolve the [FAIL] items above before running the upgrade ==="
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
app:
|
||||
secrets:
|
||||
- eurooffice_jwt
|
||||
environment:
|
||||
- EUROOFFICE_DOMAIN
|
||||
|
||||
eurooffice:
|
||||
image: ghcr.io/euro-office/documentserver:v9.3.2
|
||||
stdin_open: true
|
||||
depends_on:
|
||||
- eurooffice-db
|
||||
- eurooffice-rabbitmq
|
||||
networks:
|
||||
- proxy
|
||||
- internal
|
||||
environment:
|
||||
- JWT_ENABLED=true
|
||||
- JWT_SECRET_FILE=/run/secrets/eurooffice_jwt
|
||||
# Use external Postgres + RabbitMQ instead of the flaky bundled ones.
|
||||
# (The all-in-one image ships an uncleanly-shut-down Postgres data dir
|
||||
# whose crash recovery exceeds pg_ctl's start timeout -> restart loop.)
|
||||
- DB_TYPE=postgres
|
||||
- DB_HOST=eurooffice-db
|
||||
- DB_PORT=5432
|
||||
- DB_NAME=eurooffice
|
||||
- DB_USER=eurooffice
|
||||
- AMQP_URI=amqp://guest:guest@eurooffice-rabbitmq
|
||||
volumes:
|
||||
- eurooffice_data:/var/lib/euro-office
|
||||
- eurooffice_config:/etc/euro-office
|
||||
- eurooffice_logs:/var/log/euro-office
|
||||
- eurooffice_fonts:/usr/share/fonts/custom
|
||||
secrets:
|
||||
- eurooffice_jwt
|
||||
configs:
|
||||
- source: entrypoint_eurooffice
|
||||
target: /custom-entrypoint.sh
|
||||
mode: 555
|
||||
entrypoint: /custom-entrypoint.sh
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost/healthcheck"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 10
|
||||
start_period: 3m
|
||||
deploy:
|
||||
update_config:
|
||||
failure_action: rollback
|
||||
order: start-first
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.swarm.network=proxy"
|
||||
- "traefik.http.services.${STACK_NAME}_eurooffice.loadbalancer.server.port=80"
|
||||
- "traefik.http.routers.${STACK_NAME}_eurooffice.rule=Host(`${EUROOFFICE_DOMAIN}`)"
|
||||
- "traefik.http.routers.${STACK_NAME}_eurooffice.entrypoints=web-secure"
|
||||
- "traefik.http.routers.${STACK_NAME}_eurooffice.tls.certresolver=${LETS_ENCRYPT_ENV}"
|
||||
- "traefik.http.routers.${STACK_NAME}_eurooffice.middlewares=${STACK_NAME}_eurooffice-fwdproto"
|
||||
- "traefik.http.middlewares.${STACK_NAME}_eurooffice-fwdproto.headers.customRequestHeaders.X-Forwarded-Proto=https"
|
||||
|
||||
eurooffice-db:
|
||||
image: postgres:16-alpine
|
||||
networks:
|
||||
- internal
|
||||
environment:
|
||||
- POSTGRES_DB=eurooffice
|
||||
- POSTGRES_USER=eurooffice
|
||||
# Internal-only DB holding transient editing state; trust auth on the
|
||||
# private overlay network avoids managing a Swarm secret for it.
|
||||
- POSTGRES_HOST_AUTH_METHOD=trust
|
||||
volumes:
|
||||
- eurooffice_db:/var/lib/postgresql/data
|
||||
configs:
|
||||
# Seed the document server schema on first init. The all-in-one image only
|
||||
# creates its schema in the *bundled* Postgres; with an external DB the
|
||||
# docservice starts against an empty DB, errors on missing task_result /
|
||||
# doc_changes, never binds its port, and gets healthcheck-killed in a loop.
|
||||
- source: eurooffice_createdb
|
||||
target: /docker-entrypoint-initdb.d/createdb.sql
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready", "-U", "eurooffice"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 10
|
||||
start_period: 1m
|
||||
|
||||
eurooffice-rabbitmq:
|
||||
image: rabbitmq:4.3.2
|
||||
networks:
|
||||
- internal
|
||||
healthcheck:
|
||||
test: rabbitmq-diagnostics -q ping
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 10
|
||||
start_period: 1m
|
||||
|
||||
secrets:
|
||||
eurooffice_jwt:
|
||||
external: true
|
||||
name: ${STACK_NAME}_eurooffice_jwt_${SECRET_EUROOFFICE_JWT_VERSION}
|
||||
|
||||
volumes:
|
||||
eurooffice_data:
|
||||
eurooffice_config:
|
||||
eurooffice_logs:
|
||||
eurooffice_fonts:
|
||||
eurooffice_db:
|
||||
|
||||
configs:
|
||||
entrypoint_eurooffice:
|
||||
name: ${STACK_NAME}_entrypoint_eurooffice_${ENTRYPOINT_EUROOFFICE_VERSION}
|
||||
file: entrypoint.eurooffice.sh.tmpl
|
||||
template_driver: golang
|
||||
eurooffice_createdb:
|
||||
name: ${STACK_NAME}_eurooffice_createdb_${EUROOFFICE_CREATEDB_VERSION}
|
||||
file: eurooffice-createdb.sql
|
||||
@@ -29,7 +29,7 @@ services:
|
||||
mode: 0600
|
||||
|
||||
searchindexer:
|
||||
image: nextcloud:32-fpm
|
||||
image: nextcloud:34.0.2-fpm
|
||||
volumes:
|
||||
- nextcloud:/var/www/html/
|
||||
- nextapps:/var/www/html/custom_apps:cached
|
||||
|
||||
@@ -10,7 +10,7 @@ services:
|
||||
- NEXTCLOUD_UPDATE=1
|
||||
|
||||
db:
|
||||
image: "pgautoupgrade/pgautoupgrade:14-debian"
|
||||
image: "pgautoupgrade/pgautoupgrade:17-debian"
|
||||
#setting max_connections with -c breaks pgautoupgrade
|
||||
#command: -c "max_connections=${MAX_DB_CONNECTIONS:-100}"
|
||||
volumes:
|
||||
@@ -23,11 +23,11 @@ services:
|
||||
POSTGRES_DB: nextcloud
|
||||
secrets:
|
||||
- db_password
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready", "-U", "nextcloud"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
# The pgautoupgrade image already ships its own HEALTHCHECK.
|
||||
# This runs pg_isready but also takes into accounts if pg_upgrade is being run.
|
||||
# No need to override it here.
|
||||
# healthcheck:
|
||||
# test: ["CMD", "/usr/local/bin/pgautoupgrade-healthcheck.sh"]
|
||||
deploy:
|
||||
labels:
|
||||
backupbot.backup.pre-hook: "/pg_backup.sh backup"
|
||||
|
||||
+4
-4
@@ -48,7 +48,7 @@ services:
|
||||
start_period: 5m
|
||||
|
||||
app:
|
||||
image: nextcloud:32-fpm
|
||||
image: nextcloud:34.0.2-fpm
|
||||
depends_on:
|
||||
- db
|
||||
configs:
|
||||
@@ -95,7 +95,7 @@ services:
|
||||
failure_action: rollback
|
||||
order: start-first
|
||||
labels:
|
||||
- "coop-cloud.${STACK_NAME}.version=13.1.5+32.0.13-fpm"
|
||||
- "coop-cloud.${STACK_NAME}.version=15.1.0+34.0.2-fpm"
|
||||
- "coop-cloud.${STACK_NAME}.timeout=${TIMEOUT}"
|
||||
- "backupbot.backup=${ENABLE_BACKUPS:-true}"
|
||||
- "backupbot.backup.volumes.redis=false"
|
||||
@@ -109,7 +109,7 @@ services:
|
||||
start_period: 15m
|
||||
|
||||
cron:
|
||||
image: nextcloud:32-fpm
|
||||
image: nextcloud:34.0.2-fpm
|
||||
volumes:
|
||||
- nextcloud:/var/www/html/
|
||||
- nextapps:/var/www/html/custom_apps:cached
|
||||
@@ -154,7 +154,7 @@ volumes:
|
||||
|
||||
configs:
|
||||
nginx_conf:
|
||||
name: ${STACK_NAME}_nginx_${NGINX_CONF_VERSION}
|
||||
name: ${STACK_NAME}_nginx_conf_${NGINX_CONF_VERSION}
|
||||
file: nginx.conf.tmpl
|
||||
template_driver: golang
|
||||
fpm_tune:
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
# Read a Swarm secret file (<VAR>_FILE) into the plain env var the
|
||||
# Euro-Office document server expects, then hand off to its own entrypoint.
|
||||
file_env() {
|
||||
local var="$1"
|
||||
local fileVar="${var}_FILE"
|
||||
local def="${2:-}"
|
||||
|
||||
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
|
||||
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local val="$def"
|
||||
if [ "${!var:-}" ]; then
|
||||
val="${!var}"
|
||||
elif [ "${!fileVar:-}" ]; then
|
||||
val="$(< "${!fileVar}")"
|
||||
fi
|
||||
|
||||
export "$var"="$val"
|
||||
unset "$fileVar"
|
||||
}
|
||||
|
||||
file_env "JWT_SECRET"
|
||||
|
||||
exec /entrypoint.sh
|
||||
@@ -0,0 +1,73 @@
|
||||
--
|
||||
-- Create schema onlyoffice
|
||||
--
|
||||
|
||||
-- CREATE DATABASE onlyoffice ENCODING = 'UTF8' CONNECTION LIMIT = -1;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for doc_changes
|
||||
-- ----------------------------
|
||||
CREATE TABLE IF NOT EXISTS "doc_changes" (
|
||||
"tenant" varchar(255) COLLATE "default" NOT NULL,
|
||||
"id" varchar(255) COLLATE "default" NOT NULL,
|
||||
"change_id" int4 NOT NULL,
|
||||
"user_id" varchar(255) COLLATE "default" NOT NULL,
|
||||
"user_id_original" varchar(255) COLLATE "default" NOT NULL,
|
||||
"user_name" varchar(255) COLLATE "default" NOT NULL,
|
||||
"change_data" text COLLATE "default" NOT NULL,
|
||||
"change_date" timestamp without time zone NOT NULL,
|
||||
PRIMARY KEY ("tenant", "id", "change_id")
|
||||
)
|
||||
WITH (OIDS=FALSE);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for task_result
|
||||
-- ----------------------------
|
||||
CREATE TABLE IF NOT EXISTS "task_result" (
|
||||
"tenant" varchar(255) COLLATE "default" NOT NULL,
|
||||
"id" varchar(255) COLLATE "default" NOT NULL,
|
||||
"status" int2 NOT NULL,
|
||||
"status_info" int4 NOT NULL,
|
||||
"created_at" timestamp without time zone DEFAULT NOW(),
|
||||
"last_open_date" timestamp without time zone NOT NULL,
|
||||
"user_index" int4 NOT NULL DEFAULT 1,
|
||||
"change_id" int4 NOT NULL DEFAULT 0,
|
||||
"callback" text COLLATE "default" NOT NULL,
|
||||
"baseurl" text COLLATE "default" NOT NULL,
|
||||
"password" text COLLATE "default" NULL,
|
||||
"additional" text COLLATE "default" NULL,
|
||||
PRIMARY KEY ("tenant", "id")
|
||||
)
|
||||
WITH (OIDS=FALSE);
|
||||
|
||||
CREATE OR REPLACE FUNCTION merge_db(_tenant varchar(255), _id varchar(255), _status int2, _status_info int4, _last_open_date timestamp without time zone, _user_index int4, _change_id int4, _callback text, _baseurl text, OUT isupdate char(5), OUT userindex int4) AS
|
||||
$$
|
||||
DECLARE
|
||||
t_var "task_result"."user_index"%TYPE;
|
||||
BEGIN
|
||||
LOOP
|
||||
-- first try to update the key
|
||||
-- note that "a" must be unique
|
||||
IF ((_callback <> '') IS TRUE) AND ((_baseurl <> '') IS TRUE) THEN
|
||||
UPDATE "task_result" SET last_open_date=_last_open_date, user_index=user_index+1,callback=_callback,baseurl=_baseurl WHERE tenant = _tenant AND id = _id RETURNING user_index into userindex;
|
||||
ELSE
|
||||
UPDATE "task_result" SET last_open_date=_last_open_date, user_index=user_index+1 WHERE tenant = _tenant AND id = _id RETURNING user_index into userindex;
|
||||
END IF;
|
||||
IF found THEN
|
||||
isupdate := 'true';
|
||||
RETURN;
|
||||
END IF;
|
||||
-- not there, so try to insert the key
|
||||
-- if someone else inserts the same key concurrently,
|
||||
-- we could get a unique-key failure
|
||||
BEGIN
|
||||
INSERT INTO "task_result"(tenant, id, status, status_info, last_open_date, user_index, change_id, callback, baseurl) VALUES(_tenant, _id, _status, _status_info, _last_open_date, _user_index, _change_id, _callback, _baseurl) RETURNING user_index into userindex;
|
||||
isupdate := 'false';
|
||||
RETURN;
|
||||
EXCEPTION WHEN unique_violation THEN
|
||||
-- do nothing, and loop to try the UPDATE again
|
||||
END;
|
||||
END LOOP;
|
||||
END;
|
||||
$$
|
||||
LANGUAGE plpgsql;
|
||||
@@ -0,0 +1,57 @@
|
||||
Upgrades Nextcloud from 32.0.13 to 33 (major version upgrade).
|
||||
|
||||
IMPORTANT:
|
||||
- Nextcloud does NOT support downgrades. Take a backup before deploying.
|
||||
- Do not skip major versions: your instance must be on the latest 32.x before
|
||||
upgrading to 33. If you are on an older 32.x, deploy 32.0.13 first.
|
||||
- After deploying, check the logs and run any pending repair/upgrade steps:
|
||||
`abra app cmd <app> app run_occ '"app:update --all"'`
|
||||
- Review app (plug-in) compatibility with Nextcloud 33 before upgrading; some
|
||||
apps may need to be updated or temporarily disabled.
|
||||
- Added `check_major_upgrade` (`abra app cmd <app-name> app check_major_upgrade`)
|
||||
to check whether an instance is ready to upgrade to the next Nextcloud
|
||||
major version.
|
||||
|
||||
Upgrades postgresql with pgautoupgrade:17.
|
||||
Please only update coming from 14.0.0+33.0.7-fpm.
|
||||
|
||||
Last release of the nextcloud recipe for versio 33 with a rolling version.
|
||||
|
||||
Upgrades Nextcloud from 33 to 34.0.2 (major version upgrade).
|
||||
|
||||
IMPORTANT:
|
||||
- Check your current version is up-to-date with
|
||||
`abra app cmd <app-name> app check_major_upgrade` before updating to this version
|
||||
- Nextcloud does NOT support downgrades. Take a backup before deploying.
|
||||
- Do not skip major versions: your instance must be on the latest 33.x before
|
||||
upgrading to 34.0.2. If you are on an older 33.x, deploy 33.0.7 first.
|
||||
- After deploying, check the logs and run any pending repair/upgrade steps:
|
||||
`abra app cmd <app> app run_occ '"app:update --all"'`
|
||||
- Review app (plug-in) compatibility with Nextcloud 34.0.2 before upgrading; some
|
||||
apps may need to be updated or temporarily disabled.
|
||||
|
||||
Adds an optional Euro-Office integration (compose.eurooffice.yml).
|
||||
|
||||
Euro-Office is the AGPL fork of OnlyOffice that powers "Nextcloud Office" from
|
||||
Nextcloud 34 onwards. This overlay runs the Euro-Office document server inside
|
||||
the stack, so there is no external document server to manage.
|
||||
|
||||
This change is additive: existing installs are unaffected unless you opt in.
|
||||
|
||||
To enable it (`abra app config <app>`):
|
||||
- COMPOSE_FILE="$COMPOSE_FILE:compose.eurooffice.yml"
|
||||
- EUROOFFICE_DOMAIN=eurooffice.example.com
|
||||
- APPS="$APPS eurooffice"
|
||||
- SECRET_EUROOFFICE_JWT_VERSION=v1
|
||||
|
||||
Then:
|
||||
- Create a DNS record for EUROOFFICE_DOMAIN pointing at this host (the browser
|
||||
talks to the document server directly over HTTPS).
|
||||
- `abra app secret generate -a <app>`
|
||||
- `abra app deploy <app>`
|
||||
- `abra app cmd <app> app install_eurooffice`
|
||||
|
||||
Notes:
|
||||
- The document server needs ~4 GB RAM (8 GB recommended for multi-user).
|
||||
- The `ghcr.io/euro-office/documentserver` image currently only publishes a
|
||||
`latest` tag (no semver pinning yet), so it is not tracked by Renovate.
|
||||
Reference in New Issue
Block a user