Skip to content

Nextcloud

Self-hosted file sharing and collaboration — the file hub that other templates plug into.

  • Upstream project: https://nextcloud.com
  • Replaces: Google Drive, Dropbox, OneDrive for Business
  • Sign-in (SSO): Wired automatically — your operator’s converge runs an idempotent CLI hook that registers Keycloak inside the app on every run. Zero post-deploy step on the client side.
  1. Open the Environment tab and fill S3_BUCKET, S3_REGION, S3_HOST, S3_ACCESS_KEY, S3_SECRET_KEY with your bucket’s coordinates. (Everything else is pre-filled — NEXTCLOUD_HOSTNAME, admin/DB credentials, OIDC integration vars.)
  2. Click Deploy. Wait ~2 minutes for the first boot.
  3. Wire SSO: open actions.<your-domain> and click Wire Nextcloud OIDC. The button registers Keycloak as an OIDC provider inside Nextcloud (idempotent — safe to re-click after redeploys or secret rotations).
  4. Sign in at your Nextcloud domain with Log in with keycloak (uses your operator-managed identity), or fall back to NEXTCLOUD_ADMIN_USER / NEXTCLOUD_ADMIN_PASSWORD from the Environment tab.

Sign-in with Keycloak — wired by the OliveTin button

Section titled “Sign-in with Keycloak — wired by the OliveTin button”

After Nextcloud’s first deploy you click Wire Nextcloud OIDC at actions.<your-domain>. The button enables Nextcloud’s user_oidc app and registers a keycloak provider with the OIDC fields from the Environment tab. The Nextcloud login page then shows Log in with keycloak the next time you visit. Local admin login (NEXTCLOUD_ADMIN_USER / NEXTCLOUD_ADMIN_PASSWORD) keeps working alongside SSO as a break-glass.

Re-click the button any time the OIDC configuration drifts (after a secret rotation, a destructive redeploy, etc.). It is idempotent — re-running just refreshes the provider record.

Keycloak SSO governs user login to Nextcloud. It does not restrict anonymous public share links — /s/<token> URLs your team generates from inside Nextcloud are reachable by recipients who have no Keycloak account.

So the common workflow stays intact:

  1. A signed-in user (your team member) creates a share link in Nextcloud, optionally with a password and expiry date.
  2. Nextcloud emails the link to the recipient.
  3. The recipient clicks the link. Cloudflare Tunnel routes the request straight to Nextcloud; Nextcloud serves the public share page (or the password prompt, if you set one). No Keycloak redirect, no login required.

This works because Nextcloud is reached via Nextcloud’s own auth code, not a forward-auth proxy. The user_oidc plugin only handles the login flow for your team members; the public-share endpoints remain anonymous-by-design.

If you ever need to lock down public shares entirely, the right control is inside Nextcloud (Settings -> Sharing -> “Allow share via public link”), not at the network layer.

These values live in the Dokploy compose’s Environment tab. Random secrets are minted automatically when the template is first seeded — you don’t need to generate them yourself.

VariableDefault
NEXTCLOUD_HOSTNAMEnextcloud.yourdomain.com
NEXTCLOUD_ADMIN_USERadmin
NEXTCLOUD_ADMIN_PASSWORDauto-generated random value
DB_PASSWORDauto-generated random value
NEXTCLOUD_LOGLEVEL1
NEXTCLOUD_VERSIONS_RETENTIONauto, 7
NEXTCLOUD_TRASH_RETENTIONauto, 30
S3_BUCKET(set before deploy)
S3_REGIONbhs
S3_HOSTs3.bhs.io.cloud.ovh.net
S3_ACCESS_KEY(set before deploy)
S3_SECRET_KEY(set before deploy)
OIDC_CLIENT_IDnextcloud
OIDC_CLIENT_SECRET<your-nextcloud_oidc_client_secret>
OIDC_DISCOVERY_URLhttps://auth.yourdomain.com/realms/catena/.well-known/openid-configuration
OIDC_ISSUER_URLhttps://auth.yourdomain.com/realms/catena
OIDC_REDIRECT_URLhttps://nextcloud.yourdomain.com/apps/user_oidc/code
SIGNALING_HOSTNAMEsignaling.yourdomain.com
SIGNALING_SECRET<your-nextcloud_talk_signaling_secret>
TALK_INTERNAL_SECRET<your-nextcloud_talk_internal_secret>
TURN_HOSTNAMEturn.yourdomain.com
TURN_STATIC_AUTH_SECRET<your-turn_static_auth_secret>
  • Service and port: app:80
  • Hostname: nextcloud.yourdomain.com

The hostname is attached automatically when the template is seeded; change it in the Domains tab before clicking Deploy if you want something else.

For reference — this is what the template deploys. Do not paste this anywhere. The compose is seeded into Dokploy automatically; the client-facing adjustments you make happen in the Environment and Domains tabs (described above), never in the compose itself.

# Nextcloud -- S3 primary storage + Keycloak SSO.
#
# All values come from the Environment tab: hostname, S3 credentials,
# admin password, DB password, OIDC coordinates (auto-injected). The
# compose itself is not edited per deploy.
services:
app:
image: nextcloud:33.0.3-apache
restart: unless-stopped
# Two-stage delivery for the loglevel override:
#
# 1. The entrypoint wrapper writes a `before-starting` hook
# script into the container's writable layer (image-baked
# path /docker-entrypoint-hooks.d/before-starting/).
# 2. Wrapper exec's the upstream /entrypoint.sh apache2-foreground.
# 3. Upstream entrypoint populates /var/www/html/config (rsync
# from /usr/src/nextcloud/config/), runs occ install / occ
# upgrade, then iterates `before-starting/*.sh` -- our hook
# runs as www-data and drops zz-loglevel.config.php into the
# already-populated config dir.
#
# Why this dance instead of writing the .config.php from the
# wrapper directly? Upstream's populate.sh skips rsync'ing
# /var/www/html/config when the dir is already non-empty
# (`directory_empty` check). A wrapper that writes our file in
# /var/www/html/config BEFORE the upstream runs makes the dir
# non-empty -> populate skips -> autoconfig.php / redis.config.php
# / s3.config.php / etc. never land in the volume -> Apache 503s.
# Running our writer in a before-starting HOOK sidesteps that
# check entirely.
#
# Why not the compose-v2 `configs:` block? Through Dokploy the
# inline content-delivery pipeline produced a script that exited 2
# with no script-side stderr on every start. Materializing the
# hook ourselves via the wrapper bypasses that delivery path.
#
# `$$X` -> `$X` after compose interpolation. The outer
# `<<'HOOK'` is single-quoted so the wrapper writes the hook
# body verbatim; the INNER `<<PHP` is unquoted so the runtime
# shell expands `${NEXTCLOUD_LOGLEVEL}` and friends from the
# container env. `\$$CONFIG` escapes the `$` through both
# rounds so the literal `$CONFIG` (PHP variable) lands in the
# rendered .config.php.
entrypoint:
- /bin/sh
- -ec
- |
cat > /docker-entrypoint-hooks.d/before-starting/zz-catena.sh <<'HOOK'
#!/bin/sh
# Catena-managed config overlay. Re-rendered on every container
# start from the env vars below. Lets the operator change
# client-policy knobs (log level, version retention) via the
# Dokploy Environment tab without dropping into occ.
set -e
: "$${NEXTCLOUD_LOGLEVEL:=1}"
: "$${NEXTCLOUD_VERSIONS_RETENTION:=auto, 7}"
: "$${NEXTCLOUD_TRASH_RETENTION:=auto, 30}"
cat > /var/www/html/config/zz-catena.config.php <<PHP
<?php
\$$CONFIG = [
'loglevel' => $${NEXTCLOUD_LOGLEVEL},
'versions_retention_obligation' => '$${NEXTCLOUD_VERSIONS_RETENTION}',
'trashbin_retention_obligation' => '$${NEXTCLOUD_TRASH_RETENTION}',
];
PHP
# Server-side encryption (SSE), master-key mode. Encrypts file
# content before it is handed to the S3 object-store driver, so
# the storage provider only ever sees ciphertext at rest.
# Master-key mode encrypts against a single, operator-recoverable
# key (held in DB + the config `secret`) -- NOT per-user keys,
# which would put files out of reach of an operator restore.
# Idempotent: this hook runs on every container start, but
# master-key SELECTION runs only once -- on the fresh install,
# before any file is encrypted. Switching modes on already-
# encrypted data is destructive, hence the useMasterKey guard.
# `encryption:enable-master-key` prompts y/n and treats
# --no-interaction as "no", so the confirmation is fed on stdin.
php occ app:enable encryption
# Force-set the useMasterKey config flag BEFORE any path that
# might trigger the encryption module's per-user-mode bootstrap.
# Bench diag (run 2026-05-31T14-26-35-ad7b nc_s3_hot_recovery)
# caught the failure mode this guards against: master_<id>.{pub,
# priv}Key files DID land in S3, but useMasterKey stayed empty
# in oc_appconfig. Nextcloud's KeyManager::getPrivateKey then
# took the per-user branch (because isMasterKeyEnabled returns
# false when useMasterKey != "1") and threw PrivateKeyMissing-
# Exception for admin -- the admin user has no per-user key
# because we never went through that setup. occ encryption:
# enable-master-key shorts out with "Master key already enabled"
# if the FILES exist, regardless of the config flag, so the
# original guard could not self-heal. Setting the flag
# idempotently FIRST flips KeyManager into master-key mode for
# every subsequent occ + Apache request.
php occ config:app:set encryption useMasterKey --value=1
if [ "$$(php occ config:app:get encryption useMasterKey 2>/dev/null)" != "1" ]; then
printf 'y\n' | php occ encryption:enable-master-key
fi
php occ encryption:enable
# --- Catena SSE diagnostic sentinel ------------------------------
# Captures the bytes that would diverge under the three Bad-
# Signature theories (secret rotation, hook ordering, S3 master-
# key corruption) so the bench / operator can compare runtime
# state against install-time state when WebDAV PUT 503s with
# "Encryption not ready". Hashes never leak the secret in
# clear -- only sha256 prints land in the sentinel. The file
# sits under the local nc-data volume (NOT objectstore), so it
# survives container recreate but goes away with the VM disk.
# Rewritten on every container boot so a redeploy that bumps
# the secret would show in a fresh capture.
diag_inst="$$(php occ config:system:get instanceid 2>/dev/null | tr -d '\n')"
diag_secret="$$(php occ config:system:get secret 2>/dev/null)"
diag_salt="$$(php occ config:system:get passwordsalt 2>/dev/null)"
diag_secret_h="$$(printf '%s' "$$diag_secret" | sha256sum | cut -d' ' -f1)"
diag_salt_h="$$(printf '%s' "$$diag_salt" | sha256sum | cut -d' ' -f1)"
diag_useMK="$$(php occ config:app:get encryption useMasterKey 2>/dev/null | tr -d '\n')"
diag_encE="$$(php occ config:app:get core encryption_enabled 2>/dev/null | tr -d '\n')"
diag_defM="$$(php occ config:app:get core default_encryption_module 2>/dev/null | tr -d '\n')"
diag_apps_enc="$$(php occ app:list 2>/dev/null | awk '/^- encryption:/{getline; print $$2}' | tr -d '\n')"
diag_now="$$(date -u +%Y-%m-%dT%H:%M:%SZ)"
mkdir -p /var/www/html/data
cat > /var/www/html/data/.catena-encryption-setup.json <<EOF_DIAG
{
"captured_at": "$$diag_now",
"container_hostname": "$$(hostname)",
"instanceid": "$$diag_inst",
"secret_sha256": "$$diag_secret_h",
"passwordsalt_sha256": "$$diag_salt_h",
"encryption_app_useMasterKey": "$$diag_useMK",
"core_encryption_enabled": "$$diag_encE",
"core_default_encryption_module": "$$diag_defM",
"encryption_app_version": "$$diag_apps_enc"
}
EOF_DIAG
HOOK
chmod 0755 /docker-entrypoint-hooks.d/before-starting/zz-catena.sh
# Remove the predecessor hook if present from a prior catalog
# version so the same key is not declared twice.
rm -f /docker-entrypoint-hooks.d/before-starting/zz-loglevel.sh \
/var/www/html/config/zz-loglevel.config.php
exec /entrypoint.sh "$$@"
- --
command: ["apache2-foreground"]
environment:
NEXTCLOUD_TRUSTED_DOMAINS: ${NEXTCLOUD_HOSTNAME}
NEXTCLOUD_ADMIN_USER: ${NEXTCLOUD_ADMIN_USER}
NEXTCLOUD_ADMIN_PASSWORD: ${NEXTCLOUD_ADMIN_PASSWORD}
# Catena-managed config knobs. The zz-catena.sh hook reads these
# at container start and writes /var/www/html/config/zz-catena
# .config.php. Change the value here (Dokploy Environment tab)
# + redeploy and the next container start picks it up.
#
# NEXTCLOUD_LOGLEVEL: 0=debug, 1=info, 2=warn, 3=error, 4=fatal.
# Default 1 matches the historical zz-loglevel.sh hook.
#
# NEXTCLOUD_VERSIONS_RETENTION: passed verbatim into the
# `versions_retention_obligation` config key. Format is
# `<min>, <max>` in days OR the keyword `auto, <N>` where N is
# the operator-controlled max-age cap. Default `auto, 7` keeps
# ~50-70% less storage than the upstream default 30-day cap;
# raise to `auto, 14` or `auto, 30` for clients who routinely
# need deeper undo. Direct lever on hot+cold bucket storage cost.
#
# NEXTCLOUD_TRASH_RETENTION: passed verbatim into the
# `trashbin_retention_obligation` config key (same `auto, <N>`
# format). This is the mass-DELETE safety net: a runaway desktop
# sync that deletes a tree propagates the deletes server-side, but
# the files land in each user's trash and are recoverable for at
# least N days regardless of free space. Default `auto, 30` keeps a
# 30-day undo window for accidental/ransomware bulk deletion; lower
# it only for storage-constrained clients who accept a shorter
# recovery window. (versions_retention covers OVERWRITES; this
# covers DELETES -- both are needed.)
NEXTCLOUD_LOGLEVEL: ${NEXTCLOUD_LOGLEVEL:-1}
NEXTCLOUD_VERSIONS_RETENTION: ${NEXTCLOUD_VERSIONS_RETENTION:-auto, 7}
NEXTCLOUD_TRASH_RETENTION: ${NEXTCLOUD_TRASH_RETENTION:-auto, 30}
# TLS is terminated upstream (Cloudflare Tunnel -> Traefik). Force
# Nextcloud to render https:// links + trust the reverse-proxy
# Forwarded headers so user_oidc's HTTPS precondition check passes.
OVERWRITEPROTOCOL: https
OVERWRITEHOST: ${NEXTCLOUD_HOSTNAME}
OVERWRITECLIURL: https://${NEXTCLOUD_HOSTNAME}
TRUSTED_PROXIES: 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
POSTGRES_HOST: db
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD: ${DB_PASSWORD}
REDIS_HOST: redis
OBJECTSTORE_S3_BUCKET: ${S3_BUCKET}
OBJECTSTORE_S3_REGION: ${S3_REGION}
OBJECTSTORE_S3_HOST: ${S3_HOST}
OBJECTSTORE_S3_PORT: "443"
OBJECTSTORE_S3_SSL: "true"
OBJECTSTORE_S3_USEPATH_STYLE: "true"
OBJECTSTORE_S3_AUTOCREATE: "false"
OBJECTSTORE_S3_KEY: ${S3_ACCESS_KEY}
OBJECTSTORE_S3_SECRET: ${S3_SECRET_KEY}
NEXTCLOUD_OIDC_CLIENT_ID: ${OIDC_CLIENT_ID}
NEXTCLOUD_OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET}
NEXTCLOUD_OIDC_ISSUER_URL: ${OIDC_ISSUER_URL}
NEXTCLOUD_OIDC_REDIRECT_URL: ${OIDC_REDIRECT_URL}
# Talk + HPB wire script (catena-wire-nextcloud-talk-hpb) reads
# these from the running container at click time and feeds them
# to `occ talk:turn:add` / `occ talk:signaling:add`. They live
# alongside the OIDC + S3 envs because both go through the same
# docker-exec pattern. Empty / unset is fine -- the wire script
# auto-detects HPB-disabled state via an http probe to
# signaling:8081 first and exits 0 when the service is absent.
SIGNALING_HOSTNAME: ${SIGNALING_HOSTNAME}
SIGNALING_SECRET: ${SIGNALING_SECRET}
TURN_HOSTNAME: ${TURN_HOSTNAME}
TURN_STATIC_AUTH_SECRET: ${TURN_STATIC_AUTH_SECRET}
volumes:
- nc-config:/var/www/html/config
- nc-apps:/var/www/html/custom_apps
# Even with S3 primary storage, /var/www/html/data still holds
# appdata_<instance>/ residue, nextcloud.log, audit.log, .ocdata,
# sqlite caches for some apps -- everything Nextcloud writes
# outside the objectstore driver. Explicit named volume so the
# path lives at /mnt/data/docker/volumes/<compose>_nc-data/_data
# (predictable, visible in `docker volume ls`, captured by
# restic's docker/volumes/ rule). Without this mount, Docker
# creates an anonymous volume from the image's VOLUME directive
# -- still backed up but with an opaque sha256 name.
- nc-data:/var/www/html/data
labels:
- "vps.auth.mode=public"
- "vps.auth.oidc=true"
- "vps.auth.groups=staff"
- "vps.auth.oidc.redirect_uris=https://${NEXTCLOUD_HOSTNAME}/apps/user_oidc/code"
- "vps.auth.oidc.scopes=openid email profile groups"
- "vps.auto-update=patch"
networks:
dokploy-network:
aliases:
- nextcloud
default: {}
# Gate Nextcloud's first-boot install on postgres being ready to
# accept connections. See the db service's healthcheck block for
# the failure mode this prevents.
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:16.13-alpine
restart: unless-stopped
environment:
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- db-data:/var/lib/postgresql/data
# pg_isready health-check is what `app` and `cron` gate on via
# `depends_on: { db: { condition: service_healthy } }`. Without
# it, both services launch in parallel with the db, the upstream
# nextcloud entrypoint runs `occ maintenance:install` before
# postgres has accepted its first connection, install retries 10x
# 10s, exhausts the budget, container exits rc=1, Dokploy auto-
# restarts. The restart finds /var/www/html/version.php already
# written by the previous populate.sh run -> entrypoint takes the
# UPGRADE path -> no-op -> NC stuck reporting installed=false.
healthcheck:
test: ["CMD-SHELL", "pg_isready -U nextcloud -d nextcloud"]
interval: 5s
timeout: 3s
retries: 30
start_period: 10s
labels:
- "vps.auto-update=patch"
networks:
- default
redis:
image: redis:7.4.9-alpine
restart: unless-stopped
labels:
- "vps.auto-update=patch"
networks:
- default
cron:
image: nextcloud:33.0.3-apache
restart: unless-stopped
entrypoint: /cron.sh
environment:
POSTGRES_HOST: db
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD: ${DB_PASSWORD}
REDIS_HOST: redis
OBJECTSTORE_S3_BUCKET: ${S3_BUCKET}
OBJECTSTORE_S3_REGION: ${S3_REGION}
OBJECTSTORE_S3_HOST: ${S3_HOST}
OBJECTSTORE_S3_PORT: "443"
OBJECTSTORE_S3_SSL: "true"
OBJECTSTORE_S3_USEPATH_STYLE: "true"
OBJECTSTORE_S3_KEY: ${S3_ACCESS_KEY}
OBJECTSTORE_S3_SECRET: ${S3_SECRET_KEY}
volumes:
- nc-config:/var/www/html/config
- nc-apps:/var/www/html/custom_apps
# Cron and app must share the data volume -- background jobs
# (file scanning, preview generation, etc.) write to the same
# /var/www/html/data tree the app reads from.
- nc-data:/var/www/html/data
# No command override on cron: it runs /cron.sh as its entrypoint,
# which is a thin runner for occ background-jobs. The app service
# writes zz-loglevel.config.php into the shared nc-config volume
# on its own startup; cron picks it up via the shared mount.
networks:
- default
# Cron is also a Nextcloud entrypoint variant (runs /cron.sh) so
# it gates on postgres readiness for the same reason `app` does.
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
# === HPB BEGIN -- Talk High-Performance Backend ==========================
# Comment out this single service to disable Talk + HPB. The wire
# script catena-wire-nextcloud-talk-hpb already handles the
# "HPB not deployed -> exit 0" path so leaving it commented does
# NOT break the rest of the stack -- Talk falls back to built-in
# P2P mode (works up to ~5 participants).
#
# Image is the Nextcloud team's official All-In-One HPB bundle:
# signaling + janus + nats + an internal eturnal TURN, all under
# supervisord in one container. We deliberately KEEP the standalone
# roles/coturn (TURN/STUN at turn.<base>:5349) because Rocket.Chat's
# bundled Jitsi (rocketchat-oidc template) shares the same coturn
# via JVB_TURN_*. Two design choices follow from that:
#
# 1. Janus inside aio-talk is configured (via TURN_DOMAIN +
# TALK_PORT) to use the EXTERNAL standalone coturn for its
# own ICE relay. Janus's start.sh inside aio-talk mints
# ephemeral HMAC-SHA1 creds against TURN_SECRET (which we
# set to vault_turn_static_auth_secret -- the same secret
# coturn validates with). Clients dialing Talk get TURN
# coordinates pointing at the same coturn (set by the
# catena-wire-nextcloud-talk-hpb wire script via
# `occ talk:turn:add`), so all media converges through one
# shared TURN provider.
# 2. aio-talk's bundled eturnal still binds TALK_PORT inside
# the container netns -- start.sh has no skip flag for it.
# That binding is harmless: TALK_PORT=5349 lives only in the
# container's private netns; nothing on the host competes.
# The bundled eturnal stays unused.
#
# Public exposure: only the signaling HTTP endpoint (port 8081
# inside the container) needs to be reachable. The catalog entry
# in dokploy_template_catalog.yml declares signaling.<base>:8081
# as an extra_domain so Dokploy auto-injects the Traefik labels.
#
# Tag: pinned to a dated upstream build. Bump by listing
# `ghcr.io/nextcloud-releases/aio-talk` tags and picking the
# most recent stable one (the upstream tag scheme is YYYYMMDD_HHMMSS).
talk-hpb:
image: ghcr.io/nextcloud-releases/aio-talk:20260409_094910
init: true
restart: unless-stopped
environment:
# NEXTCLOUD_HOSTNAME owns the public Nextcloud URL; aio-talk
# advertises this to clients as the parent app's identity.
NC_DOMAIN: ${NEXTCLOUD_HOSTNAME}
# Public hostname clients dial for the WSS signaling channel.
# Routed through Cloudflare Tunnel + Traefik to this container's
# port 8081.
TALK_HOST: ${SIGNALING_HOSTNAME}
# TURN coordinates Janus uses for its own ICE candidates.
# Pointed at the standalone coturn (turn.<base>:5349) so
# restrictive-network clients reach Janus through the same
# shared TURN that the wire script advertises to Talk.
TURN_DOMAIN: ${TURN_HOSTNAME}
TALK_PORT: "5349"
TURN_SECRET: ${TURN_STATIC_AUTH_SECRET}
# Bearer secret between the signaling service and the Talk
# backend. The wire script (catena-wire-nextcloud-talk-hpb)
# passes this same value to `occ talk:signaling:add`, so the
# two endpoints share the secret.
SIGNALING_SECRET: ${SIGNALING_SECRET}
# Internal secret between the signaling frontend and its
# backend store. Never leaves the container; aio-talk requires
# it set at startup but clients never see it.
INTERNAL_SECRET: ${TALK_INTERNAL_SECRET}
# Quiet the supervisord log to warn-level by default; bump to
# debug temporarily when troubleshooting.
AIO_LOG_LEVEL: warn
# Optional bitrate ceilings. aio-talk defaults to 1 Mbps audio +
# 2 Mbps screen-share when these are unset; ship the defaults
# explicitly so a UI edit lands in the catalog managed-keys.
TALK_MAX_STREAM_BITRATE: "1048576"
TALK_MAX_SCREEN_BITRATE: "2097152"
labels:
# Public via Traefik (the Domain entry in catalog adds the
# router/service labels at deploy time). Bearer-secret authed
# by aio-talk's signaling layer; no oauth2-proxy gate.
- "vps.auth.mode=public"
- "vps.auto-update=patch"
networks:
dokploy-network:
aliases:
# Wire script's auto-detect probe hits http://signaling:8081
# from inside the Nextcloud container; keep this alias so
# the existing probe URL continues to resolve.
- signaling
default: {}
# === HPB END =============================================================
volumes:
nc-config:
nc-apps:
nc-data:
db-data:
networks:
dokploy-network:
external: true

<- Back to all pre-configured apps