
WordPress remains the most practical way to launch a blog, business site, portfolio, or small ecommerce store without building everything from scratch. On Fedora 44, the installation process is straightforward, but a production-ready setup needs more than running a few package commands. You need a properly configured Apache web server, MariaDB database, PHP runtime, correct file ownership, SELinux-aware permissions, HTTPS, and a firewall that only exposes what it must.
Fedora 44 ships with modern versions of the core stack: Apache, MariaDB, and PHP through PHP-FPM. That combination gives WordPress a fast, maintainable foundation, especially when you configure PHP OPcache and use sensible MariaDB tuning. WordPress itself recommends PHP 8.3 or newer, MariaDB 10.11 or newer, and HTTPS support, all of which are easy to meet on a current Fedora system.
This guide walks through a complete WordPress installation on Fedora 44 using the LAMP stack: Linux, Apache, MariaDB, and PHP. It covers installation, database creation, WordPress configuration, SELinux, firewalld, SSL certificates, performance tuning, backups, and the errors that tend to appear once real traffic starts hitting the server.
Prerequisites
Before starting, make sure you have:
- A Fedora 44 server or virtual machine with at least 1 GB RAM; 2 GB is more comfortable for WordPress plus MariaDB.
- Root access or a user with sudo privileges.
- A domain name pointed to the server’s public IP address, if you plan to serve the site publicly.
- Ports 80 and 443 reachable through any cloud firewall or security group.
- Basic familiarity with the terminal.
If you are testing locally, you can use localhost or the server’s LAN IP address. For a public production site, DNS should be configured before issuing a Let’s Encrypt certificate.
Start by updating the system. On Fedora, this refreshes repository metadata and applies current package updates:
sudo dnf upgrade --refresh -y
Reboot if the update installs a new kernel:
sudo reboot
After the server comes back online, confirm the Fedora release:
cat /etc/fedora-release
Install the LAMP Stack
WordPress needs four moving parts: a web server, a database server, PHP, and the operating system underneath them. Fedora’s package manager, DNF, can install all of them in one transaction, which reduces the chance of ending up with mismatched package versions.
Install Apache, MariaDB, PHP-FPM, and the PHP extensions WordPress relies on:
sudo dnf install -y \
httpd \
mariadb-server \
php \
php-cli \
php-fpm \
php-mysqlnd \
php-gd \
php-curl \
php-mbstring \
php-xml \
php-intl \
php-opcache \
php-zip \
php-pecl-zip
These packages matter for more than the initial installer:
httpdprovides the Apache HTTP server.mariadb-serverprovides the database engine.php-fpmruns PHP as a separate FastCGI process manager.php-mysqlndenables PHP to communicate with MariaDB using the MySQL native driver.php-gdsupports image manipulation.php-curlis required for outbound HTTP requests, plugin updates, and some theme functionality.php-mbstringhandles multibyte text, important for international content.php-xmlandphp-intlsupport XML processing and localization.php-opcachecaches compiled PHP bytecode, reducing repeated compilation work.php-zipsupports plugin and theme uploads that arrive as ZIP archives.
Enable and start Apache, MariaDB, and PHP-FPM:
sudo systemctl enable --now httpd mariadb php-fpm
Check that all three services are active:
systemctl is-active httpd mariadb php-fpm
You should see:
active
active
active
If any service fails, inspect its logs before continuing:
sudo journalctl -u httpd -b --no-pager
sudo journalctl -u mariadb -b --no-pager
sudo journalctl -u php-fpm -b --no-pager
Configure the Firewall
Fedora commonly uses firewalld. If it is installed and running, open HTTP and HTTPS traffic:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Confirm the rules:
sudo firewall-cmd --list-all
Look for http and https under services. On a cloud VPS, also verify that the provider’s security group allows inbound TCP ports 80 and 443. A local firewall rule will not help if the upstream cloud firewall blocks the traffic.
For a quick test, create a temporary Apache page:
echo '<?php phpinfo(); ?>' | sudo tee /var/www/html/info.php
Visit:
http://your_server_ip/info.php
You should see the PHP information page. Delete it immediately afterward; exposing phpinfo() publicly reveals configuration details that are useful to attackers:
sudo rm -f /var/www/html/info.php
Secure MariaDB
MariaDB is installed with a root account that, on many fresh Fedora installs, uses Unix socket authentication for local administrative access. That is convenient, but a WordPress database should never use the database root account.
Run MariaDB’s security script:
sudo mysql_secure_installation
Answer the prompts as follows for a typical single-purpose web server:
- Switch to Unix socket authentication:
Y, if prompted and appropriate for your workflow. - Set a root password: choose a strong password and store it in a password manager.
- Remove anonymous users:
Y. - Disallow remote root login:
Y. - Remove the test database:
Y. - Reload privilege tables:
Y.
If you prefer explicit SQL hardening instead of the interactive script, you can run:
sudo mariadb
Then execute:
DELETE FROM mysql.global_priv WHERE User='';
DELETE FROM mysql.global_priv WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
DROP DATABASE IF EXISTS test;
FLUSH PRIVILEGES;
EXIT;
Be careful with database-level changes on an existing server. On a fresh WordPress host, these steps are safe. On a server already hosting other applications, review each account before removing anything.
Create the WordPress Database
WordPress stores posts, pages, users, comments, settings, and plugin configuration in MariaDB. Create a dedicated database and a dedicated database user rather than sharing credentials across applications.
Log in to MariaDB as the administrative root user:
sudo mariadb -u root -p
Create the database. The utf8mb4 character set is the right choice for modern WordPress installations because it fully supports emojis, international characters, and many non-Latin scripts:
CREATE DATABASE wordpress_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Create a least-privilege database user. Replace the password with a long, unique value:
CREATE USER 'wordpress_user'@'localhost' IDENTIFIED BY 'UseAVeryLongUniquePasswordHere';
Grant that user access only to the WordPress database:
GRANT ALL PRIVILEGES ON wordpress_db.* TO 'wordpress_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Why limit the grant to wordpress_db.*? If the WordPress database credentials ever leak, the attacker should not automatically gain access to every other database on the server. This is a small configuration decision that pays off enormously in a multi-application environment.
Test the credentials:
mariadb -u wordpress_user -p wordpress_db
If login succeeds, exit:
EXIT;
Download and Install WordPress
Create a dedicated document root for the site. Keeping WordPress outside the default /var/www/html directory makes it easier to host multiple sites cleanly:
sudo mkdir -p /var/www/wordpress
cd /tmp
Download the latest WordPress release:
curl -LO https://wordpress.org/latest.tar.gz
Extract it into the site directory:
sudo tar -xzf latest.tar.gz -C /var/www/wordpress --strip-components=1
Remove the archive:
rm -f latest.tar.gz
Copy the sample configuration file:
sudo cp /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php
Generate unique security keys and salts. WordPress uses these values for cookie authentication and other cryptographic operations. Do not reuse the example values from the sample file:
curl -s https://api.wordpress.org/secret-key/1.1/salt/
Open the configuration file:
sudo nano /var/www/wordpress/wp-config.php
Update the database settings:
define( 'DB_NAME', 'wordpress_db' );
define( 'DB_USER', 'wordpress_user' );
define( 'DB_PASSWORD', 'UseAVeryLongUniquePasswordHere' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );
Replace the authentication keys and salts with the values generated from the WordPress API. The section looks like this:
define( 'AUTH_KEY', 'replace-this-with-a-unique-value' );
define( 'SECURE_AUTH_KEY', 'replace-this-with-a-unique-value' );
define( 'LOGGED_IN_KEY', 'replace-this-with-a-unique-value' );
define( 'NONCE_KEY', 'replace-this-with-a-unique-value' );
define( 'AUTH_SALT', 'replace-this-with-a-unique-value' );
define( 'SECURE_AUTH_SALT', 'replace-this-with-a-unique-value' );
define( 'LOGGED_IN_SALT', 'replace-this-with-a-unique-value' );
define( 'NONCE_SALT', 'replace-this-with-a-unique-value' );
Add these production-oriented settings near the bottom of the file, before the line that says:
/* That's all, stop editing! Happy publishing. */
define( 'WP_HOME', 'https://example.com' );
define( 'WP_SITEURL', 'https://example.com' );
define( 'FORCE_SSL_ADMIN', true );
define( 'WP_MEMORY_LIMIT', '256M' );
define( 'WP_MAX_MEMORY_LIMIT', '512M' );
define( 'DISALLOW_FILE_EDIT', true );
define( 'WP_POST_REVISIONS', 10 );
define( 'WP_AUTO_UPDATE_CORE', 'minor' );
define( 'FS_METHOD', 'direct' );
A few notes from operational experience:
DISALLOW_FILE_EDITprevents WordPress from editing theme and plugin files through the dashboard. If an administrator account is compromised, this reduces the immediate blast radius.WP_AUTO_UPDATE_COREset tominorallows automatic security and maintenance releases while leaving major upgrades for a controlled maintenance window.FS_METHODset todirectavoids FTP credential prompts during plugin and theme updates, provided file permissions are correct.
Save and close the file.
Set File Ownership and Permissions
This is where many WordPress installations become either insecure or unnecessarily fragile. The web server needs to read WordPress files. It also needs write access to wp-content for uploads, plugin installations, and theme updates, but it should not need write access to core WordPress files under normal operation.
Set ownership of the WordPress directory to Apache:
sudo chown -R apache:apache /var/www/wordpress
Set safe directory permissions:
sudo find /var/www/wordpress -type d -exec chmod 755 {} \;
sudo find /var/www/wordpress -type f -exec chmod 644 {} \;
Protect the WordPress configuration file:
sudo chmod 600 /var/www/wordpress/wp-config.php
Create the uploads directory if it does not already exist:
sudo mkdir -p /var/www/wordpress/wp-content/uploads
sudo chown -R apache:apache /var/www/wordpress/wp-content/uploads
In practice, wp-content often needs to remain writable by Apache because WordPress installs plugins and themes from the dashboard. If your workflow allows it, you can tighten permissions after deployment and use WP-CLI or a deployment pipeline for updates. For a typical self-hosted site, writable wp-content with properly restricted core files is a reasonable balance.
Configure SELinux
Fedora enforces SELinux by default. This is a feature, not an obstacle. It limits what the Apache process can do even if the web application is compromised.
Check the SELinux context on the WordPress directory:
ls -Z /var/www/wordpress | head
Files under /var/www should normally inherit the correct httpd_sys_content_t context. If Apache returns permission errors despite standard Unix permissions being correct, restore the context:
sudo restorecon -Rv /var/www/wordpress
Allow Apache to connect to the local MariaDB service:
sudo setsebool -P httpd_can_network_connect_db on
This boolean is commonly required when PHP-FPM or Apache needs to communicate with a database service.
If you use an external object storage plugin, outbound webhook service, or remote API integration, you may also need:
sudo setsebool -P httpd_can_network_connect on
Use SELinux booleans deliberately. Do not disable SELinux just to make an error disappear. A better workflow is to inspect denials first:
sudo ausearch -m avc -ts recent
Then apply the narrowest fix that resolves the specific denial.
Configure Apache for WordPress
Create an Apache virtual host for the site:
sudo nano /etc/httpd/conf.d/wordpress.conf
Add the following configuration, replacing example.com and www.example.com with your domain:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/wordpress
<Directory /var/www/wordpress>
AllowOverride All
Require all granted
</Directory>
ErrorLog /var/log/httpd/wordpress_error.log
CustomLog /var/log/httpd/wordpress_access.log combined
</VirtualHost>
AllowOverride All permits WordPress to use its .htaccess file for permalink rewriting and other rules. On a high-traffic site, some administrators prefer moving rewrite rules into the Apache virtual host itself for slightly better performance, but .htaccess remains the simplest and most compatible option for WordPress.
Test the Apache configuration:
sudo apachectl configtest
Expected output:
Syntax OK
Restart Apache:
sudo systemctl restart httpd
Enable HTTPS with Let’s Encrypt
A WordPress site should not run over plain HTTP. Login credentials, session cookies, admin dashboard traffic, and form submissions all benefit from TLS encryption.
Install Certbot and the Apache plugin:
sudo dnf install -y certbot python3-certbot-apache
Issue and install a certificate:
sudo certbot --apache -d example.com -d www.example.com
Certbot will ask for an email address, require agreement to the terms of service, and offer to redirect HTTP traffic to HTTPS. Choose the redirect option.
Verify automatic renewal:
sudo certbot renew --dry-run
Let’s Encrypt certificates renew automatically through a systemd timer in most setups. Check the timer:
systemctl list-timers | grep certbot
If you are using Cloudflare in proxy mode, make sure the SSL/TLS mode is set to Full or Full Strict, not Flexible. Flexible mode can create redirect loops and does not provide end-to-end encryption between Cloudflare and your origin server.
Complete the WordPress Installation
Open your domain in a browser:
https://example.com
WordPress should display its installation wizard.
Choose:
- Site title
- Admin username
- Strong admin password
- Administrator email address
- Search engine visibility preference
Avoid using admin as the username. It is one of the first values automated login attempts try. Use a unique username and a long passphrase stored in a password manager.

After installation, log in at:
https://example.com/wp-admin
Before installing plugins or themes, check for updates:
Dashboard -> Updates
Then configure permalinks:
Settings -> Permalinks -> Post name
Save the settings. WordPress writes the required rewrite rules to .htaccess.
Install WP-CLI
WP-CLI is one of those tools that becomes indispensable once you manage more than one WordPress site. It lets you update plugins, clear caches, search-replace URLs, inspect database tables, and run maintenance tasks from the terminal.
Install it:
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
Verify the downloaded file:
php wp-cli.phar --info
Make it executable and move it into the system path:
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
Confirm installation:
wp --info --path=/var/www/wordpress
Useful examples:
cd /var/www/wordpress
wp core version
wp plugin list
wp theme list
wp core update
wp plugin update --all
wp cache flush
wp db optimize
WP-CLI is especially useful during incidents. If a plugin update breaks the site, you can deactivate it without accessing the dashboard:
wp plugin deactivate broken-plugin
PHP Performance Tuning
PHP-FPM is the component that executes WordPress code. Default settings are conservative, which is sensible for a small server but can become a bottleneck during a traffic spike.
Open the PHP-FPM pool configuration:
sudo nano /etc/php-fpm.d/www.conf
Look for the process manager settings. For a 2 GB WordPress server, a reasonable starting point is:
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
pm.max_requests = 500
These values are not universal. Each PHP worker can consume roughly 50 MB to 120 MB depending on themes, plugins, and workload. Do not blindly raise pm.max_children on a small VPS; doing so can exhaust memory and trigger the kernel’s out-of-memory killer.
A practical calculation:
Available RAM for PHP / average PHP worker memory = pm.max_children
For example, if 1.5 GB is safely available for PHP and workers average 75 MB:
1536 MB / 75 MB = approximately 20 workers
Apply the configuration:
sudo systemctl restart php-fpm
Check for PHP-FPM saturation during busy periods:
sudo journalctl -u php-fpm -f
Warnings such as server reached pm.max_children setting mean PHP-FPM cannot spawn enough workers to handle incoming requests. Increase worker capacity only after confirming available RAM, or move to a larger server.
Configure PHP OPcache
OPcache stores compiled PHP bytecode in memory. Without it, every request forces PHP to recompile scripts, wasting CPU and adding latency.
Create a dedicated PHP configuration file:
sudo nano /etc/php.d/99-wordpress-opcache.ini
Add:
opcache.enable=1
opcache.memory_consumption=192
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=16000
opcache.validate_timestamps=1
opcache.revalidate_freq=60
opcache.save_comments=1
Restart PHP-FPM:
sudo systemctl restart php-fpm
validate_timestamps=1 allows PHP to detect changed files. Setting it to 0 improves performance but requires a PHP-FPM restart after every deployment. For a normal WordPress site, 1 with a 60-second revalidation interval is the safer default.
Tune MariaDB for WordPress
MariaDB defaults are conservative. They work, but WordPress databases can grow quickly once post revisions, transients, plugin tables, and logs accumulate.
Create a tuning override file:
sudo nano /etc/my.cnf.d/99-wordpress.cnf
Add a cautious starting configuration for a 2 GB server:
[mysqld]
innodb_buffer_pool_size = 768M
innodb_log_file_size = 256M
innodb_flush_method = O_DIRECT
innodb_file_per_table = 1
max_connections = 100
tmp_table_size = 64M
max_heap_table_size = 64M
slow_query_log = 1
slow_query_log_file = /var/log/mariadb/slow-query.log
long_query_time = 2
Restart MariaDB:
sudo systemctl restart mariadb
The InnoDB buffer pool is the most important setting. It caches data and indexes in RAM, reducing disk reads. Do not allocate all available memory to it; leave room for PHP-FPM, Apache, the operating system, backups, and temporary query workloads.
On a Btrfs filesystem, MariaDB performance can suffer because copy-on-write behavior is inefficient for database files. If /var/lib/mysql resides on Btrfs, disable CoW for the database directory before substantial data exists:
sudo chattr -R +C /var/lib/mysql
This is a Fedora-specific edge case worth checking before launch.
Apache and Caching Optimization
WordPress is dynamic by default. Every page view can trigger PHP execution and multiple database queries. Caching reduces that repeated work.
A simple and effective stack is:
- Apache with
mod_deflatefor compression - Browser caching headers for static assets
- A WordPress page caching plugin
- Object caching for repeated database queries
- A CDN for global traffic and static asset delivery
Enable Apache compression and expiration modules:
sudo dnf install -y mod_deflate mod_expires
Create a cache configuration file:
sudo nano /etc/httpd/conf.d/performance.conf
Add:
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json image/svg+xml
</IfModule>
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>
Test and restart Apache:
sudo apachectl configtest
sudo systemctl restart httpd
For page caching, WP Super Cache, W3 Total Cache, or LiteSpeed Cache are common choices. On Apache, WP Super Cache is often the least complicated option. On a high-traffic site, consider moving to Nginx with FastCGI caching or adding Varnish, but only after measuring where the bottleneck actually is.
Do not stack every caching plugin available. Multiple page caches can conflict, serve stale content, and make debugging miserable. Choose one page-cache layer and test it.
WordPress Security Hardening
A fresh WordPress install is not automatically insecure, but its popularity makes it a constant target. Most compromises come from outdated plugins, weak credentials, vulnerable themes, or misconfigured file permissions.
Keep Everything Updated
Run updates regularly:
cd /var/www/wordpress
sudo -u apache wp core update
sudo -u apache wp plugin update --all
sudo -u apache wp theme update --all
Before major updates, take a backup. A plugin update can break a site just as easily as a WordPress core update.
Limit Login Exposure
Install a reputable security plugin or use server-level controls to limit repeated failed logins. Options include:
- Fail2ban with an Apache log filter
- Cloudflare rate limiting
- A WordPress security plugin with login throttling
- Restricting
/wp-login.phpby IP address for private or internal sites
For a site with only a few known administrators, Apache-level IP allowlisting is highly effective:
<Files wp-login.php>
Require ip 203.0.113.10
Require ip 198.51.100.24
</Files>
Add this inside the appropriate virtual host or .htaccess file. Only use it when administrator IP addresses are stable.
Protect Sensitive Files
Block direct access to sensitive files:
<FilesMatch "^(wp-config\.php|\.htaccess|\.user\.ini|readme\.html|license\.txt)$">
Require all denied
</FilesMatch>
Also disable XML-RPC if you do not need it. Many automated attacks abuse xmlrpc.php for brute-force attempts and pingback floods:
<Files xmlrpc.php>
Require all denied
</Files>
Some Jetpack features, mobile apps, and certain publishing tools rely on XML-RPC. Disable it only after confirming none of your integrations need it.
Use Strong Database Practices
Never use the MariaDB root account for WordPress. Keep database credentials in wp-config.php with 600 permissions. Rotate credentials if a developer, contractor, or agency no longer needs access.
Backups and Disaster Recovery
A backup that has never been restored is only a hope, not a recovery plan. At minimum, back up:
/var/www/wordpress- The MariaDB database
wp-config.php- SSL certificates, if they are not automatically managed by Certbot
- Apache virtual host configuration
Create a database backup:
sudo mariadb-dump --single-transaction --quick \
-u wordpress_user -p wordpress_db > /backup/wordpress_db_$(date +%F).sql
Create a files backup:
sudo tar -czf /backup/wordpress_files_$(date +%F).tar.gz \
-C /var/www wordpress
For automated backups, create a script:
sudo nano /usr/local/bin/wordpress-backup.sh
Add:
#!/bin/bash
set -euo pipefail
BACKUP_DIR=/backup/wordpress
DATE=$(date +%F_%H-%M)
DB_NAME=wordpress_db
DB_USER=wordpress_user
DB_PASS='UseAVeryLongUniquePasswordHere'
SITE_DIR=/var/www/wordpress
mkdir -p "$BACKUP_DIR"
mariadb-dump --single-transaction --quick \
-u "$DB_USER" -p"$DB_PASS" "$DB_NAME" \
| gzip > "$BACKUP_DIR/db_${DATE}.sql.gz"
tar -czf "$BACKUP_DIR/files_${DATE}.tar.gz" -C /var/www wordpress
find "$BACKUP_DIR" -type f -mtime +14 -delete
Make it executable:
sudo chmod 700 /usr/local/bin/wordpress-backup.sh
Schedule it daily at 2:30 AM:
sudo crontab -e
Add:
30 2 * * * /usr/local/bin/wordpress-backup.sh >> /var/log/wordpress-backup.log 2>&1
Store backups off the server. Local backups protect against application failure, not disk failure, ransomware, or a compromised server. Use S3-compatible object storage, Backblaze B2, Google Cloud Storage, or another remote destination.
Common WordPress Installation Problems
“Error establishing a database connection”
This usually means one of the following:
- MariaDB is not running.
- The database name, username, or password in
wp-config.phpis wrong. - The database user lacks privileges.
- SELinux is blocking the connection.
Check the service:
sudo systemctl status mariadb
Test credentials:
mariadb -u wordpress_user -p
Review SELinux denials:
sudo ausearch -m avc -ts recent
WordPress shows the Apache test page
Apache is serving /var/www/html instead of your WordPress document root. Confirm that:
sudo apachectl -S
The output should show your domain pointing to /var/www/wordpress. If it does not, check for conflicting virtual hosts in /etc/httpd/conf.d/ and ensure your configuration file is loaded.
Permalinks return 404 errors
WordPress permalink rewriting is not working. Confirm AllowOverride All is present in the virtual host, then refresh permalinks:
cd /var/www/wordpress
sudo -u apache wp rewrite flush
Also verify that mod_rewrite is enabled:
sudo httpd -M | grep rewrite
Plugin installation asks for FTP credentials
PHP cannot write to the WordPress directory. Check ownership:
ls -ld /var/www/wordpress /var/www/wordpress/wp-content
Correct it if necessary:
sudo chown -R apache:apache /var/www/wordpress
Confirm FS_METHOD is set to direct in wp-config.php.
Uploads fail with “Unable to create directory”
The uploads folder is missing or has the wrong ownership:
sudo mkdir -p /var/www/wordpress/wp-content/uploads
sudo chown -R apache:apache /var/www/wordpress/wp-content/uploads
sudo restorecon -Rv /var/www/wordpress/wp-content/uploads
White screen after a plugin update
Enable WordPress debugging temporarily in wp-config.php:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
Check:
tail -f /var/www/wordpress/wp-content/debug.log
Deactivate the suspect plugin with WP-CLI:
wp plugin deactivate plugin-slug