This is how I set up a dedicated Debian subdomain (VM), Installed MySQL 14 and connected to it from a WordPress installation on a different VM
Aside
If you have not read my previous posts I have now moved my blog to the awesome UpCloud host (signup using this link to get $25 free UpCloud VM credit). I compared Digital Ocean, Vultr and UpCloud Disk IO here and UpCloud came out on top by a long way (read the blog post here). Here is my blog post on moving fearby.com from Vultr to UpCloud.
Buy a domain name here
Now on with the post.
Fearby.com
I will be honest, fearby.com is my play server where I can code, learn about InfoSec and share (It’s also my stroke rehab blog).
There is no faster way to learn than actually doing. The problem is my “doing” usually breaks the live site from time to time (sorry).
I really need to set up a testing environment (DEV-TEST-LIVE or GREEN-BLUE) server(s). GREEN-BLUE has advantages as I can always have a hot spare ready. All I need to do is toggle DNS and I can set the GREEN or BLUE server as the live server.
But first I need to separate my database from my current fearby.com server and setup up a new web server. Having a Green and Blue server that uses one database server will help with near real-time production website switches.
Dedicated Database Server
I read the following ( Should MySQL and Web Server share the same server? ) at Percona Database Performance Blog. Having a separate database server should not negatively impact performance (It may even help improve speeds).
Deploy a Debian VM (not Ubuntu)
I decided to set up a Debian server instead of Ubuntu (mostly because of the good focus on stability and focus on security within Debian).
I logged into the UpCloud dashboard on my mobile phone and deployed a Debian server in 5 mins. I will be using my existing how to setup Ubuntu on UpCloud guide (even though this is Debian).
TIP: Sign up to UpCloud using this link to get $25 free UpCloud VM credit.
Deploy a Debian server setup steps:
- Login to UpCloud and go to Create server.
- Name your Server (use a fully qualified domain name)
- Add a description.
- Choose your data centre (Chicago for me)
- Choose the server specs (1x CPU, 50GB Disk, 2GB Memory, 2TB Traffic for me)
- Name the Primary disk
- Choose an operating system (Debian for me)
- Select an SSH Key
- Choose misc settings
- Click Deploy server
After 5 mins your server should be deployed.
After Deploy
Setup DNS
Login to your DNS provider and create DNS records to the new IP’s (IPv4 and IPv6) provided by UpCloud. It took DNS 12 hours to replicate to my in Australia.
Setup a Firewall (at UpCloud)
I would recommend you set up a firewall at UpCloud as soon as possible (don’t forget to add the recommended UpCloud DNS IP’s and any whitelisted IP’s your firewall).
Block everything and only allow
- Port 22: Allow known IP(s) of your ISP or VPN.
- Port 53: Allow known UpCloud DNS servers
- Port 80 (ALL)
- Port 443 (ALL)
- Port 3306 Allow your WordPress site and known IP(s) of your ISP or VPN.
Read my post on setting up a whitelisted IP on an UpCloud VM… as it is a good idea.
UpCloud thankfully has a copy firewall feature that is very handy.
After I set up the firewall I SSH’ed into my server (I use vSSH on OSX buy you could use PUTTY).
I updated the Debian system with the following command
Get the MySQL Package
Visit http://repo.mysql.com/ and get the URL of the latest apt-config repo deb file (e.g “mysql-apt-config_0.8.9-1_all.deb”). Make a temp folder.
Download the MySQL deb Package
Install the package
Update the system again
Install MySQL on Debian
Secure MySQL
You can secure the MySQL server deployment (set options as needed)
Install NGINX
I installed NGINX to allow Adminer MySQL GUI to be used
I ran these commands to install NGINX.
I edited my NGINX configuration as required.
I reloaded NGINX
Install PHP
I followed this guide to install PHP on Debian.
Install PHP FPM
Increase Upload Limits
You may need to temporarily increase upload limits in NGINX and PHP before you can restore a WordPress database. My feabry.com blog is about 87MB.
Add “client_max_body_size 100M;” to “/etc/nginx/nginx.conf”
Add the following to “/etc/php/7.2/fpm/php.ini”
- post_max_size = 100M
- upload_max_filesize = 100M
Restore a backup of my MySQL database in MySQL
You can now use Adminer to restore your blog to MySQL. Read my post here on Adminer here. I used Adminer to move my WordPress site from CPanel to a self-managed server a year ago.
First login to your source server and export your desired database then login to the target server and import the database.
Firewall Check
Don’t forget to allow your WordPress site’s 2x Public IP’s and 1x Private IP to access port 3306 in your UpCloud Firewall.
How to check open ports on your current server
Set MySQL Permissions
Open MySQL
I ran these statements to grant the user logging in on the nominate IP’s access to MySQL.
Reload permissions in MySQL
Allow access to the Debian machine from known IP’s
Edit “/etc/host.allow”
Additions (known safe IP’s that need access to this MySQL remotely).
Tell MySQL to listen on
Edit “/etc/mysql/my.cnf”
Added..
I guess you could change the port to something random???
Restart MySQL
Install a second local firewall on Debian
Install ufw
Do add the IP of your desired server or VPN to access SSH
Do add the IP of your desired server or VPN to access WWW
Now add the known IP’s (e.g any web servers public (IPv4/IPv6) or Private IP’s) that you wish to grant access to MySQL (e.g the source website that used to have MySQL)
Do add UpCloud DNS Servers to your firewall
Add all other rules as needed (if you stuff up and lock your self out you can login to the server with the Console on UpCloud)
Restart the ufw firewall
Prevent MySQL starting on the source server
Now we can shut down MySQL on the source server (leave it there just in case).
Edit “/etc/init/mysql.conf”
Comment out the line that contains “start on ” and save the file
and run
Reboot
Stop and Disable NGINX on the new DB server
We don’t need NGINX running now the database has been imported with Adminer.
Stop and prevent NGINX from starting up on startup.
Check to see if MySQL is Disabled
Yep
Test access to the database server in PHP code
Add to dbtest.php
<em>SELECT guid FROM wp_posts</em>()<br /> <ul><?php //External IP (charged after quota hit) //$servername = 'db.yourserver.com'; //Private IP (free) //$servername = '10.x.x.x'; $username = 'username'; $password = '********your*password*********'; $dbname = 'database'; // Create connection $conn = new mysqli($servername, $username, $password, $dbname); // Check connection if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } $sql = 'SELECT guid FROM wp_posts'; $result = $conn->query($sql); if ($result->num_rows > 0) { // output data of each row while($row = $result->fetch_assoc()) { echo $row["guid"] . "<br>"; } } else { echo "0 results"; } $conn->close(); ?></ul> Done
Check for open ports.
You can install nmap on another server and scan for open ports
Install nmap
Scan a server for open ports with nmap
You should see this on a server that has access to see port 3306 (port 3306 should not be visible by non-whitelisted IP’s). Port 3shouldoudl not be seen via everyone.
You should see something like this on a server that has access to see port 80/443 (a web server)
I’d recommend you use a service like https://pentest-tools.com/network-vulnerability-scanning/tcp-port-scanner-online-nmap# to check for open ports. https://hackertarget.com/tcp-port-scan/ is a great tool too.
https://www.infobyip.com/tcpportchecker.php is also a free port checker that you can use to verify individual closed ports.
Hardening MySQL and Debian
Read: https://www.debian.org/doc/manuals/securing-debian-howto/ap-checklist.en.html
Configuring WordPress use the dedicated Debian VM
On the source server that used to have MySQL edit your wp-config.php file for WordPress.
Remove
define('DB_HOST', 'localhost');
add (read the update below, I changed the DNS IP to the Private IP to have free traffic)
//Oriinal localhost //define('DB_HOST', 'localhost'); //New external host via DNS (Charged after quota hit) //define('DB_HOST', 'db.fearby.com'); //New external host via Private IP (Free) define('DB_HOST','10.x.x.x');
Restart NGINX
Restart PHP-FPM
Conclusion
Nice, I seem to have shaved off 0.3 seconds in load times (25% improvement)
Update: Using a Private IP or Public IP between WordPress and MySQL servers
After I released this blog post (version 1.0 with no help from UpCloud) UpCloud contacted me and said the following.
I will have updated my references in this post and replace the public IP address (that is linked to DNS record for db.fearby.com) and instead use the private ip address (e.g 10.x.x.x), your servers private IP address is listed against the public IPv$ and IPv6 address.
I checked that the local ufw firewall did indeed allow the private IP access to MySQL.
On my new Debian MySQL server, I edited the file /etc/mysql/my.cnf and changed the IP to the private IP and not the public IP.
Now it looked like
(10.x.x.x my Debian servers private IP)
On my WordPress instance, I edited the file /www-root/wp-config.php
I added the new private host
//Oriinal localhost //define('DB_HOST', 'localhost'); //New external host via DNS (Charged after quota hit) //define('DB_HOST', 'db.fearby.com'); //New external host via Private IP (Free) define('DB_HOST','10.x.x.x');
(10.x.x.x my Debian servers private IP)
Alos on Debian/MySQL ensure you have granted access to the private IP of the WordPress server
Edit /etc/host.allow
Add
Restart MySQL
TIP: Enable UpCloud Backups
Do setup automatic backups (and or take manual backups). Backups are an extra charge but are essential IMHO.
Troubleshooting
If you can’t access MySQL log back into MySQL
and run
Reboot
Lower Upload Limits
Don’t forget to lower file upload sizes in NGINX and PHP (e.g 2M) now that the database has been restored.
I hope this guide helps someone.
TIP: Sign up to UpCloud using this link to get $25 free UpCloud VM credit.
https://www.upcloud.com/register/?promo=D84793
Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]
Revision History
v1.6 Changed Public IP use to private IP use to ensure we are not charged when the serves sage goes over the quota
v1.5 Fixed 03 type (should have been 0.3)
v1.4 added disable nginx info
v1.3 added https://www.infobyip.com/tcpportchecker.php
v1.1 added https://hackertarget.com/tcp-port-scan/
v1.0 Initial Post