# PostfixAdmin-RS Rustowy panel administracyjny dla Postfix/Dovecot, rozwijany jako zamiennik runtime PHP PostfixAdmin i zgodny z jego istniejaca baza danych. Aktualna linia developerska: **0.0.2**. Projekt jest przypiety do **Rust 1.99.1**, edition 2024. Frontend jest osadzony w pojedynczym binarnym pliku; bundlowanie assetow, sprite SVG i workflow developerski sa wzorowane na przekazanym RustBox. Stary wyglad PostfixAdmin nie jest kopiowany. ## Development bez produkcyjnej bazy Domyslny `dev.sh` nie potrzebuje MySQL/PostgreSQL. Uzywa izolowanego SQLite w `.dev/postfixadmin-rs.sqlite` i przy pierwszym starcie tworzy mock schematu PostfixAdmin z danymi testowymi: ```bash bash dev.sh ``` Konta testowe: ```text admin@example.test / admin123 # global-admin domain-admin@example.test / domain123 # admin example.test user@example.test / user123 # mailbox user ``` Reset mock DB oraz developerskiego mocka Rspamd DKIM: ```bash POSTFIXADMIN_RS_DEV_RESET=1 bash dev.sh ``` `database.dev_mock=true` jest dozwolone tylko z `environment="development"` i backendem SQLite. Produkcyjna baza nie jest potrzebna do pracy nad UI/API. Jesli chcesz testowac bezposrednio na produkcyjnej bazie przez SSH, `dev.sh` moze zestawic lokalny tunnel. Domyslnie taka sesja jest **read-only**. Najprosciej skopiowac gotowy przyklad dla `host.linuxiarz.pl`: ```bash cp .env.example .env $EDITOR .env bash dev.sh ``` W `.env` uzupelnij co najmniej `POSTFIXADMIN_RS_DEV_DB_PASSWORD`. Przyklad jest dopasowany do testowego hosta: `root@host.linuxiarz.pl:11922`, MySQL/MariaDB, baza `postfix`, uzytkownik DB `postfix` i lokalny port tunelu `13306`. Domyslny forward dla MySQL to `127.0.0.1:13306 -> 127.0.0.1:3306`, a dla PostgreSQL `127.0.0.1:15432 -> 127.0.0.1:5432`. Mozesz zmienic host/port po stronie serwera przez `POSTFIXADMIN_RS_DEV_DB_HOST` i `POSTFIXADMIN_RS_DEV_DB_PORT`. Weryfikacja host key SSH pozostaje wlaczona. Tunel uzywa `BatchMode=yes`, wiec przygotuj klucz/ssh-agent; opcjonalnie ustaw `POSTFIXADMIN_RS_SSH_IDENTITY` lub `POSTFIXADMIN_RS_SSH_KNOWN_HOSTS`. Zapisy na produkcyjnej bazie wymagaja dodatkowego, jawnego opt-in: ```bash POSTFIXADMIN_RS_DEV_DB_MODE=ssh POSTFIXADMIN_RS_DEV_DB_WRITES=1 bash dev.sh ``` W tym trybie aplikacja moze modyfikowac realne skrzynki/aliasy. Do zwyklych testow UI i odczytu schematu nie ustawiaj `POSTFIXADMIN_RS_DEV_DB_WRITES=1`. ## Co jest gotowe - logowanie admin/mailbox, sesje HttpOnly/SameSite, CSRF i rate limit, - global-admin, domain-admin i mailbox user, - domeny, skrzynki, aliasy, alias-domains i masowe usuwanie nieaktywnych forwardow, - limity domen, quota/domain quota, transport, backup MX i self-alias, - fetchmail, vacation/autoreply zgodny z tabela `vacation`, log, sendmail/broadcast i backup DB, - panel mailbox-user: wlasna quota/usage z DB, dane skrzynki, self-alias, bez odczytu IMAP, - opcjonalny ManageSieve dla mailbox-user: lista/edycja/walidacja/aktywacja skryptow filtrow, prosty wizualny builder reguly + edytor raw, bez IMAP, - admin preferences (m.in. domyslny cel aliasu), - DKIM keys/signing, TOTP, TOTP exceptions, application passwords, - Rspamd DKIM: generowanie kluczy, selector/path maps, configtest, podpinanie istniejacych kluczy i opcjonalny reload, - `smtp_active`, password expiration i DNS status, gdy schema je udostepnia, - bezpieczny natywny `maildir_template` zamiast PHP `maildir_name_hook`, - automatyczne subfoldery przez `doveadm mailbox create`, jesli lista jest skonfigurowana, - MySQL/MariaDB, PostgreSQL i SQLite przez SQLx Any, - hooki wykonywane jako program + argumenty, bez `sh -c`, - UI EN/PL z English jako domyslnym jezykiem; wybor z interfejsu jest zapamietywany w przegladarce, API pozostaje po angielsku. Pelna macierz: [COMPATIBILITY.md](COMPATIBILITY.md). Audyt 1:1 wobec dostarczonego PHP 4.0.1: [PORT-PARITY.md](PORT-PARITY.md). ## Mailbox user, Vacation i ManageSieve Panel zwyklego uzytkownika nie pokazuje administracyjnej listy modulow ani cudzych skrzynek. Overview pobiera tylko rekord zalogowanej skrzynki i jej self-alias. Quota/usage pochodzi z tabel PostfixAdmin/Dovecot (`mailbox`, opcjonalnie `quota`/`quota2`); aplikacja nie loguje sie do IMAP, zeby zbudowac ten widok. Vacation pozostaje zgodny z PostfixAdmin: korzysta z tabeli `vacation` i ustawien `features.vacation` / `features.vacation_control`. Samo wlaczenie UI nie konfiguruje transportu/autorespondera po stronie Postfix/Dovecot, dlatego na istniejacym serwerze wlacz te flagi tylko wtedy, gdy mechanizm Vacation jest faktycznie skonfigurowany. ManageSieve jest dodatkiem niezaleznym od mechanizmu Vacation PA. Konfiguracja: ```toml [sieve] enabled = true host = "127.0.0.1" port = 4190 tls_mode = "starttls" # starttls | implicit | none allow_insecure_auth = false timeout_secs = 10 read_only = false ``` Haslo mailbox-user jest przechowywane tylko w pamieci jego sesji, i tylko gdy Sieve jest wlaczone; nie trafia do JSON API ani logow. Po zmianie hasla credential sesji jest aktualizowany. Dla developerskiego testu przez SSH mozna wlaczyc drugi forward tym samym `dev.sh`: ```bash POSTFIXADMIN_RS_DEV_SIEVE_ENABLED=true bash dev.sh ``` Domyslnie zewnetrzny ManageSieve przez dev tunnel jest read-only. Zapis wymaga osobnego `POSTFIXADMIN_RS_DEV_SIEVE_WRITES=1`; jest to niezalezne od `POSTFIXADMIN_RS_DEV_DB_WRITES`. ## Hasla zgodne z PostfixAdmin Weryfikacja najpierw rozpoznaje format juz zapisany w rekordzie. Dzieki temu jedna baza moze zawierac stare i nowe hashe podczas migracji, bez masowego przepisywania kont. Obslugiwane sa m.in.: - `ARGON2ID`, `ARGON2ID.B64`, `ARGON2I`, `ARGON2I.B64`, - `BLF-CRYPT`, `BLF-CRYPT.B64`, `CRYPT`, - `SHA512-CRYPT`, `SHA512-CRYPT.B64`, legacy `SHA512.B64`, `SHA512`, - `SHA256-CRYPT`, `SHA256-CRYPT.B64`, `SHA256`, - `SHA1-CRYPT`, `SHA1`, `SHA1.B64`, `SHA`, `SSHA`, - `MD5-CRYPT`, legacy `md5crypt`, `PLAIN-MD5`, `MD5`, `MD5RAW`, - `AUTHLIB` (`md5raw`, `md5`, `SHA`, `crypt`), - `courier:md5`, `courier:md5raw`, `courier:sha1`, `courier:ssha`, `courier:sha256`, - `php_crypt:DES|MD5|BLOWFISH|SHA256|SHA512` z kompatybilnym difficulty/prefix, - `dovecot:METHOD` jako kontrolowany fallback do `doveadm pw`, bez shella i bez hasla w argv, - `PLAIN`, `CLEAR`, `cleartext` tylko dla zgodnosci/testow. Testy zawieraja referencyjne wektory z dostarczonego `tests/PacryptTest.php`. Slabe formaty pozostaja tylko dla kompatybilnosci; nowych kont nie nalezy na nie migrowac bez potrzeby. Dla przekazanego configu produkcyjnego pozostaje `php_crypt:MD5`, dopoki konfiguracja Dovecot/Postfix SASL nie zostanie zmieniona razem z panelem. ## Konfiguracja przekazanego serwera `config.from-user.toml` odwzorowuje przekazany config PostfixAdmin, ale nie zawiera hasla bazy. Sekret podaj przez ENV: ```bash export POSTFIXADMIN_RS_CONFIG="$PWD/config.from-user.toml" export POSTFIXADMIN_RS__DATABASE__PASSWORD='...' ``` ## Jezyki interfejsu Frontend ma katalogi `src/web/i18n/en.json` i `src/web/i18n/pl.json`. `default_language = "en"` ustawia English jako pierwszy jezyk, a przelacznik w loginie i gornej belce zapisuje wybor w `localStorage`. Lokalizacja dotyczy tylko UI; endpointy, JSON i kody bledow API pozostaja angielskie. ## Build / release gate ```bash ./scripts/build-release.sh ``` Gate wykonuje walidacje statyczna, `cargo fmt --check`, testy, Clippy z `-D warnings` i release build z `Cargo.lock`. ## Migracja z PHP 1. Zrob backup bazy i konfiguracji Postfix/Dovecot/PostfixAdmin. 2. Najpierw testuj na kopii DB lub na mocku developerskim. 3. Na realnej DB uruchom `--check-config`, sprawdz logowanie i CRUD na domenie testowej. 4. Nie zmieniaj `password.scheme`, dopoki Dovecot/Postfix SASL nie obsluguje tego samego formatu. 5. Reverse proxy przelacz dopiero po testach regresyjnych; PHP/FPM usun na koncu. ## Status 0.0.2 To nadal wersja developerska, nie deklaruje jeszcze 100% parity PostfixAdmin 4.x. Pozostale luki to przede wszystkim webowy setup/upgrade schematu, XML-RPC, SMS provider, update checker oraz generic IMAP/Courier do tworzenia folderow. Dynamiczne hooki PHP (`*_struct_hook`, `language_hook`) nie beda uruchamiane jako PHP — wymagaja natywnego mechanizmu rozszerzen. W tym srodowisku nie ma `cargo`/`rustc`; proba pobrania toolchaina 1.99.1 jest dodatkowo blokowana przez brak DNS/network, wiec realny `cargo check/test/clippy` nie mogl zostac wykonany tutaj. Statyczny gate jest uruchamiany przed spakowaniem, ale developerski build trzeba ostatecznie zweryfikowac przez `bash dev.sh` na maszynie z Rust 1.99.1. Checklista testowa: [TESTING.md](TESTING.md). ## Rspamd DKIM Integracja Rspamd nie rozbudowuje recznie `domain { ... }`. Uzywa map `selector_map` i `path_map`, generuje klucze przez `rspamadm`, wykonuje `rspamadm configtest` przed zaakceptowaniem zmian i moze wykonac jawnie skonfigurowany argv-only reload. Instrukcja: [docs/RSPAMD_DKIM.md](docs/RSPAMD_DKIM.md). ### DKIM backends The UI exposes PostfixAdmin database DKIM and Rspamd DKIM as separate backends. They can be enabled independently: ```toml [features] dkim = true [dkim] default_backend = "postfixadmin" # postfixadmin | rspamd [rspamd_dkim] enabled = true ``` When both are enabled, `dkim.default_backend` selects the tab opened first. Disabling one backend removes that tab from the UI. Mailbox users can optionally see DKIM as a **read-only DNS view** for their own domain (`[dkim].user_read_only = true`). The view merges only public records from the PostfixAdmin DKIM tables and Rspamd. `default_backend` is only a UI preference for administrators; there is no shared/global DKIM key in this project. Every key/selector remains associated with a concrete domain. When development uses the SSH database mode, `dev.sh` also forwards ManageSieve (`14190 -> 4190`) and, by default, builds a public-only Rspamd DKIM cache over SSH. The helper reads mapping/config metadata and derives the public key on the mail host; it never downloads private-key bytes. Disable this with `POSTFIXADMIN_RS_DEV_RSPAMD_PUBLIC_SYNC=false`. ### Domain-focused UI `Domains` is the main entry point for domain administration. Clicking a domain opens a workspace with mailbox and alias usage, quota progress, mailboxes, aliases and alias-domain relationships. The standalone Mailboxes and Aliases pages show one domain at a time instead of rendering all domains at once. ## Local Debian package For Debian-like systems, build a development `.deb` inside Docker: ```bash ./scripts/build-deb.sh ``` The builder uses Debian 12 as the compatibility baseline, installs the Rust toolchain pinned by `rust-toolchain.toml`, runs static validation, `cargo fmt --check`, tests and clippy, then writes the package and SHA256 file to `./packages/`. The resulting package installs the binary, a systemd service, `/etc/postfixadmin-rs/config.toml` and `/etc/default/postfixadmin-rs`. During installation it creates the unprivileged system user/group `postfixadmin`, runs the service as that identity, keeps `/etc/postfixadmin-rs` root-owned with group-read access for `postfixadmin`, and creates `/var/lib/postfixadmin-rs` for runtime state. It does not start the service automatically because database/Rspamd permissions must be configured first. Rspamd DKIM integration must be granted narrowly scoped write access to the configured key/map/config paths; do not run the whole service as root.