Open sourceIn the free reqad package (GPL-3.0).

Update scripts

Reqad keeps its maintenance scripts in /usr/local/reqad/scripts/update/. Each one fixes or sets up one thing on an existing server. Most run on their own on every install and update; a few are for you to run when you need them. This page lists them all, so you know which ones have already run and when to run the others.

You rarely need to run any of these. dnf update reqad runs the automatic ones for you, in the right order. Each checks first and changes nothing when the server is already right, so running one again is harmless. Their output is in /usr/local/reqad/log/post_install.log.

Running one by hand

bash /usr/local/reqad/scripts/update/<script> --dry-run
bash /usr/local/reqad/scripts/update/<script> --apply
  • Run them as root.
  • Where a script has --dry-run, try that first: it shows what would change and changes nothing.
  • Scripts that edit nginx, Apache, exim, dovecot or PHP-FPM test the new configuration first (nginx -t, httpd -t, exim -bV, doveconf, php-fpm -t) and put the old file back if the test fails.
  • The header comment at the top of each script explains why it exists and what it touches.

Run on every install and update

In the order the update runs them. By hand lists the options that are useful when you run one yourself; panel marks scripts the panel also calls when you change the setting they belong to.

Panel, webmail and web server

ScriptWhat it doesBy hand
update_hostname_cert.shMakes sure the panel (port 2087, and the account panel on 2083) and the server hostname's default nginx site use a certificate that exists. If the hostname's Let's Encrypt certificate could not be issued (for example port 80 is not reachable from the internet yet, or the DNS record is new), they get a self-signed certificate so the panel still starts; once the Let's Encrypt certificate exists they switch to it. A certificate you set yourself is kept.--dry-run. Run it after getting the hostname's certificate to switch to it right away.
setup_reqad_fpm.shSets up the panel's own PHP-FPM master (reqad-php-fpm, with its own php.ini). Runs once; later updates leave it alone, so your changes are kept.-
update_ini.shAdds missing keys to etc/server-software.ini. Never changes a value you set.-
update_roundcube.shUpdates Roundcube (webmail) to the latest stable release; keeps its config, logs, temp files and custom plugins. Also runs install-webmail-autologin.sh.Run it to update webmail between Reqad releases.
install-webmail-autologin.shInstalls the Roundcube plugin behind the panel's "open webmail" button, and makes webmail send mail signed in as the mailbox, so the server's sending limits apply to webmail too. A sending setting you changed yourself is kept.Panel: when webmail auto-login is switched on.
setup_webmail_guard.sh --applyWebmail brute-force protection: at most 3 failed logins a minute per mailbox, login POSTs limited per IP in nginx, and an lfd rule (tag reqadwebmail) that blocks an IP in the firewall after 10 failed logins. Blocks show under Settings > Security > Blocked addresses.--dry-run, --remove
setup_webmail_port.shGives webmail a port of its own, 2096: https://<hostname>:2096/webmail/. Mailbox owners then never need the panel's port 2087, so you can turn on Settings > Security > IP restriction and webmail keeps working for everyone. Only webmail is served on 2096, not the panel. Old links to :2087/webmail/ (and :2083/webmail/ with an up-to-date account panel) go to the new address, the firewall opens port 2096, and every site's /webmail address points there. The "open webmail" buttons in both panels keep signing you in.--dry-run shows the change, --remove puts webmail back on the panel's port, --no-firewall leaves the firewall alone.
update_user_phpfpm.shAdds required settings (security, logs, temp directories) to every account's PHP-FPM pool.-
update_default_nginx_host.shCreates the default nginx site for the server hostname if it is missing, with a Let's Encrypt certificate if there is one, otherwise self-signed, and includes the Git deploy webhook address when it is set up.Panel: when converting Apache to nginx.
update_certbot_hostname.shRenews the hostname certificate through the web server instead of the standalone method.-
update_default_apache_host.shThe same as the nginx one, for Apache servers (skipped when Apache is not installed, or when it runs behind nginx).-
update_wetty_shell.shKeeps the web terminal (wetty) on Reqad's packaged start script. Does nothing without wetty.-
merge_le_ssl_vhosts.shApache servers: when Let's Encrypt was set up on a site that had no https settings yet, certbot kept them in a separate file. This moves them into the site's own settings file, so the panel shows the certificate and its changes (suspension, redirects, PHP settings, removing the site) apply to https too. Websites keep working exactly as before; each site is tested and put back if the test fails.--dry-run, --domain=<site>. Panel: after getting a Let's Encrypt certificate on Apache.

Mail

ScriptWhat it doesBy hand
setup_autoresponder_sieve.shSets up autoresponders in Sieve. Only acts on servers that deliver mail through dovecot LMTP (see setup_dovecot_sieve.sh below).-
setup_sieve_pipe.shEnables the "Pipe to a program" email filter action, for server-wide and domain filters only. Same condition as above.-
seed_skiprbl_extra.shOne-time move of a hand-made RBL skip list into the panel's "extra addresses". Does nothing afterwards.-
fix_maildir_dotfiles.shKeeps dovecot's internal files out of the folder list in mail clients.-
fix_imap_separator.shMakes sure the IMAP folder separator is ., which matches how mail is stored, and repairs folder subscriptions.-
fix_managesieve_listen.shManageSieve listens on IPv4 loopback only, so dovecot starts on servers without IPv6.-
setup_special_use.shTells mail clients which folders are Sent, Drafts, Trash and Junk, so phones and webmail use the same ones.Afterwards see merge_duplicate_sent.sh.
repair_truncated_exim_conf.shRestores a damaged exim configuration from the newest good backup. Does nothing when the configuration is complete.[path to exim.conf]
setup_spam_score_logging.shOne SpamAssassin scan per incoming message as the receiving account, the score in exim's log and X-Spam-* headers on the message.-
setup_spamd_per_user.shLets SpamAssassin read each account's own allow and block lists.-
setup_exim_reload.shGives exim a real reload, so configuration changes apply without dropping connections.Panel: used before reloading exim.
setup_mail_limits.shOutgoing limits per sending domain: messages per hour and failed messages per hour.Panel: Email > Config.
fix_system_alias_pipe.shDelivers mail for root to the panel's root-mail forwarder reliably.-
setup_root_mail_log.shWhen root mail forwarding is off, keeps mail sent to root (cron, firewall, monitoring) on the server in /var/log/reqad/root-mail instead of leaving it in the mail queue. The file is readable only by root and the panel, and its size is capped at 10 MB plus one older copy. Settings > System mail shows the last 100 lines.--dry-run
setup_forward_spam_gate.shDoesn't forward mail SpamAssassin already marked as spam, which protects the server's sending reputation.Panel: switch in Email > Config.
setup_exim_remote_domains.shLets a domain's email be handled by another provider (such as Google Workspace, Microsoft 365 or Zoho Mail) while its website stays on this server: mail the server sends to that domain then goes to the provider instead of the mailboxes here, and mail that still arrives here while the change spreads is passed on to the provider or retried, not refused. Only the standard mail server settings are changed.--dry-run shows the change. Panel: Mail provider in the account panel's DNS zone.
setup_exim_dbl.shSender domain check: refuses incoming mail when the sender's domain is on the Spamhaus Domain Block List as spam, phishing, malware or botnet, which also stops a spammer who moves to new IP addresses. Real sites that were hacked, bounces, your own users and trusted senders are not refused. It also makes the Spamhaus IP blocklists count only real listings, so a refused DNS resolver can never cause all mail to be rejected.--on / --off. Panel: Email > Exim > Blocklists. The dashboard warns when Spamhaus does not answer the server's DNS resolver.
ensure_dovecot_packages.shChecks that the dovecot add-on packages match dovecot and that Sieve is installed where it is used. During an update it only reports.--fix installs what is missing.
setup_dovecot_compress.sh --repairMail compression settings for dovecot 2.4; --repair only fixes a setup that is already on.--status, --disable. Panel: Email > Config.
setup_dovecot_vsz.sh --migrateThe memory limit per IMAP/POP3 process, kept in its own file.--status, --vsz <size>, --reset. Panel: Email > Config.
setup_autoconfig.shAutomatic setup of mail accounts in Thunderbird and Outlook (static files, no PHP involved).Panel: when converting Apache to nginx.

Security and isolation

ScriptWhat it doesBy hand
patch_csf_cve_2026_67402.shApplies the CVE-2026-67402 fix to an installed csf (new installs get a fixed csf).-
fix_vhost_deny_order.shPuts the "deny hidden files" and "deny PHP in uploads" rules of existing sites before the PHP handler.--dry-run
setup_error_pages.shReqad's error pages for every site; the pages don't name the web server software. The web server reads them from /usr/share/reqad/error-pages.Panel: when converting Apache to nginx.
setup_directory_index.shOn servers with Apache, a folder that has both an index.php and an index.html shows the index.php, as it does with nginx. A site can still choose another order with DirectoryIndex in its .htaccess.--dry-run, --remove
setup_httpd_home_overrides.shOn servers with Apache, the public_html folder of every account allows the same .htaccess settings as the sites themselves. An addon domain or subdomain whose folder is inside public_html also reads the main site's .htaccess; before, an Options line there (for example Options -Indexes) made the addon site answer with an error 500. A copy of the old file is kept, and it is put back if Apache does not accept the change.--dry-run, --remove
setup_site_file_denies.shSites do not serve hidden files and folders (such as .git or .env) or the instruction files of AI coding assistants (CLAUDE.md, AGENTS.md, GEMINI.md), which answer 404. On nginx the rules go into each site's configuration; on servers with Apache they are in /etc/httpd/conf.d/reqad-site-denies.conf, written once and then left as you change it. Both carry a commented-out alternative that keeps /.well-known/ reachable, for a certificate client other than certbot (certbot adds its own rule while it checks the domain).--dry-run
fix_cache_perms.shTightens permissions on the nginx caches and the shared PHP session folder.-
fix_letsencrypt_perms.shKeeps Let's Encrypt private keys readable only by the server and the mail services, and certificates readable by all. Runs again after every certificate renewal.--check (only report)
refresh_wp_security.phpRe-applies WordPress Toolkit security rules to the sites that use them, so rule improvements in an update reach them. When a site has several WordPress installs (for example one in /blog), the rules protect all of them.Run with the panel's PHP: /opt/reqad/php-current/usr/bin/php -c /etc/reqad/php-fpm/php.ini …
update_wp_cache_blocks.shBrings the WordPress Toolkit page cache of sites that use it up to date, with each site's own cache rules. Links that carry only campaign tags (utm_, gclid, fbclid and similar) are served from the cache, and WordPress sees them without the tags. Sites that are already current are left alone; the previous files are kept in /var/lib/reqad/vhost-backups/.--dry-run
fix_panel_ip_bypass.shThe panel asks every client for its login, and monit checks an nginx-only /reqad-health address instead of the dashboard.--dry-run
remove_panel_websocket.shRemoves an unused web address from the panel that belonged to the old WordPress scan console, which the panel no longer has. Does nothing once it is gone.--dry-run
setup_panel_loopback_guard.shFirewall rule: code running as a hosting account can't connect to the panel's local ports (panel, web terminal, monit), nor straight to Apache behind nginx, nor to the apps of other accounts.--dry-run, --remove
setup_panel_api.shMakes the panel's web server send /api/ on port 2087 to the REST API, which accepts access tokens only (never the panel login) and limits how fast one address can call it. The API itself stays off until you turn it on. Other panels on the same web server, such as the account panel on port 2083, keep their own /api/. It also sends /pdns/ to the DNS API, where other servers keep their own DNS zones on this server with a DNS API key; that too stays off until you turn it on.--dry-run, --remove
setup_deploy_webhook.shLets GitHub, GitLab, Gitea and Bitbucket start a Git deployment on push, at https://<hostname>/.reqad-deploy/<id>. Only signed requests start a deploy, and the panel port can stay closed to the internet. Needs nginx in front.--dry-run, --remove
fix_panel_tree_perms.shThe panel's folder, database and backups are readable by the panel only, not by hosting accounts.--dry-run
fix_dovecot_users_perms.shThe mailbox password file is readable by the mail server and root only.--dry-run
setup_sysctl_hardening.shKernel settings that keep accounts from watching each other (/etc/sysctl.d/90-reqad.conf). Override a value in 99-local.conf.--dry-run, --remove
fix_sudo_nsswitch.shStops sudo from looking up its rules in sssd on servers that don't run sssd (many cloud images are set up that way). Without it every sudo call writes a “problem with defaults entries” warning and mails it to root, which fills the mail queue. Servers where sssd is configured are left alone.--dry-run
setup_proc_hidepid.shEach account sees only its own processes.--dry-run, --remove
harden_account_perms.sh --apply --quietAccount permissions: a site's files readable by its own account and the web server only; PHP pools in the account's own group. Writes a restore script (/var/lib/reqad/perms-restore-<time>.sh) before changing anything.--dry-run, --user=NAME. Panel: after a PHP handler change and when converting Apache to nginx.
setup_symlink_protection.shSymbolic links: a site can only follow a link to a file with the same owner, so an account cannot link another account's files into its own site. With Apache (PHP-FPM templates), .htaccess files can no longer turn on FollowSymLinks; the ones that ask for it get SymLinksIfOwnerMatch, which rewrite rules accept the same way. Lists the links that will stop working first.--dry-run, --htaccess (only the .htaccess files), --remove
tune_fpm_pools.sh --applyMoves PHP pools still on the old defaults to on-demand workers: up to 20 per site, stopped after 10 s idle, a stuck script ended after 5 minutes. Pools you tuned are left alone.--dry-run
setup_session_limits.sh --applyCPU, memory and process limits for each account's SSH, cron and web terminal sessions, and the log of limit hits.--dry-run, --remove. Per account: reqad account limits.

The update also runs three steps from outside this folder: scripts/account_shell.sh install (the jailed shell, for accounts with jailed or SFTP-only access), scripts/account_shell.sh restrict (when root_access=0 is set in server-software.ini, accounts get only the jailed shell or SFTP: one that still has a full shell is moved to the jailed shell and cron jobs run in the sandbox; nothing changes otherwise) and reqad account limits --sync-db --quiet (database connection limits per account).

Run once, when needed

ScriptWhen the update runs itWhat it does
migrate_smtp_errors_log.shUpdating from a panel database older than 1034.Moves old SMTP delivery errors from the panel database into log/smtp_errors.log.

Run by hand

These are never run by an update, because they change how mail is delivered, install packages, or are one-off jobs. Run each one when you need what it does.

ScriptWhen to run itNotes
check_lmtp_readiness.shBefore switching mail delivery to dovecot LMTP.Only reads. A non-zero exit code means: don't switch yet. setup_dovecot_sieve.sh runs it itself.
setup_dovecot_sieve.shTo turn on email filters at all three levels (server, domain, mailbox) and filter editing from webmail and mail clients.Switches delivery to dovecot LMTP + Sieve and installs packages. --check only reports. See Email filters.
setup_dovecot_fts.shTo make mailbox searches fast.Installs a package, restarts dovecot and indexes every mailbox over time. See Email search & indexing.
merge_duplicate_sent.shOnce, after setup_special_use.sh, to merge Apple Mail's "Sent Messages" into "Sent".Only reports by default; --apply moves the mail. The only script here that moves messages.
migrate_dovecot_2.4.shUpgrading a server from dovecot 2.3 to 2.4.Rewrites the dovecot configuration and keeps mailboxes, certificates and keys. --no-upgrade, --force.
rename_hostname.shChanging the server's hostname.<new.host.name> [--dry-run] [--yes] [--no-cert] [--delete-old-cert]. Updates the server's own sites, the certificate (a free one for the new name when it already points to the server), mail, the account panel on port 2083 and its /cpanel links, Git deploy webhooks and the FTP certificate. Copies every file it changes to /root/reqad-hostname-rename-<time>/ first. Moving to a new IP address too? Change the IP first, then the name.
update_phpmyadmin.shTo update phpMyAdmin to the latest stable release.Keeps its configuration and temp folder.
ensure_dovecot_packages.sh --fixWhen an update reported a missing or mismatched dovecot package.The report-only check runs on every update.

Need a hand? Create a free account or contact us.