This repository packages WeKan as a Nextcloud AppAPI External App (ExApp). One container runs the authenticated AppAPI gateway, WeKan and the bundled wekan/FerretDB v1 SQLite database. HaRP carries HTTP and WebSocket/DDP traffic. No MongoDB container, Docker socket mount, or external database is required.
The implementation has local HTTP/WebSocket and authentication tests. A real Nextcloud/HaRP installation and a Docker image build still need validation before an App Store production release.
- Nextcloud 32–35, AppAPI enabled, and a registered HaRP deploy daemon.
- The Nextcloud reverse proxy must forward
/exapps/to HaRP, including WebSocket upgrades. Follow the HaRP installation instructions. - A published WeKan Docker version containing
server/nextcloud.jsand/build/nextcloud-exapp-capability.json. Existing images without that marker are deliberately rejected. Publish a new WeKan release with this integration before building its ExApp; changing metadata alone cannot retrofit old images. - Persistent storage and enough RAM for WeKan and FerretDB together. Start validation with at least 2 GiB, then size for the actual workload.
After publishing the supporting WeKan release, from this repository:
# Replace VERSION with that published WeKan version (without v).
docker buildx build --platform linux/amd64 --load \
--build-arg WEKAN_VERSION=VERSION \
-t ghcr.io/wekan/wekan-exapp:vVERSION .Set appinfo/info.xml's app version to the normalized three-part version and
its image tag to vVERSION. The standalone nextcloud.yml workflow in
wekan/wekan performs these edits, tests this repository, and publishes amd64
and arm64 images. It never runs as part of release-all.yml.
For a pre-store test deployment, publish the image yourself, make the matching
appinfo/info.xml accessible to Nextcloud, then run as Nextcloud's web user:
php occ app_api:app:register wekan YOUR_HARP_DAEMON \
--info-xml /absolute/path/to/appinfo/info.xmlIf the deploy daemon uses an internal NEXTCLOUD_URL for callbacks, configure
WEKAN_PUBLIC_URL as the browser-visible URL, for example
https://cloud.example/exapps/wekan/. Otherwise it is derived from NEXTCLOUD_URL.
Include Nextcloud's subdirectory when it has one. Configure the usual Node
NODE_EXTRA_CA_CERTS environment/mount if the callback server uses a private CA;
never disable TLS verification.
Configure NEXTCLOUD_ADMIN_USERS in the app's deployment environment, for
example ["admin"], using exact Nextcloud user IDs. The default [] gives
nobody WeKan site-administrator rights. Ordinary users can still use boards.
The first visiting user never gains site-administrator privileges automatically.
When changing the list, restart/redeploy the container and reconnect clients.
Enabling the app registers WeKan in Nextcloud's navigation. That menu opens
/exapps/wekan/ (under the Nextcloud subdirectory, if any). It uses Nextcloud's
existing authenticated session; no second WeKan password or OIDC setup is needed.
AppAPI routes require a logged-in Nextcloud user, including public WeKan boards.
Anonymous sharing outside Nextcloud is not enabled by this package.
The gateway validates EX-APP-ID, EX-APP-VERSION presence and the shared
AUTHORIZATION-APP-API secret using a constant-time comparison. It strips
incoming identity headers and signs the verified Nextcloud user ID with a fresh,
private key shared only with the child WeKan process. The key is never returned
to the browser. WeKan binds login and resume to these DDP connection headers.
Accounts are identified by the Nextcloud URL and exact user ID, never linked
by matching an existing username or email. Keep NEXTCLOUD_URL stable: changing
it creates a separate identity namespace. Disabled WeKan users stay disabled.
Attachment/avatar requests resolve the same verified identity.
GET /heartbeat is public. POST /init and PUT /enabled require the system
AppAPI identity (empty user ID plus the correct secret). Initialization reports
progress to AppAPI after WeKan is ready. Disabling closes WebSocket connections
and refuses app requests. Enabled state persists across container restarts.
AppAPI provides APP_PERSISTENT_STORAGE. Keep the volume and its backups private:
it also holds the FRP tunnel configuration and any injected TLS credentials. The launcher uses:
| Container path | Contents |
|---|---|
$APP_PERSISTENT_STORAGE/wekan/files/db |
FerretDB SQLite |
$APP_PERSISTENT_STORAGE/wekan/files/attachments |
Attachments |
$APP_PERSISTENT_STORAGE/wekan/files/avatars |
Avatars |
$APP_PERSISTENT_STORAGE/nextcloud-enabled.json |
AppAPI enabled state |
WRITABLE_PATH is $APP_PERSISTENT_STORAGE/wekan. Back up the entire persistent
volume with the container stopped, and test restoration. Do not remove the
AppAPI volume when upgrading the image. This is a new-install package; it does
not automatically import an existing UCS, MongoDB or standalone WeKan instance.
The launcher initializes directory ownership as root and then drops to the
WeKan UID/GID for all services. WeKan and FerretDB listen only on loopback ports.
HaRP FRP mode uses /tmp/exapp.sock; direct-connect mode uses APP_HOST and
APP_PORT. FRP, WeKan or FerretDB exiting stops the container. SIGTERM shuts down
all children with a bounded grace period. The database is the FerretDB binary
already shipped in the selected WeKan image, so its version stays with that image.
mkdir -p .tools/tmp
TMPDIR="$PWD/.tools/tmp" node --test tests/*.test.mjsBefore production, test two Nextcloud users, configured admin privileges, denied
anonymous access, WebSocket reconnect, private boards, attachment upload/download,
avatars, disable/re-enable, container restart, upgrade with the same volume and
backup restoration. The WeKan repository also provides
tests/playwright/specs/nextcloud.e2e.js for a real signed-in browser session.
App Store signing keys, app registration, supported-version validation and production publication remain maintainer tasks. See the release instructions. AI, Deck synchronization and file/calendar integrations are separate future work.
The wrapper is MIT licensed. The image includes WeKan and its dependencies under their respective licenses; the bundled FRP client is Apache-2.0 licensed.
Run node --test tests/*.test.mjs with TMPDIR pointing to the parent WeKan
checkout's .tools/tmp. Gateway tests cover authenticated HTTP/WebSockets,
readiness, rejected identities and persistent disable state, including an OCS
failure during deregistration. Runtime tests launch real child processes and
parse the FRP configuration independently; metadata guards check USER routes and
the image's capability/privilege boundaries.
The full native Nextcloud 32–35 browser matrix lives in the parent WeKan checkout:
setup, coverage and remaining container checks.
It uses real AppAPI/HaRP, WeKan and FerretDB under .tools, with UI uploads,
private-board isolation, lifecycle operations, source-built upgrades and full
volume restore. Published WeKan v12.32 needs the source transport bridge when
used as the baseline: SockJS's default header allowlist drops the custom signed
identity headers. New ExApp images must wrap a WeKan build containing that fix.
The gateway strips ordinary Authorization credentials as well as AppAPI secrets before forwarding requests. Disabling is saved before menu deregistration, so an unavailable Nextcloud endpoint cannot restore the previous enabled state after a process restart.