How To Set Up Multiple WordPress Installations on a Single Ubuntu Server
Reference :
- https://www.digitalocean.com/community/tutorials/how-to-set-up-multiple-wordpress-sites-on-a-single-ubuntu-vps
Install LEMP
Install Nginx
sudo apt-get install nginx sudo apt-get install nginx-extras curl http://localhost
Install MySQL
sudo apt-get update sudo apt-get install mysql-server
Install PHP
sudo apt-get update sudo apt-get install php-fpm php-mysql php-mbstring php-mcrypt php-xml php-gd php-ssh2 php-curl sudo apt-get install php-cli php-cgi sudo service php7.0-fpm restart
Setup MySql
Setup MySQL for the first time
sudo /usr/bin/mysql_secure_installation The prompt will ask you for your current root password. Enter password for user root: VALIDATE PASSWORD PLUGIN can be used to test passwords and improve security. It checks the strength of password and allows the users to set only those passwords which are secure enough. Would you like to setup VALIDATE PASSWORD plugin? Press y|Y for Yes, any other key for No: y There are three levels of password validation policy: LOW Length >= 8 MEDIUM Length >= 8, numeric, mixed case, and special characters STRONG Length >= 8, numeric, mixed case, special characters and dictionary file Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 2 Estimated strength of the password: 50 Change the password for root ? ((Press y|Y for Yes, any other key for No) : y New password: Re-enter new password: Estimated strength of the password: 100 Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y By default, a MySQL installation has an anonymous user, allowing anyone to log into MySQL without having to have a user account created for them. This is intended only for testing, and to make the installation go a bit smoother. You should remove them before moving into a production environment. Remove anonymous users? (Press y|Y for Yes, any other key for No) : y Success. Normally, root should only be allowed to connect from 'localhost'. This ensures that someone cannot guess at the root password from the network. Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y Success. By default, MySQL comes with a database named 'test' that anyone can access. This is also intended only for testing, and should be removed before moving into a production environment. Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y - Dropping test database... Success. - Removing privileges on test database... Success. Reloading the privilege tables will ensure that all changes made so far will take effect immediately. Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y Success. All done!
Setup WordPress
1. Create Site Databases and Users
For the purposes of this guide, we will be using the following information:
domain1.com
site name : Domain 1
db name : domain1_wp
db user : domain1_user
db pass : password
domain2.com
site name : Domain 2
db name : domain2_wp
db user : domain2_user
db pass : password
a. Log into MySQL using the administrator account you configured during the MySQL installation:
mysql -u root -p
b. Execute the mysql commands :
CREATE DATABASE domain1_wp; CREATE USER [email protected] IDENTIFIED BY 'password'; // SET PASSWORD FOR [email protected]= PASSWORD("password"); GRANT ALL PRIVILEGES ON domain1_wp.* TO [email protected] IDENTIFIED BY 'password'; CREATE DATABASE domain2_wp; CREATE USER [email protected] IDENTIFIED BY 'password'; // SET PASSWORD FOR [email protected]= PASSWORD("password"); GRANT ALL PRIVILEGES ON domain2_wp.* TO [email protected] IDENTIFIED BY 'password'; FLUSH PRIVILEGES; exit # Drop Database DROP DATABASE domain1_wp; # Drop user DROP USER [email protected]'%'; DROP USER [email protected]'localhost'; # Show users SELECT user from mysql.user; # Show grants SHOW GRANTS FOR 'domain1_user'@'localhost';
2. Download WordPress and decompress the archive
sudo wget http://wordpress.org/latest.tar.gz or curl -O https://wordpress.org/latest.tar.gz tar -xzvf latest.tar.gz
3. Go to extracted wordpress archive and create the configuration from the sample configuration file.
sudo cp wordpress/wp-config-sample.php wordpress/wp-config.php
4. Configuring Site Root Directories
a. Create a new root document
sudo mkdir -p /var/www/html
b. Create the directories for your wordpress site
sudo mkdir /var/www/html/domain1.com sudo mkdir /var/www/html/domain1.com
c. Copy the extracted wordpress files to your site
sudo rsync -avP wordpress/ /var/www/html/domain1.com/ sudo rsync -avP wordpress/ /var/www/html/domain1.com/
d. Give ownership of the directories to the Apache web user and then add your linux username to the web group:
sudo chown www-data:www-data /var/www/html/domain1.com -R sudo chown www-data:www-data /var/www/html/domain2.com -R sudo usermod -a -G www-data
5. WordPress Configuration
a. Update the wordpress config file
sudo nano /var/www/html/domain1.com/wp-config.php
Find the section that contains the fields below and substitute the database, username, and password for your site:
// ** MySQL settings - You can get this info from your web host ** // /** The name of the database for WordPress */ define('DB_NAME', 'domain1_wp'); /** MySQL database username */ define('DB_USER', 'domain1_user'); /** MySQL database password */ define('DB_PASSWORD', 'password');
// same goes for the 2nd site
// ** MySQL settings - You can get this info from your web host ** // /** The name of the database for WordPress */ define('DB_NAME', 'domain2_wp'); /** MySQL database username */ define('DB_USER', 'domain2_user'); /** MySQL database password */ define('DB_PASSWORD', 'password'); /** Updates from WordPress Admin Panel */ define('FS_METHOD','direct'); define('AUTH_KEY', 'YOUR_KEY_HERE'); define('SECURE_AUTH_KEY', 'YOUR_KEY_HERE'); define('LOGGED_IN_KEY', 'YOUR_KEY_HERE'); define('NONCE_KEY', 'YOUR_KEY_HERE'); define('AUTH_SALT', 'YOUR_KEY_HERE'); define('SECURE_AUTH_SALT', 'YOUR_KEY_HERE'); define('LOGGED_IN_SALT', 'YOUR_KEY_HERE'); define('NONCE_SALT', 'YOUR_KEY_HERE');
6. WordPress needs an extra PHP module installed in order to function correctly.
sudo apt-get update sudo apt-get install php5-gd libssh2-php or # php-7 $ sudo apt-get install php-gd php-ssh2
Setup Nginx (Modify Nginx Server Blocks)
References :
* https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-with-nginx-on-ubuntu-14-04
* https://www.digitalocean.com/community/tutorials/how-to-set-up-nginx-server-blocks-virtual-hosts-on-ubuntu-14-04-lts
* https://www.digitalocean.com/community/tutorials/how-to-configure-single-and-multiple-wordpress-site-settings-with-nginx
Create the NGINX .conf files
1. Create a directory for global configurations under /etc/nginx/global.
* common.conf: Configurations applicable to all sites.
* wordpress.conf: Configurations applicable to all WordPress sites.
* multisite.conf: Special configurations for WordPress multisite with sub-directories.
sudo mkdir /etc/nginx/global
2. Create the common.conf file
sudo nano /etc/nginx/global/common.conf ## Copy the following configurations # Global configuration file. # ESSENTIAL : Configure Nginx Listening Port listen 80; # ESSENTIAL : Default file to serve. If the first file isn't found, index index.php index.html index.htm; # ESSENTIAL : no favicon logs location = /favicon.ico { log_not_found off; access_log off; } # ESSENTIAL : robots.txt location = /robots.txt { allow all; log_not_found off; access_log off; } # ESSENTIAL : Configure 404 Pages error_page 401 403 404 /404.html; # ESSENTIAL : Configure 50x Pages error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # SECURITY : Deny all attempts to access hidden files .abcde location ~ /\. { deny all; } # PERFORMANCE : Set expires headers for static files and turn off logging. location ~* ^.+\.(js|css|swf|xml|txt|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ { access_log off; log_not_found off; expires 30d; } ## Save and exit - Ctrl-O, Ctrl-X
3. Create the wordpress.conf file
sudo nano /etc/nginx/global/wordpress.conf ## Copy the following configurations # WORDPRESS : Rewrite rules, sends everything through index.php and keeps the appended query string intact location / { try_files $uri $uri/ /index.php?q=$uri&$args; } # SECURITY : Deny all attempts to access PHP Files in the uploads directory location ~* /(?:uploads|files)/.*\.php$ { deny all; } # Prevent XML-RPC Attacks : Deny all attempts to access the xmlrpc.php location = /xmlrpc.php { deny all; } # REQUIREMENTS : Enable PHP Support location ~ \.php$ { # SECURITY : Zero day Exploit Protection # for php5 try_files $uri =404; # ENABLE : Enable PHP, listen fpm sock fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; # for php-7 include snippets/fastcgi-php.conf; # With php7.0-cgi alone: # fastcgi_pass 127.0.0.1:9000; # With php7.0-fpm: fastcgi_pass unix:/run/php/php7.0-fpm.sock; } # PLUGINS : Enable Rewrite Rules for Yoast SEO SiteMap rewrite ^/sitemap_index\.xml$ /index.php?sitemap=1 last; rewrite ^/([^/]+?)-sitemap([0-9]+)?\.xml$ /index.php?sitemap=$1&sitemap_n=$2 last; ## Save and exit - Ctrl-O, Ctrl-X
4. Create the server block files for your wordpress site
sudo nano /etc/nginx/sites-available/domain1.conf ## Copy the following ## Same goes for your other wordpress site ## root = this is the root folder of your wordpress installation ## server_name = this is the domain name of your site ## Depending on your DNS provider route your wordpress sites accordingly server { #listen 80; root /var/www/html/domain1.com; index index.php index.html index.htm; server_name domain1.com; include global/common.conf; include global/wordpress.conf; } ## Save and exit - Ctrl-O, Ctrl-X
5. Update the /etc/nginx/nginx.conf
# Add the following to http (add at the end) http : { client_max_body_size 32M; }
6. Enable the wordpress site
sudo ln -s /etc/nginx/sites-available/domain1.conf /etc/nginx/sites-enabled/ sudo ln -s /etc/nginx/sites-available/domain2.conf /etc/nginx/sites-enabled/ # (Optional) Disable the default nginx server block sudo rm /etc/nginx/sites-enabled/default
7. To check your Nginx configuration
# You can use this command to troubleshoot your configuration if there is something wrong. $ sudo nginx -t
8. Restart the web server and PHP processor.
sudo service nginx restart sudo service php5-fpm restart # php-7 sudo service nginx php7.0-fpm restart
Secure NGINX
1. Update /etc/nginx/nginx.conf and apply the SSL Ciphers
http { ... # ----------------------- # Max Body Size # ----------------------- client_max_body_size 20M; # ----------------------- # SSL Protocol | Ciphers # ----------------------- ssl_protocols TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!3DES'; ... }
2. Update your wordpress server block
sudo nano /etc/nginx/sites-available/domain2.conf server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; server_name _; root /var/www/domain2.com; index index.php index.html index.htm; # ---------------- # SSL # ---------------- listen 443 ssl; ssl_certificate /etc/ssl/ssl_certificate; ssl_certificate_key /etc/ssl/private_key; # ---------------- # Redirect to HTTPS # ---------------- if ($scheme = 'http') { return 301 https://$host$request_uri; } # ---------------- # HSTS # ---------------- add_header Strict-Transport-Security 'max-age=31536000'; # ---------------- # Enable SiteMap # ---------------- #Yoast SEO Sitemaps location ~ ([^/]*)sitemap(.*).x(m|s)l$ { rewrite ^/sitemap.xml$ /sitemap_index.xml permanent; rewrite ^/([a-z]+)?-?sitemap.xsl$ /index.php?xsl=$1 last; rewrite ^/sitemap_index.xml$ /index.php?sitemap=1 last; rewrite ^/([^/]+?)-sitemap([0-9]+)?.xml$ /index.php?sitemap=$1&sitemap_n=$2 last; rewrite ^/news-sitemap.xml$ /index.php?sitemap=wpseo_news last; rewrite ^/locations.kml$ /index.php?sitemap=wpseo_local_kml last; rewrite ^/geo-sitemap.xml$ /index.php?sitemap=wpseo_local last; rewrite ^/video-sitemap.xsl$ /index.php?xsl=video last; } include conf.prod/common.conf; include conf.prod/wordpress.conf; }
Update WordPress – PHP Config
To increase the file upload limit for WordPress. * Update the php.ini file sudo nano /etc/php5/fpm/php.ini # Php 7 sudo nano /etc/php/7.0/fpm/php.ini Set the following configurations : upload_max_filesize = 32M post_max_size = 16M memory_limit = 128M file_uploads = On max_execution_time = 60
Backup WordPress
references : https://codex.wordpress.org/Backing_Up_Your_WordPress_Files
Backup MySql Databases
1. Execute the command
sudo mysqldump -u root -p --all-databases > all_databases.sql # Enter your mysql root password Backup WordPress files * By default, you can backup the whole wordpress installation. If you want to backup only your own user-generated content, such as edited themes, new plugins, and uploaded files Backup the /wp-content and the wp-config.php $ sudo cp -R /var/www/html/domain1.com/wp-content /home/ubuntu/wordpress/backup/backup_20160630 $ sudo cp /var/www/html/domain1.com/wp-config.php /home/ubuntu/wordpress/backup/backup_20160630
Restoring WordPress
Restore the MySql Databases
1. Execute the command
sudo mysql -u root -p < all_databases.sql # Single Database sudo mysql -u root -p wp-fourd < db_backup.dump
2. Include again the privileges for the Users of every database
a. Log into MySQL using the administrator account you configured during the MySQL installation:
$ mysql -u root -p
b. Execute the mysql commands :
FLUSH PRIVILEGES; exit
3. Copy the wordpress backup files.
* If you backup the whole wordpress site. Just setup your nginx server blocks.
* If you backup just the /wp-content and the wp-config.php, Download again the latest WordPress (see Setup WordPress at the top) and copy the wp-content to the wordpress
WP Content
domain1.com/wp-content
domain2.com/wp-content
sudo rsync -avP domain1.com/ /var/www/domain1.com/
sudo rsync -avP domain2.com/ /var/www/domain2.com/
Other Needed Libraries
sudo apt-get install php5-curl # See installed packages dpkg --list # See running services service --status-all ------------ PHP-5.6 ------------ sudo add-apt-repository ppa:ondrej/php sudo apt-get update sudo apt-get install php5.6-fpm php5.6-mbstring php5.6-mcrypt php5.6-mysql php5.6-xml php5.6-gd php5.6-ssh2 php5.6-curl sudo service nginx php5.6-fpm restart sudo nano /etc/nginx/conf.prod/wordpress.conf # REQUIREMENTS : Enable PHP Support location ~ \.php$ { # SECURITY : Zero day Exploit Protection # for php5 try_files $uri =404; # ENABLE : Enable PHP, listen fpm sock fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php5.6-fpm.sock; fastcgi_index index.php; include fastcgi_params; } ------------ PHP-7.1 ------------ sudo add-apt-repository ppa:nginx/stable sudo add-apt-repository ppa:ondrej/php sudo apt-get update sudo apt-get install php-fpm php-mbstring php-mcrypt php-mysql php-xml php-gd php-ssh2 php-curl sudo apt-get install php-cli php-cgi sudo service nginx php7.1-fpm restart sudo nano /etc/nginx/conf.prod/wordpress.conf # REQUIREMENTS : Enable PHP Support location ~ \.php$ { # SECURITY : Zero day Exploit Protection try_files $uri =404; # ENABLE : Enable PHP, listen fpm sock fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php7.1-fpm.sock; fastcgi_index index.php; include fastcgi_params; }