
I love VPS servers. Configuring them and customizing cloud solutions brings me joy.
For the last seven years or so, we have hosted all our clients on Linode, and they're great. Their support is lightning fast and top-notch. They had some outages, though, in their earlier years that hit hard.
Regardless, they've been a solid choice, and I'm proud to have been their customer for so long. Before SNI, we needed a provider that can bind multiple IPs to one host, and Linode was the best solution...back then.
Fast forward to today. We now host our clients on a powerful bare-metal box with RAID configurations, using a virtual machine running VMWare.
There's a pretty good-sized fiber connection as well. We have full control of our client's data, run local backups, can spin up new VMs anytime, and much more. It gives our clients a powerhouse server, and keeps costs way down!
However, if our building power were to go down, so would our clients' websites. The building has backup power, but that would still be a disaster, and we needed a fail-over solution.
After thinking about the many cloud providers we've used, I have decided that Digital Ocean is a great fit.
Their interface is clean and fantastic with a continually growing set of solutions. I've built out a lot of custom solutions for various clients in the past across all cloud providers (AWS, Azure, Google), and DO is by far the easiest.
Plus, the cost is right. The other option I was thinking of was to build out an auto-scaling solution in Azure or AWS; it's unnecessary at this time.
Digital Ocean Setup Quick Summary
This post is not going to cover the fail-over solution, sorry.
Instead, I'm going to go over the basics of building a fresh Debian LEMP server, all the way through to a full working Nginx setup to run WordPress. If you're into Apache instead, I've written a quick-start guide on setting up a LAMP server before (it's a little dated but should still apply).
In case you're not sure what LEMP stands for, it's Linux, Nginx (pronounced Engine-x), MariaDB (or MySQL), and PHP.
Creating Your LEMP Server
Ok, let's get started with the Linux part and install our preferred distribution. Create an account on Digital Ocean, and login to create your first Droplet.
Next, choose the latest version of Debian 9 as your image. You could also continue through this tutorial if you want Ubuntu.

Next, choose the size of your Droplet. You can skip the Backups and Block Storage section for now. You can always add these later. Since this will act as a secondary server, I don't need either of those solutions.
Choose your Datacenter that best matches where your customers are geographically. A close server means low latency, and that's what you want.
Next, you have some Additional Options to choose from:

Let's talk through these. First off, you can always enable the options later, and they're all free. I chose the Monitoring option to see some extended metrics in my dashboard and to be able to create alerts. If you're creating a mail server, IPv6 would be a good idea for better email delivery, especially to Gmail servers. Anyway, you can read more about the additional options on Digital Ocean.
Next, we're going to skip setting up the SSH key here. Just personal preference, but I don't want my keys anywhere but with me. We'll still lock down SSH and create keys in a bit. Ok, update your hostname, then hit the big Create button, and in a few seconds, you'll have a new server with your own IP. Shortly after, you will receive an email with your "root" password.
Before we access our new server, let's create some firewall rules in the Networking section of DO. This is another great feature. Before, we needed to use something like UFW or Shorewall. Their network-based firewall is all you need in most cases, and stopping threats before reaching your server is the best option. Here are the rules you need to create for a standard web server:

Make sure you click the "Droplets" tab to add your new Droplet and apply the rules you just created.
Basic VPS Server Setup
Finally, let's access your server. Open up a terminal window on your Mac, or use PuTTY on your PC. My instructions are going to be Mac focused throughout this tutorial.
You're going to SSH over the default port 22 and simple type from the terminal window:
ssh root@111.222.333.444
Obviously, replacing your newly supplied IP in place of the one above. It will prompt you to change your password, and you're in!
You should also create a new A record at your DNS provider to point your hostname to your new IP. Then, you can replace the IP with your hostname next time you login to your server.
Then, I always run a few commands with any new server.
apt-get update && apt-get upgrade
apt-get -y install build-essential htop ntp wget sendmail
The first line updates our package lists found in /etc/apt/sources.list and /etc/apt/sources.list.d/ and then upgrades all packages.
And, I just like htop as a better visual tool for checking server resources. You can run htop at the command line once installed to see how that looks.
Let's now configure our Network Time Protocol (NTP) server and timezone.
nano /etc/ntp.conf
Uncomment the "server" line and change the value to us.pool.ntp.org for the server name.
Then run:
dpkg-reconfigure tzdata
Follow the on-screen prompts to select your correct timezone settings using your up/down keyboard arrows.
Locking Down SSH
Before we lock SSH down, there are some things you need to consider. Will you be the only one accessing your server, or will you provide access to developers, clients, or other people? Do you have a dedicated IP that you work from? I'm going to cover some basic security, with some additional details at the end.
We're definitely going to lock down the ability for "root" to access your server over SSH. In order to do that, we first need to create a new user, which is simple:
adduser user adduser user sudo
The username above is user
- replace with your desired username. Enter in a strong 20+ character password. The next line adds the new user to the sudo group. Moving forward, you can run root commands as this user.
I've been using this password generator tool for years, in case you need one.
Also, Digital Ocean creates a user debian, which could pose a security risk (kind of like having a default user on your router - not good). Let's remove this user.
groupdel debian userdel -rf debian
Now, Let's type exit at the terminal and terminate our SSH session. We're going to create a new SSH key for this user from your Mac!
Again, with a new terminal window...from your Mac command line...type the following:
ssh-keygen -b 4096
It will prompt you for the file location. I like to change the file name to match the server since I have multiple SSH keys for various servers. Follow the example given and change the last part id_rsa to any new name. I always add a passphrase as well; it's up to you.
Now, we're going to push the public key to your server and login as the new user your create above with adduser.
ssh-copy-id -i your_public_key.pub user@host
It will prompt for the password you created for your new user. That's it! Now, you can access your server using your SSH key pair.
Next time you type login to your server, you can simply type:
ssh user@host
Replace host with your IP or updated DNS record.
If you entered a passphrase, that's all you'll have to remember, not your highly secure 20+ character password.
Let's log in back as root to finish securing SSH.
ssh root@111.222.333.444 groupadd sshusers gpasswd -a user sshusers
Replace user
above with the username you created in the beginning of this section. We're creating a new group called sshusers
and adding user
to that group. Only users added to this group will be allowed SSH access.
cd /etc/ssh nano sshd_config
You can update the SSH port, but I never do.
Uncomment the 3 lines starting with HostKey by removing the # sign at the beginning.
Find PermitRootLogin and change the yes to no.
Then go all the way to the bottom and add this line:
AllowGroups sshusers
Use ctrl + x, then type "y", then type "enter" to save and close the file.
service sshd restart
That's a very basic lock down. You can take it further by locking SSH down to only your IP by modifying /etc/hosts.allow
and /etc/hosts.deny
through researching that on your own.
Now, type exit and enter as many times until you're back at your own computer's command prompt. Once again, type ssh user@host
or ssh user@111.222.333.444
(replacing user either host or IP with your settings).
You should go directly in without having to type a password unless you added a challenge phrase.
Installing MariaDB
The latest version of Debian 9 is called Stretch. It now ships with MariaDB instead of MySQL. MariaDB is fully backward-compatible and has many new features you can read about. You can still run phpMyAdmin with MariaDB, so all is good there.
apt-get install mariadb-server mysql_secure_installation
The first line will install MariaDB and all package dependencies. Then, we'll run the next line to set the database root password. During the prompts, type "y" for all questions to secure the installation and remove unnecessary users and tables.
**** make sure to save your database root password ****
Let's log in to MariaDB (mysql) and create a database while we're here, that we'll use to complete the WordPress setup later.
mysql -u root -p
Enter your mysql root password. You'll see a MariaDB prompt, then enter:
create database <strong>wpdb</strong>; create user <strong>wp_user</strong>@localhost; SET PASSWORD FOR '<strong>wp_user</strong>'@localhost= PASSWORD('your_password_here'); GRANT ALL PRIVILEGES ON <strong>wpdb</strong>.* TO <strong>wp_user</strong>@localhost IDENTIFIED BY 'your_password_here';
You can change wpdb
and wp_user
to anything that might suit you better above.
You will want to tune your MariaDB/MySQL installation. Start with navigating to /etc/mysql to get familiar with the configuration structure. If there's interest, I can do a separate guide on database tuning. However, for a single WordPress site, it's ready to go.
We'll come back to the database after completing the Nginx setup.
Installing Nginx
You're probably familiar with Apache as the webserver, and it's a powerhouse. It's the typical setup on shared hosting providers, and it does have some advantages. If you're in the SEO space, you know about the .htaccess file to build things like 301 redirects, among the many other configurations files. However, these same config files can cause security issues and are speed bottle-necks.
Nginx was originally built to process a massive amount of concurrent connections. The resource usage (memory, CPY, etc.) is highly optimized. When it first came out, many used Nginx on the front-end in combination with Apache processing requests on the back-end. It was a clumsy setup, and there's absolutely no need for Apache any longer.
With Nginx, you can use it as a reverse proxy, a load balancer, and so much more. It's badass! Ok, let's get into the install.
We could install nginx directly using the current Debian repositories, but let's get the official ones and do this right. There are different flavors of Nginx. We're going to install the "full" version for when we need other modules, such as memcached.
First, let's download the key:
wget https://nginx.org/keys/nginx_signing.key apt-key add nginx_signing.key
Next, let's edit the sources.list file:
nano /etc/apt/sources.list
Add these two lines at the bottom:
deb https://nginx.org/packages/mainline/debian/ stretch nginx deb-src https://nginx.org/packages/mainline/debian/ stretch nginx
Now, you're ready to install Nginx:
apt-get install nginx-full
Click "Y" to install all the dependencies, then you can visit http://111.222.333.444
(your IP address) or the DNS name you associated with your IP to see a default Nginx welcome screen.

You now have a working webserver! However, it still will not be able to process PHP. We'll get into that next. Keep in mind, this is a bare-bones install.
I'm not going to cover how to "tune" your Nginx settings in this article. If that's a topic you would like me to write about, just let me know in the comments.
Setting up PHP 7.3
At the time of this writing, the latest stable and supported version of PHP is 7.3 which you can read about here.
Debian 9 (Stretch) ships with PHP 7.0 which will be upgraded to 7.3 in the next Debian release 10 (Buster). However, PHP 7.0 is already "end of life" and no longer support.
Let's install the latest version, but it will require adding new repos first:
apt install ca-certificates apt-transport-https wget -q https://packages.sury.org/php/apt.gpg -O- | sudo apt-key add - echo "deb https://packages.sury.org/php/ stretch main" | sudo tee /etc/apt/sources.list.d/php.list apt-get update
That last line above is important to update all the repositories. Now, we can install the common PHP 7.3 packages (plus, some others that will come in handy).
apt-get install php7.3-cli php7.3-common php7.3-curl php7.3-dev php7.3-fpm php7.3-gd php7.3-geoip php7.3-gmp php7.3-igbinary php7.3-json php7.3-mbstring php7.3-memcached php7.3-msgpack php7.3-mysql php7.3-opcache php7.3-readline php7.3-soap php7.3-tidy php7.3-xml php7.3-xsl php7.3-zip
Just hit "y" on the prompt, and PHP should now be installed. You can check by typing php -v
at the command line.
Ok, so now we have Nginx installed and PHP installed, but we still can't run any PHP files through Nginx. This requires more configuration.
Setting Up Nginx with PHP
Nginx has a default configuration file that has lines you can un-comment for PHP to work. You can find the file here: /etc/nginx/sites-enabled/default
If you un-comment the location PHP location block and update php7.0-fpm.sock
to php7.3-fpm.sock
, you'll have a working Nginx setup, ready to process PHP.
It should look like this:
location ~ \.php$ { include snippets/fastcgi-php.conf; # With php-fpm (or other unix sockets): fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; # With php-cgi (or other tcp sockets): #fastcgi_pass 127.0.0.1:9000; }
Notice there are 2 different fastcgi_pass parameters. You can only uncomment one, and I prefer using the unix socket vs. the TCP socket. You can later create separate PHP pools if you host multiple websites.
Also, look for this line and add index.php
index index.php index.html index.htm index.nginx-debian.html;
Now, navigate back to /var/www/html and create a file called info.php
with the following code:
<?php phpinfo(); ?>
You can do that by simply typing nano info.php and copy/paste the code into the file. Then use ctrl + x, then type "y", then type "enter" to save and close the file.
Next, you will need to restart nginx using: service nginx restart
Let's test it.
Navigate to your IP address and check the info file, with something like http://111.222.333.444/info.php
Hopefully, it all went well, you will see this page:

Hey, look at that! You now have a fully working version of LEMP!
Setting Up WordPress
Ok, you should still be in the /var/www/html folder.
Remove the couple files by typing:
rm info.php index.nginx-debian.html
Next, let's download and uncompress WordPress. Again, you want to be in the /var/www/html folder and can type cd /var/www/html
if you're not there already.
apt-get install wget wget https://wordpress.org/latest.tar.gz tar --strip-components=1 -xvf latest.tar.gz rm latest.tar.gz chown www-data:www-data -R * mv wp-config-sample.php wp-config.php
After you complete those steps, open a browser window, and let's get random salt and keys.
Copy all 8 lines, then once again use nano to edit the wp-config.php file:
nano wp-config.php
Find the section that shows the salt and keys, and replace it with the 8 lines you copied.
Ok, now look up towards the beginning of the file. We need to update the database information from the MariaDB setup from earlier.
Update these three lines:
define( 'DB_NAME', 'wpdb' ); define( 'DB_USER', 'wp_user' ); define( 'DB_PASSWORD', 'your_password_here' );
Same as before, ctrl + x, then type "y", then type "enter" to save and close the file.
We're done! Now navigate to your IP or domain name and you should see the WordPress install screen like below.

Just follow the prompts, and you will have a fully working version of WordPress ready to go.
In Summary
Creating your own virtual private server (VPS) is an amazing way to control your web server environment. I wouldn't have it any other way. You can do so much more on your own server, like adding ClamAV for basic file protection, enhancing Nginx with modules like Brotli, PageSpeed, and so many more.
Keep in mind this is a complete setup to get your VPS up and running with WordPress. However, there are more setup tasks such as testing mail flow, setting up SSL, and tuning your entire server. If you would like a custom solution for your own site or business, feel free to reach out or start a discussion below in the comments.