Activity and blocking
nginx
Turn blocked IPs away in nginx, before PHP runs, with a deny file the connector keeps up to date.
For sites not behind Cloudflare, or as well as it. The connector keeps a deny file up to date and nginx reads it, so blocked addresses never reach PHP.
The Blocking page's Set up nginx walks through these steps with your site's real paths, copy buttons and an example config, and shows how far each server has got.
Laravel, Filament and Statamic: three steps
-
Turn on nginx mode, once for the site:
PORRO_BLOCK_NGINX=truein the site's environment. The scheduler then writes the file every minute, on each server, in production only. -
Add one line to the site's nginx config, on each server, inside
server { }and above the firstlocation:include /path/to/site/storage/porro/nginx-blocklist.conf;On Forge: open the site, then Edit Nginx Configuration from the Files menu.
-
Reload nginx when the list changes, on each server: a scheduled job running every minute as root (on Forge: Server → Scheduler). The setup page gives you the exact command. It reloads only when the file has changed and
nginx -tpasses, so a bad config never takes the site down.
Craft CMS: four steps
Craft has no scheduler of its own, so there's one more: a cron line on each server, as the site's user, running php craft porro/blocklist every minute to keep the file current. Then the include line and the reload job, as above.
Behind Cloudflare as well
nginx would see Cloudflare's address rather than the visitor's, and deny Cloudflare. So when the site is behind Cloudflare (a Cloudflare token is set, or you've opened the setup page through Cloudflare), the deny file also carries Cloudflare's real IP lines, and the config still needs only the one include. If your config already sets real_ip_header, set PORRO_NGINX_REAL_IP=false.
Each server's progress
Every server checks itself every minute by looking, never by running anything: the file exists, a readable nginx config includes it, and the reload job has run since the last change. The setup page lists each one as No file yet, Include missing, Waiting for reload or Loaded.
To see every server, the site needs a cache they share, such as Redis or the database. With a per-server cache, only the server showing the page appears.
The file goes in storage/porro/nginx-blocklist.conf unless PORRO_NGINX_PATH says otherwise.