WordPress is on of the most used CMS (content management system) that allows user to create blogs, e-commerce sites, portfolio, news site, headless servers and many more. WordPress needs a web server (Apache, Nginx, LiteSpeed), database (MariaDB, MySQL) and PHP.
In this tutorial we are going to deploy multiple WordPress sites on WebDock. WebDock is a fast and cheap VPS provider that fits everyone’s need and provides semi managed and ummanged VPS servers. WebDock provides their own control panel where you can manage your VPS servers like, installing LEMP stack, WordPress, phpMyAdmin, MonogDB, CertBot, FTP etc. Hence I described it as semi managed. But the problem is their control panel does not support multiple WordPress installations and they suggest to have single site per server. This is the reason this tutorial about installing multiple WordPress with LEMP in a single VPS server exists.
Create a Server
Create a new server and select Clean OS
instead of The Perfect Server
. Since WebDock does not support multiple sites in a single server we should manage our server ourselves to avoid accidental changes from WebDock control panel. And this is they way I recommend if you want to have multiple sites or web apps in your VPS. A web server can run at 512 MB RAM too but I recommend to have at least 2 GB of RAM for multiple WordPress sites.
WebDock only supports Ubuntu for now hence we will get Ubuntu Focal 20.4 as our server. Give a name and slug and spin up your server.
Congratulations you have your server running and ready to deploy our site.
Setup SSH
At bottom of the dashboard click on add shell user
then provide username and password and press ADD USER
. You don’t need to change other options and you should not if you don’t know what are you doing.
After adding user to your server you need to login to the server in order to make changes and to do so you need to add SSH key first. SSH is generated in you local machine and a copy of public key is uploaded to server so that server knows who is trying to connect.
Generate SSH Key
To create SSH key, in your local machine in terminal use ssh-keygen
.
~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):
If you already have SSH key then a overwrite message will be shown and you don’t need to create a new key. Then it will ask for passphrase. Adding passphrase is recommended.
~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_rsa
Your public key has been saved in /home/user/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:6H5M8HkmTD1BPkPCA67a8CdWR7KKx8b4kN6fTMndQhQ
user@myPc
The key's randomart image is:
+---[RSA 3072]----+
| .oE.o |
| . o=. |
| o oo+. |
| ..<em>. oo | | . . +=S. . | | @ = =</em>.o |
| * @ *oo+. |
| . B * .o. |
| . o.=. |
+----[SHA256]-----+
This is what you see after completing generating SSH key.
Copy Public Key
As our key is saved in ~/.ssh/id_rsa.pub
we can get public key using cat
.
~$ cat ~/.ssh/id_rsa.pub
It will give result like this;
~$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7DFwx4hgyBKvhqd5ss56YIhU2PMgO1NEQ4Kln8dnHit6eLF4HKzCPfsIhkeWUGu4VdqS4Zg+U04Xvx/TG1z3N9klnvV7pHeZaxGciUT8+Ii6YUWosBUX/Ki8ZfC+QgmzkGmQwIefXzxOMijqa1j7CJH8JFigQYCw9B6LIwNhageQjPyPy68ido/XDuqI1xtbr/aJcuYxE2IHVzsNzMAoJlNEVjrhwTp0y78bWW2RodftPPNT670MwrFfiP+iqck1zQ/n+VwB9wW67cFlE/HX6Invc13i/psjn6UJcpKEDW3tHvvpX6Y/Nik79dSSTAX9lAAuOKwe3VJ6YQBSPpE0JInVE0veO+xEJkTnXz+kUWgQQT+PxfHSIE63v0mIAiPTW3WnFkZkjW23BZX+2Tty6xPyHuXJGtaiyyaZ+F4/A51jZ3yXR2G7pLOy9PdeDl1j3Doy466UX86p0zpPEG5KpRuis/JMve5vvPQBwppoBHCQTdkb2ApvA2XL3vtxoMyk= user@myPc
Copy all the output content and save to WebDock.
Then assign key to the user.
Login to Server using SSH
We can get server IP address from the servers list.
To login into server using SSH;
~$ ssh admin@45.148.30.37
Install LEMP Stack
L: We already installed Linux.
Install Nginx (pronounce as Engine-X)
admin@webdocktutor:~$ sudo apt update
admin@webdocktutor:~$ sudo apt install nginx
Browse to your IP http://your_ip_address
, for me it is http://45.148.30.37
. We can see nginx Welcome page. Which means nginx is installed correctly.
Install MariaDB
MariaDB or MySQL can be installed for database used by WordPress.
admin@webdocktutor:~$ sudo apt install mariadb-server
After installing we need to setup MariaDB for the first time.
admin@webdocktutor:~$ sudo mysql_secure_installation
Create new root password and select yes for other options.
Create new user and database for WordPress site. Login into mariadb.
admin@webdocktutor:~$ sudo mariadb
Now create wordpress1
user and wordpress2
user for 2 WordPress installation. If you don’t want to install 2 WordPress sites you don’t need to create wordpress2
user. You can have your own names and don’t need to have exact wordpress
name. Don’t forget ;
after sql
command. If you forgot ;
and have pressed enter, MySQL shell will go to new line. You can enter forgotten ;
and hit enter again to continue.
MariaDB [(none)]> CREATE DATABASE wordpress1;
MariaDB [(none)]> CREATE DATABASE wordpress2;
To view newly created database you can use SHOW DATABASES
command.
MariaDB [(none)]> SHOW DATABASES;
Create new users for wordpress1
and wordpress2
databases.
MariaDB [(none)]> GRANT ALL ON wordpress1.* TO 'wordpress1user'@'localhost' IDENTIFIED BY 'password1' WITH GRANT OPTION;
MariaDB [(none)]> GRANT ALL ON wordpress2.* TO 'wordpress2user'@'localhost' IDENTIFIED BY 'password2' WITH GRANT OPTION;
We created users wordpress1user
and wordpress2user
and gave them full privileges to their respective databases wordpress1
and wordpress2
. You can always have users and database as your own choice. For example, you can give wordpress1user
access to both database without need to create wordpress2user
. But for security we created users for each databases.
Keep these root password, usernames and passwords at safe place. We need it later and also we may need in future.
Flush the privileges to ensure that they are available in the current session.
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> exit;
Login again to MariaDB and see databases if they are available or not. They should appear.
admin@webdocktutor:~$ sudo mariadb
MariaDB [(none)]> SHOW DATABASES;
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| wordpress1 |
| wordpress2 |
+--------------------+
5 rows in set (0.001 sec)
It is not necessary to write sql command in all capital letters. To exit;
MariaDB [(none)]> exit;
Install PHP
Nginx uses php-fpm to process PHP. Install php-fpm
and php-mysql
:
admin@webdocktutor:~$ sudo apt install php-fpm php-mysql
So LEMP stack is installed. Now we need to setup nginx to run php. By default it is does not run php.
Configure NGINX to use PHP-FPM
In nginx config file there are server blocks that defines web servers. These server blocks need domain name to work. WebDock gives a subdomain for all servers and in my case it is webdocktutor.vps.webdock.io
. You can find yours in sever overview page named as alias.
You can use this domain name to test your nginx configuration.
All web files are saved inside /var/www/
and here is html
folder inside it which we already seen by browsing our IP address http://ip-address
.
In this tutorial I am assuming that we have domain names, mycoolsite.com
and mycoolblog.com
. So all configuration from now will be based on these 2 domain names.
For our 2 WordPress sites, create 2 folders with the same name as our domain names, which is, mycoolsite.com
and mycoolblog.com
. So that our new directories are /var/www/mycoolsite.com/
and /var/www/mycoolblog.com/
. Inside those directories we will place WordPress files and setup nginx config to server them.
Configure NGINX config file for multiple sites
Nginx saves all config in /etc/nginx/nginx.conf
but as we are in Ubuntu server config files are available in separate folder to match Apache config directories. Generally all available sites/servers config files are kept inside /etc/nginx/sites-available/
and to enable those sites symbolic link to available sites must be added to /etc/nginx/sites-enabled/
.
If you take a look at /etc/nginx/sites-available/
you will find a file named default
which is responsible to serve files under /var/www/html/
. So what we need to do to setup our WordPress sites? Well, we will remove the symbolic link of default
from /etc/nginx/sites-enabled/
and create our own config file then create a link.
To remove default
site use:
admin@webdocktutor:~$ sudo rm /etc/nginx/sites-enabled/default
This will remove symbolic link but not the actual config file under /etc/nginx/sites-available/
and that is how is should be done.
Now create a new config file to make WordPress (PHP) working:
admin@webdocktutor:~$ sudo nano /etc/nginx/snippets/wordpress.conf
And put this inside wordpress.conf
:
# /etc/nginx/snippets/wordpress.conf
# this should be used inside server block
index index.php;
location / {
# try to serve static file if not found then directory then php
# include the "?$args" part so non-default permalinks doesn't break when usi>
try_files $uri $uri/ /index.php?$args;
}
# php-fpm
location ~ \.php$ {
include fastcgi_params;
# you may need to change this fastcgi_pass to match your php version
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_intercept_errors on;
# The following parameter can be also included in fastcgi_params file
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# favicon.ico
location = /favicon.ico {
log_not_found off;
access_log off;
}
# robots.txt related
location = /robots.txt {
# wordpress dynamically generates robots.txt
try_files $uri $uri/ /index.php?$args;
allow all;
log_not_found off;
access_log off;
}
# sitemap related
location ~* \.(xml|xsl)$ {
# wordpress dynamically generates sitemap.xml
try_files $uri $uri/ /index.php?$args;
log_not_found off;
access_log off;
}
# static assets caching
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
# RESTRICTIONS
# Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
location ~ /\. {
deny all;
}
# Deny access to any files with a .php extension in the uploads directory
# Works in sub-directory installs and also in multisite network
# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
location ~* /(?:uploads|files)/.*\.php$ {
deny all;
}
You may need to have a look in location ~ \.php$ {}
block since it may be different in your setup. Because it is for php7.4
.
Now we need to create virtual host and use above config. To create virtual hosts for our 2 different domain names create config files inside sites-available
folder.
admin@webdocktutor:~$ sudo nano /etc/nginx/sites-available/mycoolsite.com
Then pust this config:
server {
root /var/www/mycoolsite.com;
server_name mycoolsite.com;
listen 80;
listen [::]:80;
# WordPress core
include snippets/wordpress/wordpress.conf;
}
Similarly for another domain name:
admin@webdocktutor:~$ sudo nano /etc/nginx/sites-available/mycoolblog.com
server {
root /var/www/mycoolblog.com;
server_name mycoolblog.com;
listen 80;
listen [::]:80;
# WordPress core
include snippets/wordpress/wordpress.conf;
}
So now when you browse these domains it will try to server the content from directory specified as root
. If you browse you domains now you will get 404 not found
error since we haven’t placed anything in those directories.
Now it’s time to install WordPress. Navigate to /tmp
directory and download WordPress.
cd /tmp
wget https://wordpress.org/latest.tar.gz
Extract the files:
tar -zxvf latest.tar.gz
Change files permission to www-data
user/group so that we won’t get any permission error when using WordPresss.
sudo chown -R www-data:www-data wordpress
Now opy files to /var/www/mycoolsite.com
and /var/www/mycoolblog.com
sudo cp -a wordpress/. /var/www/mycoolsite.com/
sudo cp -a wordpress/. /var/www/mycoolblog.com/
Now create a symlink from sites-available
to sites-enabled
.
sudo ln -s /etc/nginx/sites-available/mycoolblog.com /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/mycoolsite.com /etc/nginx/sites-enabled/
Check nginx configuration:
sudo nginx -t
If everything is ok reload nginx:
sudo nginx -s reload
Install Let’s Encrypt SSL
Make sure you have already installed certbot
, if not then install from here – https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal. From the dropdown you can select different OS than Ubuntu. We are going to manually config our SSL so only get the certificates we needed. certbot
will prompt domain names select them and continue.
sudo certbot certonly --nginx
After successfully getting certificate from cerbot
command it will provide you certificates /etc/letsencrypt/live/mycoolsite.com/fullchain.pem
and /etc/letsencrypt/live/mycoolsite.com/privkey.pem
. After than we need to use those with Nginx. Open the config file we previously created for each sites, e.g. /etc/nginx/sites-available/mycoolsite.com
. And config SSL like this.
server {
root /var/www/mycoolsite.com;
server_name mycoolsite.com;
listen 80;
listen [::]:80;
# WordPress core
include snippets/wordpress/wordpress.conf;
# SSL
ssl_certificate /etc/letsencrypt/live/mycoolsite.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mycoolsite.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
Now visit those domains/urls, mycoolblog.com
and mycoolsite.com
you will find WordPress installation screen. Provide necessary info, database name, username, password we have created previously.
I hope you find this aricle helpful.
Can you please update this post
Nice