If you want to run single WordPress site, best to use a WordPress hosting offer. If you want to run 5 WordPress sites, it is often more economical to get a VPS and configure multi-site. But you will face much more install and admin work, especially if you avoid using tools like Plesk etc.
On a fresh Debian 10 server install, I started with:
apt update; apt upgrade —> set timezone timedatectl set-timezone Europe/Berlin —> verify status of timers systemctl list-timers —> install zip & unzip for Duplicator (WordPress plugin) apt install zip unzip
Make sure to run:
apt update apt list --upgradable
regularly and then decide what to do. On a Debian server install, unattended updates are disabled.
Next install webserver and php. I opted for nginx and php-fpm.
apt install nginx —> test install nginx -t —> install PHP with FPM and modules for WordPress apt install php-fpm php-mysql php-curl php-xml php-gd php-mbstring php-zip —> fix nginx gateway timeout 504 error for Duplicator vi /etc/nginx/snippets/fastcgi-php.conf fastcgi_read_timeout 900;
Next install and configure the database engine. Here I opted for MariaDB.
—> install and secure MariaDB
apt install mariadb-server
mysql_secure_installation
—> create databases and database accounts for WordPress
for each site do (check the quotes !!)
CREATE DATABASE site1_db;
GRANT ALL ON site1_db.* TO ‘site1_user’@‘127.0.0.1’ IDENTIFIED BY ‘site1_pw’;
FLUSH PRIVILEGES;
—> check database login
mariadb -u site1_user -h 127.0.0.1 -p (and enter site1_pw)
SHOW DATABASES;
—> verify all database accounts
mariadb (as root)
SELECT user,authentication_string,plugin,host FROM mysql.user;
—> My MariaDB updated settings for WordPress
vi /etc/mysql/mariadb.conf.d/50-server.cnf
bind-address = 127.0.0.1
innodb_buffer_pool_size = 512M
query_cache_size = 64M
MariaDB defaults to unix permissions for root logins (using the unix_socket plugin). So no need to set a root password on MariaDB, just run mariadb as root. I also use 127.0.0.1 instead of localhost for the accounts, to avoid any issues with ipv6, dual stack etc. Make sure to set bind-address to 127.0.0.1 as well.
This is my nginx config for site1. You need one for site2 as well. nginx configs go into /etc/nginx/sites-available with softlinks from /etc/nginx/sites-enabled. Https is not yet enabled, certbot takes care of that later.
server { listen [::]:80; listen 80; #include snippets/ssl-params.conf; root /var/www/site1; index index.php; server_name site1.com www.site1.com; location / { # First attempt to serve request as file, then as directory try_files $uri $uri/ /index.php?$args; } # pass PHP scripts to FastCGI server location ~ \.php$ { include snippets/fastcgi-php.conf; # with php-fpm socket fastcgi_pass unix:/run/php/php7.3-fpm.sock; } location ~ /\.ht { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { log_not_found off; access_log off; allow all; } location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { expires max; log_not_found off; } }
Now you can create the root directories for each site and do some tests.
mkdir /var/www/site1 mkdir /var/www/site2 —> test PHP vi /var/www/site1/info.php <?php phpinfo(); —> set ownership chown -R www-data:www-data /var/www/site1 /var/www/site2
For now, I set website file and directory ownership to www-data, basically the default security model where both nginx and php-fpm run as user www-data. I’ve described a more secure solution for multi-site here.
Next step is getting a free Letsencrypt certificate and setup https with Certbot as snap. I decided to use the snap version of certbot instead of the certbot package from debian. That way, certbot is not impacted by debian updates, since the snap provides a containerised environment for certbot.
apt install snap snap install core; snap refresh core snap install --classic certbot ln -s /snap/bin/certbot /usr/bin/certbot —> show all snaps snap list —> get and install certificates for each site certbot --nginx —> test renewal without changing anything certbot renew --dry-run —> show certificates certbox certificates —> renewal timer check systemctl list-timers
The certbot command will change and configure each nginx config file to https and add a redirect from http to https. Time to test again and verify the certificate in your browser.
Next up, download and copy WordPress to site1 and site2.
wget https://wordpress.org/latest.tar.gz tar -xzvf latest.tar.gz cd wordpress cp -R * /var/www/site1 cp -R * /var/www/site2 chown -R www-data:www-data /var/www/site1 /var/www/site2
You can start the WordPress install by accessing it at https://site1.com/wp-admin/install.php for site1 and at https://site2.com/wp-admin/install.php for site2.
Since you’re running a https site already, WordPress will configure your site with https. Your site should now score A+ on the SSL Labs test with the default certbot settings…