81 lines
5.0 KiB
Markdown
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.
|
|
|
|

|
|
|
|
```
|
|
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).
|