Files
2026-11-04 08:55:53 +01:00

142 lines
7.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PostfixAdmin-RS
Panel administracyjny serwera poczty Postfix/Dovecot napisany w Rust — zamiennik
PHP-owego [PostfixAdmin](https://github.com/postfixadmin/postfixadmin), działający
na **tej samej bazie danych** (MySQL/MariaDB, PostgreSQL, SQLite). Postfix, Dovecot,
`vacation.pl` i `fetchmail.pl` korzystają z tabel dokładnie tak jak przy PHP-owym
PostfixAdminie, więc panel można podmienić bez migracji danych.
Wersja: **0.1.0** · referencja logiki: PostfixAdmin 4.0.5 + gałąź `master` (schemat bazy 1857).
Jeden statyczny plik binarny z wbudowanym interfejsem (EN/PL, jasny/ciemny motyw,
działa na telefonie), bez PHP, bez serwera aplikacji, bez zależności w runtime.
## Funkcje
| Obszar | Zachowanie |
|---|---|
| Domeny | limity aliasów/skrzynek (`-1` = wyłączone, `0` = bez limitu), quota domeny i maks. quota skrzynki, transport, backup MX, wygasanie haseł, status DNS, domyślne aliasy przy tworzeniu, kasowanie domeny z wszystkimi danymi |
| Lista wirtualna | widok domeny jak `list-virtual.php`: domeny aliasowe, aliasy, skrzynki, wyszukiwanie, stronicowanie, filtr aktywne/nieaktywne, przełączanie aktywności jednym kliknięciem, „usuń nieaktywne”, statusy (niedostarczalny, zewnętrzny, autoresponder, wyłączona, hasło wygasło, POP/IMAP) |
| Skrzynki | reguły quota identyczne z `MailboxHandler::check_quota()`/`allowed_quota()` (podpowiedź „maks. N MB” w formularzu), generowanie hasła, potwierdzenie hasła, SMTP on/off, e-mail do odzyskiwania, wiadomość powitalna (w tle), maildir zgodny z `domain_path`/`domain_in_mailbox`, hooki po utworzeniu/edycji/usunięciu/zmianie hasła |
| Przekierowania | alias skrzynki („przekaż i zachowaj”), z uprawnieniami `alias_control` / `alias_control_admin` / `edit_alias` jak w PostfixAdminie |
| Aliasy | catch-all (`*` → `@domena`), przekierowanie całej domeny, konto lokalne (`root`), blokada aliasu wskazującego na siebie, `emailcheck_localaliasonly`, chronione aliasy domyślne (`special_alias_control`), zapamiętany domyślny cel |
| Domeny aliasowe | z ochroną przed łańcuchami i pętlami |
| Administratorzy | globalni i domenowi, przypisanie domen, aktywacja, reset hasła |
| Autoresponder | tabela `vacation` + alias transportu `user#domena@vacation_domain`, data i godzina od/do, `vacation_choice_of_reply`, czyszczenie `vacation_notification` |
| Panel użytkownika | podgląd skrzynki i quota, przekierowania, autoresponder, zmiana hasła, zmiana nazwy (`edit_mailbox_name`), 2FA, hasła aplikacji, filtry Sieve |
| Bezpieczeństwo | TOTP + wyjątki IP, hasła aplikacji, odzyskiwanie hasła e-mailem, limit prób logowania per IP/konto, CSRF, ciasteczka `HttpOnly`/`SameSite=Strict`/`Secure`, nagłówki CSP/HSTS, wylogowanie innych sesji po zmianie hasła, rewalidacja sesji (wyłączone konto lub odebrane uprawnienia działają natychmiast) |
| Inne | fetchmail (hasło base64 jak w PostfixAdmin), dziennik zmian z filtrem domen i stronicowaniem, wysyłanie poczty / wiadomość do wszystkich, kopia zapasowa bazy, DKIM (tabele PostfixAdmin/OpenDKIM oraz Rspamd), ManageSieve |
| Hasła | wszystkie formaty PostfixAdmin (ARGON2ID/I, BLF-CRYPT, SHA512-CRYPT, MD5-CRYPT, `php_crypt:*`, `md5crypt`, SSHA, Courier, Authlib, `dovecot:*` …) — format zapisany w rekordzie ma pierwszeństwo, więc stare i nowe hashe mogą współistnieć |
Szczegółowe porównanie z PHP: [PORT-PARITY.md](PORT-PARITY.md).
## Instalacja produkcyjna
### 1. Budowanie
```bash
cargo build --release --locked # wynik: target/release/postfixadmin-rs
# albo pakiet Debiana (w Dockerze):
./scripts/build-deb.sh # wynik: packages/postfixadmin-rs_*.deb
```
### 2. Konfiguracja
```bash
install -d -m 0750 -g postfixadmin /etc/postfixadmin-rs
install -m 0640 -g postfixadmin config.example.toml /etc/postfixadmin-rs/config.toml
$EDITOR /etc/postfixadmin-rs/config.toml
```
Najważniejsze ustawienia:
- `[database]` – dane bazy używanej przez Postfix/Dovecot. Hasło można podać w
`/etc/default/postfixadmin-rs` jako `POSTFIXADMIN_RS__DATABASE__PASSWORD=...`.
- `[password] scheme` – **musi** odpowiadać temu, co obsługuje Dovecot
(`default_pass_scheme`). Dla nowych instalacji: `ARGON2ID` lub `SHA512-CRYPT`.
- `[defaults] vacation_domain` – domena transportu autorespondera z `master.cf`.
- `[security]` – za nginx ustaw `trusted_proxies = ["127.0.0.1", "::1"]`,
`cookie_secure = true`, `hsts = true`.
### 3. Baza danych
```bash
export POSTFIXADMIN_RS_CONFIG=/etc/postfixadmin-rs/config.toml
postfixadmin-rs --init-schema --dry-run # co zostałoby zmienione
postfixadmin-rs --init-schema # tworzy brakujące tabele/kolumny/indeksy
postfixadmin-rs --create-superadmin admin@example.com # hasło ze stdin lub POSTFIXADMIN_RS_ADMIN_PASSWORD
postfixadmin-rs --check-config
```
`--init-schema` zastępuje `setup.php`/`upgrade.php`: na pustej bazie tworzy pełny
schemat PostfixAdmin (wersja 1857), na istniejącej tylko dodaje brakujące elementy —
nigdy niczego nie usuwa. Jest idempotentne.
### 4. Usługa i reverse proxy
```bash
install -m 0644 packaging/postfixadmin-rs.service /etc/systemd/system/
systemctl daemon-reload && systemctl enable --now postfixadmin-rs
```
Przykład nginx z TLS, HSTS i limitem logowań: [packaging/nginx.conf.example](packaging/nginx.conf.example).
Aplikacja nasłuchuje tylko na `127.0.0.1:8080`; publicznie wystawiony jest wyłącznie nginx.
### 5. Zadania okresowe (opcjonalnie)
```cron
# odświeżanie statusu DNS domen (odpowiednik scripts/domain-dns-check.php)
17 3 * * * postfixadmin POSTFIXADMIN_RS_CONFIG=/etc/postfixadmin-rs/config.toml /usr/bin/postfixadmin-rs --refresh-dns
```
## Migracja z PHP PostfixAdmin
1. Kopia zapasowa bazy oraz konfiguracji Postfix/Dovecot/PostfixAdmin.
2. Przenieś ustawienia z `config.local.php` do `config.toml`
(`$CONF['encrypt']` → `password.scheme`, `$CONF['vacation_domain']`, `default_aliases`, limity, `quota_multiplier` …).
Przykład odwzorowania: [config.from-user.toml](config.from-user.toml).
3. `postfixadmin-rs --init-schema --dry-run`, a potem bez `--dry-run`
(dodaje tylko brakujące kolumny nowszych wersji PostfixAdmin).
4. Uruchom panel równolegle (inny vhost), sprawdź logowanie, listy i jedną domenę testową.
5. Przełącz reverse proxy, a PHP/FPM wyłącz na końcu.
Konta administratorów i skrzynek oraz ich hasła działają bez zmian.
## Polecenia
```
postfixadmin-rs uruchamia serwer
postfixadmin-rs --check-config sprawdza konfigurację, połączenie i schemat
postfixadmin-rs --init-schema tworzy/aktualizuje schemat (--dry-run: tylko raport)
postfixadmin-rs --integrity-check osierocone rekordy (tylko odczyt)
postfixadmin-rs --create-superadmin EMAIL
postfixadmin-rs --refresh-dns odświeża status DNS wszystkich domen
postfixadmin-rs --version | --help
```
## Rozwój
```bash
bash dev.sh # izolowana baza SQLite z danymi testowymi
POSTFIXADMIN_RS_DEV_RESET=1 bash dev.sh
```
Konta testowe: `admin@example.test / admin123` (globalny), `domain-admin@example.test / domain123`
(admin `example.test`), `user@example.test / user123` (skrzynka). Tryb SSH do prawdziwej bazy
(domyślnie tylko do odczytu) opisuje `.env.example`.
Testy:
```bash
cargo fmt --check && cargo clippy --all-targets -- -D warnings && cargo test
python3 scripts/api-smoke.py http://127.0.0.1:8080 admin@example.test admin123 # test API na działającej instancji
python3 scripts/i18n/build.py # przebudowa katalogu PL + kontrola brakujących tłumaczeń
```
Interfejs jest w `src/web` (zwykły JS/CSS, wbudowywany przez `build.rs`); teksty źródłowe
są po angielsku, tłumaczenia polskie w `scripts/i18n/pl_messages.py`.
## Licencja
GPL-2.0-or-later, jak PostfixAdmin. Zob. [LICENSE](LICENSE) i [NOTICE.md](NOTICE.md).