bilias/rqwatch
bilias/rqwatch is a lightweight Laravel package for watching Redis queues. It gives visibility into queued jobs and queue activity, helping you spot stalled or failing work and keep background processing healthy.
Rqwatch isn't a Composer package and has no service provider, facade, or publishable config — it's a standalone PHP application you deploy next to Rspamd/Postfix. There is no composer require: you either vendor the repo onto the mail node or run it as a sibling service, and your Laravel app integrates over HTTP (the mail get/release API, /maps) and by shelling out to bin/cli.php for cron work. Treat it as infrastructure, not a dependency.
First steps on v2.1.2:
grep -nE '^(RSPAMD|MAIL)_API_PASS=CHANGE_ME_' .env
RSPAMD_API_PASS must be changed in .env and metadata_exporter.conf together../bin/cli.php db:migrate (five migrations, incl. ever_stored index and Users session_version).<Location /maps> block from contrib/apache-rqwatch.conf, restricted to the Rspamd servers that fetch maps, plus contrib/rspamd/local.d/force_actions.conf with your antivirus symbol expression.Where to read first: docs/UPGRADE.md, docs/CONFIGURE.md#rspamd-fuzzy-learning, and config.local.php (the only file you should be editing for site-specific behaviour). First real use case: get the quarantine release flow working end-to-end — a user receives a notification, opens the detail page, and releases the mail via the now-shared release form — because that path touches the API password check, MAILER_DSN/MAILER_FROM, and the new notification-link semantics all at once.
Talk to the mail API, don't scrape the UI. GetMail/Release clients now refuse redirects and accept only the API's reply. If you front Rqwatch with a Laravel proxy or reverse proxy that 302s (auth bounce, trailing slash, HTTPS upgrade), remote get/release will fail. Make the proxy pass through without redirects on the API paths.
Map delivery is a first-class integration surface. Maps under /maps are consumed by Rspamd over HTTP and are now locked down by the shipped Apache config. IP map entries are stored canonically and IPv6 networks are supported, so generate entries as proper CIDRs rather than freeform strings. Per-user personal map entries are capped at 1000 per user per map — set $USER_MAP_MAX_ENTRIES = 0 if your users legitimately curate bigger lists, and pre-empt support tickets when the cap bites.
Fuzzy learning is opt-in and admin-only. Leave it off unless you want the workflow: learn/unlearn quarantined mail as Spam/Not spam, with configurable lists ($fuzzy_learn_flags) and a per-learn weight you can add to without unlearning. Learned mails sharing a hash are surfaced and duplicate learns warn. Schedule cron:fuzzy_cleanup alongside your other timers; $fuzzy_learn_expire_days (default 90) must line up with Rspamd's own fuzzy expiry or you'll accumulate dead records.
Suppress notification noise with maps, not code. The rqwatch_virus_no_notify map is created empty by db:migrate; entries are case-insensitive globs (SECURITE_SPAM, SecuriteInfo.com.Spam-*). Matching mails produce no user or admin notification. This is the clean way to silence a chatty AV signature without touching templates.
Cron, not the Laravel scheduler. cron:import_spool, cron:notifications -B (sends blacklisted mail at any score), and cron:fuzzy_cleanup are CLI subcommands. Either wire them into systemd/cron directly or have Laravel's scheduler exec them on the correct node — remember the importer and mailer run on specific hosts, not wherever your queue worker lives.
Search results are now real GET pages. Fuzzy, alias, user and map searches redirect to a plain GET results page, so Back/refresh work and paging keeps the search. That makes deep links shareable and makes light automation feasible — but aliases and users accept partial addresses like @domain, so be liberal in what you generate.
Session invalidation is the integration contract for identity. session_version means a user's sessions end when an alias is deleted, when an admin changes username/email/password/admin flag/auth provider, or when the user is deleted. If you provision users from a Laravel app via LDAP/OIDC, expect logouts on any attribute change — do the writes in batches, not field-by-field.
ever_stored index build blocks writes cluster-wide under Galera. It scales with mail_logs (~2 s on ~860k rows). Run db:migrate in a quiet window. With $import_spool on (default), imports that fail during the window are spooled and replayed by cron:import_spool — but only if that cron is actually running.rqwatch_virus_no_notify already exists, the migration aborts. Set $notification_skip_virus_map in config.local.php to a fresh name and re-run.CHANGE_ME_ passwords are a silent outage. Import, remote get and release all refuse placeholders. Keep the .env and metadata_exporter.conf values in lockstep or one side will authenticate and the other won't.$notification_links_idle_minutes (10) idle. Set $notification_links_one_time = false if you need a link re-openable until release. Pages send Cache-Control: no-store and Referrer-Policy: no-referrer, so don't try to embed them in an iframe you cache./logout will now fail; fetch the token first.DB_WEB_MAX_STATEMENT_TIME (default 30 s) caps web queries. Runaway searches fail fast, which is good — but the new quarantine-per-month chart and heavy detail pages may need a higher value on slow storage. Tune it rather than removing it.$dns_resolv_redis_fail_cache_ttl) instead of the 3600 s negative TTL, and login throttling counts IPv6 clients by /64 — shared test NAT or a cloud /64 can lock out a whole team. There's no login delay on unmatched routes, blocked IPs, or empty credentials, so timing-based enumeration probes no longer get throttled the way they used to.MAILER_FROM blocks password-less release with a message; MAILER_DSN and MAILER_FROM are validated on the node that actually sends the release, not the web node you're looking at.USER_CAN_SEE_ADMIN_MAP_ENTRIES — admin-created ones; map entry edit/delete/toggle is scoped to the map and the user's own entries. If you relied on USER_CAN_DEL_ADMIN_MAP_ENTRIES for shared addresses, that no longer reaches other users' rows. Non-admins also no longer see other envelope recipients (BCC) or absolute quarantine paths.force_actions.conf discards viruses even from whitelisted senders.config.local.php, the contrib/ Apache and Rspamd confs, the maps, and the cron subcommands. There are no events or hooks — if you need behaviour Rqwatch doesn't offer, you're forking or fronting it with your own Laravel app.How can I help you explore Laravel packages today?