# Limristem eMail

Limristem eMail is a Debian 13+ provisioning kit for a mail stack based on `Postfix`, `Dovecot`, `Rspamd`, `MariaDB`, `Redis`, `PostSRSd`, and a `FastAPI` control plane.

Package/code name: `limristem-mail`.

The repository now ships with safer defaults:
- API bound to `127.0.0.1` and published through `nginx` over HTTPS.
- Unified `limristem-mail` systemd unit running as dedicated service user instead of `root`.
- Admin API password stored as hash (`LIMRISTEM_MAIL_API_ADMIN_PASS_HASH`) instead of plaintext.
- Input validation for domains, mailboxes, aliases, redirects, reputation entities, and DKIM selectors.
- Dovecot quota enforcement wired to `quota_mb`.
- Optional SRS (`postsrsd`) to make external forwarding less likely to fail SPF/DMARC.
- Optional primary-domain support for `MTA-STS` policy serving and `TLS-RPT` DNS guidance.
- Backup, restore, and performance tooling included.

`MTA-STS` should only be enabled when the policy endpoint is served with a publicly trusted certificate. The installer disables `MTA-STS` automatically when `LIMRISTEM_MAIL_SSL_MODE` is neither `letsencrypt` nor `manual`; `TLS-RPT` remains independently configurable because it only requires DNS.

## Contents

- `install.sh` – top-level installer wrapper with interactive prompts and CLI options.
- `scripts/install.sh` – installer/configurer for Debian 13+.
- `scripts/backup.sh` – full/incremental backup job for mail data, configs, Redis, and MariaDB.
- `scripts/restore.sh` – restore helper for filesystem backups and logical MariaDB dumps.
- `scripts/performance-report.sh` – quick operational report for services, queue, DB, Redis, Rspamd, and storage.
- `scripts/deliverability-check.sh` – checks public DNS/TLS/MTA-STS/TLS-RPT readiness from a deployment perspective.
- `scripts/deliverability-report.sh` – saves a timestamped public deliverability report under the live bundle directory.
- `scripts/generate-dns-plan.sh` – prints the DNS zone records and deployment notes for MX/SPF/DKIM/DMARC/MTA-STS/TLS-RPT.
- `scripts/export-live-bundle.sh` – creates a live deployment bundle with DNS, PTR/rDNS, firewall, client settings, and post-install checklist.
- `scripts/manage-queue.sh` – CLI management for Postfix queue.
- `scripts/manage-bans.sh` – CLI management for active fail2ban bans and manual jail-wide bans.
- `scripts/manage-limits.sh` – CLI management for Limristem eMail/Postfix/Rspamd/API limits.
- `scripts/manage-backups.sh` – CLI management for backup settings, local run listing, and on-demand backup execution.
- `scripts/manage-ssl.sh` – shared TLS certificate management for Postfix, Dovecot, Nginx, panel, and API.
- `scripts/sync-postsrsd-domains.sh` – syncs active domains from MariaDB into `postsrsd`.
- `api/` – FastAPI control plane.
- `database/schema.sql` – MariaDB schema.
- `templates/` – templates for Postfix, Dovecot, Rspamd, Nginx, systemd, and PostSRSd.
- `config/` – example env files for runtime and backup configuration.

## Quick start

Recommended on the target Debian 13+ host:

```bash
sudo ./install.sh
```

The wrapper:
- asks for the mail hostname/FQDN;
- asks which optional services/features to activate;
- asks the installation path (default `/opt/limristem-mail`);
- can also run fully from CLI options.

Installed layout:
- `<BASE_DIR>/limristem-mail` – main launcher for CLI/API/panel
- `<BASE_DIR>/config/` – active runtime configuration files only
- `<BASE_DIR>/bin/` – operational helpers and Python runtime modules
- `<BASE_DIR>/bin/api/` – FastAPI runtime package
- `<BASE_DIR>/bin/panel/` – panel HTML templates

Example non-interactive CLI:

```bash
sudo ./install.sh \
  --hostname mail.example.com \
  --install-path /opt/limristem-mail \
  --ssl-mode letsencrypt \
  --le-email postmaster@example.com \
  --public-ip 203.0.113.10 \
  --enable-api yes \
  --enable-nginx yes \
  --enable-rspamd yes \
  --enable-srs yes \
  --enable-mta-sts yes \
  --enable-tls-rpt yes \
  --enable-web-panel no \
  --enable-backup-timer yes \
  --enable-deliverability-timer no
```

`scripts/install.sh` remains available as the low-level installer for environment-driven runs.

What the installer does:
- installs packages and creates service users/groups;
- provisions MariaDB schema and runtime user;
- configures Postfix, Dovecot, Rspamd, Redis, optional PostSRSd, and Nginx;
- builds `.venv`, installs API requirements, and enables `limristem-mail.service` when API runtime is active;
- writes `<BASE_DIR>/config/limristem-mail.env` and `<BASE_DIR>/config/limristem-mail-backup.env`;
- generates `/var/lib/limristem-mail/live-deployment` for the external live rollout;
- can optionally expose a hardened HTTPS admin panel at `/panel`;
- enables `limristem-mail-backup.timer`.

If `LIMRISTEM_MAIL_API_ADMIN_PASS` is omitted, the installer generates one and prints it once at the end. Only the password hash is persisted in `<BASE_DIR>/config/limristem-mail.env`.
If `LIMRISTEM_MAIL_ENABLE_WEB_PANEL=yes` and `LIMRISTEM_MAIL_PANEL_ADMIN_PASS` is omitted, the installer also generates dedicated panel credentials and prints them once at the end. Only the hash is persisted.

## Runtime ports

- SMTP: `25`
- Submission: `587`
- SMTPS: `465`
- IMAP: `143`
- IMAPS: `993`
- POP3: `110`
- POP3S: `995`
- HTTPS API proxy: `443`
- Internal API bind: `127.0.0.1:8080`

## Main config files

- Runtime env: `<BASE_DIR>/config/limristem-mail.env`
- Backup env: `<BASE_DIR>/config/limristem-mail-backup.env`
- App unit: `/etc/systemd/system/limristem-mail.service`
- Backup timer: `/etc/systemd/system/limristem-mail-backup.timer`
- Nginx API proxy: `/etc/nginx/sites-available/limristem-mail-api.conf`
- SRS config: `/etc/default/postsrsd`

## Deliverability notes

Limristem eMail can help you generate correct DNS hints, sign outbound mail with DKIM, and preserve SPF better on forwards via SRS, but real deliverability still depends on:
- valid public certificates;
- proper MX, A/AAAA, SPF, DKIM, DMARC, and PTR/rDNS;
- published `MTA-STS` / `TLS-RPT` records if you enable those policies;
- IP reputation and clean outbound behavior;
- external testing from the deployed host.

## Backups

Limristem eMail includes:
- filesystem full/incremental backups;
- logical MariaDB dumps by default;
- optional physical MariaDB backups via `mariabackup`;
- Redis RDB snapshots;
- local retention;
- remote copy with `rclone`, so you can target `FTP`, `FTPS`, `SFTP/SSH`, `S3`, and other supported backends.

See `config/limristem-mail-backup.env.example` and `docs/OPERATIONS.md`.

## Web panel

When `LIMRISTEM_MAIL_ENABLE_WEB_PANEL=yes`, Limristem eMail exposes a dedicated HTTPS admin panel at `https://<mail-host>/panel` over the primary certificate. The panel uses a separate login flow with Redis-backed sessions, CSRF protection, `Secure` + `HttpOnly` cookies, and bootstrap credentials generated by the installer. It lets you:

- create/update/delete domains
- manage accounts, aliases, and redirects for the selected domain
- inspect and manage the Postfix queue on its own page
- review backup configuration, list local runs, and trigger a backup on its own page
- list, ban, and unban IPv4/IPv6 addresses on a dedicated security page
- inspect and rotate the shared TLS certificate from a dedicated SSL page
- review and update runtime limits on a dedicated limits page
- export suggested DNS records as JSON or Cloudflare-ready zone files
- configure a per-domain Cloudflare DNS provider and publish DKIM TXT records automatically after DKIM rotation
- update account quota, password, suspend/restore state, and deletion directly from dedicated table columns
- toggle light/dark theme and session-scoped accessibility tools from any page

## Operations

Useful commands after install:

```bash
sudo /opt/limristem-mail/limristem-mail add domain example.com
sudo /opt/limristem-mail/limristem-mail add account postmaster@example.com very secure password --quota-mb 4096
sudo /opt/limristem-mail/limristem-mail show dns example.com --zone
sudo /opt/limristem-mail/limristem-mail dns configure-cloudflare example.com --zone-id 0123456789abcdef0123456789abcdef --api-token cloudflare-zone-token --enable-sync
sudo /opt/limristem-mail/limristem-mail dns sync-dkim example.com --json
sudo /opt/limristem-mail/limristem-mail ssl show --json
sudo /opt/limristem-mail/limristem-mail ssl selfsigned --json
sudo /opt/limristem-mail/limristem-mail ssl import /path/to/fullchain.pem /path/to/privkey.pem --json
sudo /opt/limristem-mail/limristem-mail monitor services --json
sudo /opt/limristem-mail/limristem-mail start api --host 127.0.0.1 --port 8080
sudo systemctl status postfix dovecot rspamd limristem-mail nginx
sudo /opt/limristem-mail/bin/generate-dns-plan.sh example.com mail.example.com
sudo /opt/limristem-mail/bin/export-live-bundle.sh example.com mail.example.com 203.0.113.10
sudo /opt/limristem-mail/bin/performance-report.sh
sudo /opt/limristem-mail/bin/deliverability-check.sh example.com mail.example.com 203.0.113.10
sudo /opt/limristem-mail/bin/deliverability-report.sh example.com mail.example.com 203.0.113.10
sudo /opt/limristem-mail/bin/backup.sh
sudo /opt/limristem-mail/bin/restore.sh --help
```

See `docs/LIVE_DEPLOYMENT.md` for the full manual rollout flow on the real host/provider.

## Security model

- API credentials are expected to travel only over HTTPS.
- The API listens locally and is reverse-proxied by Nginx.
- Set `LIMRISTEM_MAIL_TRUSTED_PROXIES` to the IP/CIDR list of the local reverse proxies allowed to supply `X-Forwarded-For`; otherwise Limristem eMail uses the direct peer address for rate limits and login CSRF scope.
- The installer persists `LIMRISTEM_MAIL_PANEL_LOGIN_CSRF_SECRET` so login CSRF tokens stay stable across process restarts independently of admin credential rotation. You can also set it manually before install/update.
- DKIM keys live in `LIMRISTEM_MAIL_DKIM_KEYS_DIR`, writable by `limristem-mail` and readable by Rspamd through the shared `mailkeys` group.
- `Rspamd` failure defaults to temporary reject (`tempfail`) instead of silently accepting unfiltered mail.

## Caveats

- `plain` SSL mode is only for controlled lab use.
- Incremental filesystem restores require the full backup chain.
- Physical MariaDB restore is intentionally left as a controlled manual step after `mariabackup --prepare`.
