b6c98e2a65
ci / changes (push) Successful in 3s
ci / test_platform_api (push) Has been skipped
ci / build_portal (push) Has been skipped
ci / build_booking (push) Has been skipped
ci / build_operator (push) Has been skipped
ci / build_platform_api (push) Has been skipped
ci / tc_portal (push) Has been skipped
ci / tc_operator (push) Has been skipped
ci / tc_booking (push) Has been skipped
ci / tc_website (push) Has been skipped
ci / tc_platform_api (push) Has been skipped
ci / build_zpush (push) Successful in 11s
ci / deploy (push) Successful in 25s
The shipped policies.ini has maxattsize='' and PHP 8's string/int
comparison semantics make SyncProvisioning's '>-1' check fail, so
every Provision command 500'd ('Invalid policies!') and the device
got 449 retry-after-provisioning on FolderSync/Sync/SendMail forever
— account added but no folders, no sent mail, no calendar. dezky
doesn't manage device policies (no remote-wipe promise), so turn
PROVISIONING off rather than patching the policy file.
102 lines
5.5 KiB
Docker
102 lines
5.5 KiB
Docker
# dezky EAS gateway — Z-Push (AGPLv3) wrapping Stalwart in Exchange
|
|
# ActiveSync so "Exchange" accounts on iOS/Android native Mail/Calendar get
|
|
# two-way mail + calendar + contacts sync. Z-Push talks to Stalwart with the
|
|
# client's own Basic credentials (mailbox password or app password) over
|
|
# IMAP/CalDAV/CardDAV — this container stores no secrets, only sync state.
|
|
#
|
|
# Z-Push 2.6.x speaks EAS up to 14.1. That covers native mobile clients but
|
|
# NOT the Outlook mobile app (Microsoft enforces EAS >= 16.1 there since
|
|
# March 2026) and not new Outlook for Windows (no EAS at all). See
|
|
# LICENSE-NOTES.md for the AGPL source-offer obligation.
|
|
|
|
ARG ZPUSH_VERSION=2.6.4
|
|
|
|
FROM alpine/git AS source
|
|
ARG ZPUSH_VERSION
|
|
RUN git clone --depth 1 --branch ${ZPUSH_VERSION} \
|
|
https://github.com/EGroupware/z-push.git /z-push
|
|
# AWL (Andrew's Web Libraries) — Z-Push's CalDAV client (include/z_caldav.php)
|
|
# requires XMLDocument.php from it, and its include_path already expects the
|
|
# Debian location /usr/share/awl/inc. Debian dropped the php-awl package
|
|
# after bullseye, so vendor it from upstream at a pinned tag.
|
|
RUN git clone --depth 1 --branch r0.65 \
|
|
https://gitlab.com/davical-project/awl.git /awl
|
|
|
|
# php:8.2 — the imap extension lives in PHP core through 8.3 and moved to
|
|
# PECL in 8.4; stay on a version where docker-php-ext-install still works.
|
|
# Pinned to the bookworm base: Debian trixie dropped the (upstream-dead)
|
|
# uw-imap libc-client packages the imap extension compiles against.
|
|
FROM php:8.2-apache-bookworm
|
|
ARG ZPUSH_VERSION
|
|
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends \
|
|
libc-client2007e-dev libkrb5-dev libicu-dev \
|
|
&& docker-php-ext-configure imap --with-kerberos --with-imap-ssl \
|
|
&& docker-php-ext-install -j"$(nproc)" imap intl sysvshm sysvsem \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
COPY --from=source /z-push/src/ /usr/share/z-push/
|
|
COPY --from=source /awl/inc/ /usr/share/awl/inc/
|
|
|
|
# Main config: keep the 50+ upstream defaults, patch only what we change.
|
|
# The greps make the build fail loudly if an upstream config rename ever
|
|
# makes a sed miss instead of shipping a silently unconfigured gateway.
|
|
# (USE_FULLEMAIL_FOR_LOGIN is already true in the EGroupware fork.)
|
|
#
|
|
# PROVISIONING off: dezky doesn't manage device policies (no remote wipe
|
|
# promise), and Z-Push's policy checks are PHP 8-broken anyway — the shipped
|
|
# policies.ini has maxattsize='' and PHP 8 string/int comparison makes the
|
|
# ">-1" SyncProvisioning check fail, 500ing every Provision command and
|
|
# blocking ALL folder/calendar sync behind "retry after provisioning".
|
|
RUN sed -i \
|
|
-e "s|define('TIMEZONE', '');|define('TIMEZONE', 'Europe/Copenhagen');|" \
|
|
-e "s|define('BACKEND_PROVIDER', '');|define('BACKEND_PROVIDER', 'BackendCombined');|" \
|
|
-e "s|define('PROVISIONING', true);|define('PROVISIONING', false);|" \
|
|
/usr/share/z-push/config.php \
|
|
&& grep -q "define('BACKEND_PROVIDER', 'BackendCombined')" /usr/share/z-push/config.php \
|
|
&& grep -q "define('USE_FULLEMAIL_FOR_LOGIN', true)" /usr/share/z-push/config.php \
|
|
&& grep -q "define('PROVISIONING', false)" /usr/share/z-push/config.php
|
|
|
|
# PHP 8 fix (upstream Z-Push 2.6.4 bug): sem_get()/shm_attach() return
|
|
# objects instead of resources since PHP 8.0 and this debug log line
|
|
# sprintf's them — a fatal TypeError on every request. The rest of the
|
|
# provider only compares the handles against false, which is PHP 8-safe.
|
|
RUN sed -i \
|
|
's|sprintf("%s(): Initialized mutexid %s and memid %s.", $class, $this->mutexid, $this->memid)|sprintf("%s(): Initialized shared memory mutex and segment.", $class)|' \
|
|
/usr/share/z-push/backend/ipcsharedmemory/ipcsharedmemoryprovider.php \
|
|
&& grep -q "Initialized shared memory mutex and segment" \
|
|
/usr/share/z-push/backend/ipcsharedmemory/ipcsharedmemoryprovider.php
|
|
|
|
# Backend + autodiscover configs are small files — full replacements.
|
|
COPY config/caldav.config.php /usr/share/z-push/backend/caldav/config.php
|
|
COPY config/carddav.config.php /usr/share/z-push/backend/carddav/config.php
|
|
COPY config/imap.config.php /usr/share/z-push/backend/imap/config.php
|
|
COPY config/combined.config.php /usr/share/z-push/backend/combined/config.php
|
|
COPY config/autodiscover.config.php /usr/share/z-push/autodiscover/config.php
|
|
|
|
# Schema-sniffing autodiscover dispatcher (mobilesync → Z-Push, outlook
|
|
# schema → proxied to Stalwart). Lives inside autodiscover/ because
|
|
# autodiscover.php resolves its requires relative to that directory.
|
|
COPY autodiscover-router.php /usr/share/z-push/autodiscover/router.php
|
|
|
|
# Build-time smoke test: force-load every class the combined backend pulls
|
|
# in at runtime. Catches missing vendored dependencies (the AWL include
|
|
# above only crashes on the first *authenticated* request otherwise).
|
|
RUN php -d include_path='.:/usr/local/lib/php:/usr/share/z-push/:/usr/share/awl/inc' -r ' \
|
|
require "/usr/share/z-push/vendor/autoload.php"; \
|
|
foreach (array("CalDAVClient", "carddav_backend", "BackendIMAP", "BackendCalDAV", "BackendCardDAV", "BackendCombined") as $c) { \
|
|
if (!class_exists($c)) { fwrite(STDERR, "FAILED loading $c\n"); exit(1); } \
|
|
} \
|
|
echo "class-load smoke OK\n";'
|
|
|
|
COPY apache/zpush.conf /etc/apache2/conf-available/zpush.conf
|
|
COPY php/zpush.ini /usr/local/etc/php/conf.d/zpush.ini
|
|
RUN a2enconf zpush \
|
|
&& mkdir -p /var/lib/z-push/state /var/log/z-push \
|
|
&& chown -R www-data:www-data /var/lib/z-push /var/log/z-push \
|
|
&& echo "${ZPUSH_VERSION}" > /usr/share/z-push/DEZKY_PINNED_VERSION
|
|
|
|
VOLUME /var/lib/z-push
|
|
EXPOSE 80
|