Files
ActivePush/README.md
T
2026-11-05 12:52:32 +01:00

81 lines
5.0 KiB
Markdown

# ActivePush
**Exchange ActiveSync server written in Rust** - a from-scratch successor of **Z-Push** (PHP) for classic mail
stacks: **IMAP + SMTP** (e.g. Dovecot + Postfix), **CalDAV** and **CardDAV** (Radicale, SOGo, Baikal,
Nextcloud, DAViCal). One binary, no PHP-FPM, with a built-in administration panel in the RustProxy style:
configuration, devices, remote wipe, policies, statistics, charts and live traffic.
![Overview](docs/images/overview.png)
```
phone / Outlook --HTTPS--> nginx | RustProxy --> ActivePush :8081 --> IMAP / SMTP / CalDAV / CardDAV
administrator --(SSH tunnel / VPN)-------------> panel :9091
```
## Features
| Area | What you get |
|---|---|
| Protocol | ActiveSync 2.5, 12.0, 12.1, 14.0, 14.1; WBXML; plain and base64 query strings; multipart responses |
| Commands | Sync (incl. empty/partial and hanging Sync), FolderSync, FolderCreate/Update/Delete, GetHierarchy, Ping (push), Provision, SendMail, SmartReply, SmartForward, GetAttachment, ItemOperations (Fetch, byte ranges, EmptyFolderContents), GetItemEstimate, MoveItems, MeetingResponse, Search (GAL and mailbox), ResolveRecipients, Settings, ValidateCert |
| Mail | IMAP folder hierarchy and SPECIAL-USE, read/flag/answered/forwarded, move, trash, attachments, text/HTML/MIME bodies with truncation and preview, S/MIME passthrough, iMIP invitations as MeetingRequest |
| Calendar | VEVENT <-> EAS: time zones (TIME_ZONE_INFORMATION <-> IANA), all-day events, RRULE recurrences, exceptions (EXDATE + RECURRENCE-ID), attendees and responses, reminders, busy status, categories |
| Tasks | VTODO <-> EAS Tasks (due, start, completion, priority, reminder, recurrence) |
| Contacts | vCard 2.1/3.0/4.0 <-> EAS Contacts with **lossless merging** of fields ActiveSync cannot represent |
| Push | Ping with cheap change detection (IMAP STATUS / DAV CTag every N seconds, full diff only when a signature changes) |
| Security | per-account and per-IP lockout, fail2ban friendly log line, user/domain/network/device-type allow and block lists, device approval, provisioning policies, remote wipe, sender enforcement, DAV SSRF guard, XML without DTD, size limits, panel with argon2id + CSRF + strict CSP |
| Panel | overview charts, live traffic (SSE), devices grouped per phone, mailboxes, backends with connection tests, ActiveSync settings, policies, security, logs and audit; English/Polish, dark/light theme |
| Operations | hardened systemd unit, portable `.deb`, Prometheus `/metrics`, `/healthz`, Z-Push config importer, CLI equivalent of `z-push-admin`, automatic database retention and compaction |
## Quick start (development)
```bash
cp .env.example .env
./dev.sh backends # terminal 1: Dovecot + Radicale + SMTP sink (needs dovecot-imapd, radicale, aiosmtpd)
./dev.sh seed # settings matching those backends
./dev.sh # terminal 2: server (ActiveSync :8081, panel :9091)
./dev.sh admin setup-token # one-time token for creating the administrator at http://127.0.0.1:9091
./dev.sh probe jan@test.local # ActiveSync smoke test (password: Test-Password-123)
./dev.sh e2e # end-to-end test of every command
```
`./dev.sh help` lists all commands (`lint`, `test`, `release`, `deb`, `dist`, `import-zpush` ...).
## Production (Debian/Ubuntu)
```bash
./dev.sh deb # -> dist/active-push_<version>-1_amd64.deb (glibc >= 2.30)
sudo apt install ./dist/active-push_*.deb # creates the user and directories, enables the service
sudo -u active-push active-push admin setup-token
ssh -L 9091:127.0.0.1:9091 server # panel: http://127.0.0.1:9091
```
Then replace the Z-Push fastcgi locations in nginx with `proxy_pass` - ready snippet:
[`deploy/nginx-active-push.conf`](deploy/nginx-active-push.conf). Details: [docs/INSTALL.md](docs/INSTALL.md).
## Migrating from Z-Push
```bash
python3 /usr/share/active-push/zpush-import.py /usr/share/z-push > zpush.json # or /etc/z-push
sudo -u active-push active-push config apply zpush.json
```
Devices resynchronise on their own (unknown sync key -> status 9/3, unknown policy key -> provisioning,
unknown Z-Push collection ids are removed from the device). See [docs/MIGRATION.md](docs/MIGRATION.md).
## Documentation
- [docs/PANEL.md](docs/PANEL.md) - tour of the administration panel with screenshots
- [docs/INSTALL.md](docs/INSTALL.md) - installation, nginx/RustProxy, systemd, upgrades, backups
- [docs/CONFIGURATION.md](docs/CONFIGURATION.md) - every setting and its Z-Push equivalent
- [docs/LOGS.md](docs/LOGS.md) - logging, retention, rotation and database maintenance
- [docs/SECURITY.md](docs/SECURITY.md) - security model and recommendations
- [docs/MIGRATION.md](docs/MIGRATION.md) - moving from Z-Push
- [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) - common problems
- [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) - architecture, tests, development environment
- [docs/API.md](docs/API.md) - panel API and Prometheus metrics
## License
AGPL-3.0-only (like Z-Push, from which the WBXML code pages and protocol behaviour originate).