{"id":195884,"date":"2021-03-17T23:26:17","date_gmt":"2021-03-17T23:26:17","guid":{"rendered":"https:\/\/premium.wpmudev.org\/blog\/?p=195884"},"modified":"2021-03-23T00:42:17","modified_gmt":"2021-03-23T00:42:17","slug":"optimized-wordpress-vps-hosting-dyi-vs-managed","status":"publish","type":"post","link":"https:\/\/wpmudev.com\/blog\/optimized-wordpress-vps-hosting-dyi-vs-managed\/","title":{"rendered":"Optimized WordPress Hosting: DIY or Managed?"},"content":{"rendered":"<p>With WordPress optimized hosting, should you DIY or have someone else manage it for you? In this guide, we explore both options and show you how to set up your own VPS&#8230;<\/p>\n<p>There are many options when it comes to setting up hosting for your WordPress website. You can choose a shared hosting plan (where your site performance is at the mercy of over-provisioned servers), pay a bit more to run your very own VPS (virtual private server) with dedicated resources, or pay just a little bit extra to have someone else manage a VPS for you.<\/p>\n<p>If you&#8217;re not sure about the right type of hosting for your needs, check out our <a href=\"https:\/\/premium.wpmudev.org\/blog\/types-of-web-hosting\/\" rel=\"noopener\" target=\"_blank\">guide to understanding different types of hosting<\/a>.<\/p>\n<p>In this guide, we&#8217;ll focus on the second option and help you understand what kind of effort goes into setting up a VPS for WordPress hosting.<\/p>\n<p>More specifically, we&#8217;ll walk you through all the steps you need to set up your own VPS and then look at the pros and cons of choosing this option.<\/p>\n<p>For ease of reference, you can jump to any section using the links below or go through the entire step-by-step tutorial:<\/p>\n<ul>\n<li><strong><a href=\"#what-is-diy-vps\">What Is DIY VPS Hosting for WordPress?<\/a><\/strong><\/li>\n<li><strong><a href=\"#diy-vps-setup\">Setting Up A WordPress-Optimized VPS:<\/a><\/strong>\n<ol>\n<li><strong><a href=\"#ssh\">Create a non-root user to SSH to the server<\/a><\/strong><\/li>\n<li><strong><a href=\"#secure-mysql\">Secure the MySQL installation<\/a><\/strong><\/li>\n<li><strong><a href=\"#configure-virtual-hosts\">Configure Virtual Hosts for your domain(s)<\/a><\/strong><\/li>\n<li><strong><a href=\"#install-phpmyadmin\">Install PhpMyAdmin to visually access your database (optional)<\/a><\/strong><\/li>\n<li><strong><a href=\"#wp-db\">Change the default WordPress database table prefix<\/a><\/strong><\/li>\n<li><strong><a href=\"#dns\">Configure your new droplet&#8217;s domain DNS settings<\/a><\/strong><\/li>\n<li><strong><a href=\"#https\">Install a Let&#8217;s Encrypt certificate to serve your website over HTTPS<\/a><\/strong><\/li>\n<li><strong><a href=\"#patch-server\">Patch common vulnerabilities on your server<\/a><\/strong><\/li>\n<li><strong><a href=\"#increase-php-limits\">Increase common PHP limits to help with WordPress performance<\/a><\/strong><\/li>\n<\/ol>\n<\/li>\n<li><strong><a href=\"#diy-vps-pros-cons\">Pros and Cons of DIY WordPress VPS vs Managed WordPress Hosting<\/a><\/strong><\/li>\n<\/ul>\n<h2 id=\"what-is-diy-vps\">What Is DIY VPS Hosting for WordPress?<\/h2>\n<p>VPS hosting is web hosting that uses a Virtual Private Server. As we explain <a href=\"https:\/\/wpmudev.com\/blog\/types-of-web-hosting\/\" target=\"_blank\" rel=\"noopener\">here<\/a>, a VPS is a nice compromise between shared and dedicated hosting.<\/p>\n<p>You can customize the VPS resources to suit your needs in terms of\u00a0disk space, memory, processing power, and bandwidth, and scale it if your site&#8217;s traffic increases.<\/p>\n<p>DIY VPS hosting normally refers to running an unmanaged VPS (whereas with a &#8220;managed&#8221; VPS, the\u00a0web hosting company handles everything like system setup, control panel installation, and technical support, leaving you free to just manage your web hosting account).<\/p>\n<p>Although choosing unmanaged or DIY VPS hosting tends to be more affordable than managed VPS hosting, you need to handle everything yourself.<\/p>\n<p>WordPress has its own server requirements, so if you plan to choose DIY VPS hosting specifically for WordPress, you&#8217;ll need to have technical experience with managing servers and running WordPress.<\/p>\n<h2 id=\"diy-vps-setup\">Setting Up A WordPress-Optimized VPS<\/h2>\n<p>VPS web hosts are plentiful and many offer great cloud-hosted servers at reasonable costs.<\/p>\n<p>For this tutorial, we&#8217;ll use <a href=\"https:\/\/www.digitalocean.com\/\" rel=\"noopener\" target=\"_blank\">DigitalOcean<\/a> as our host.<\/p>\n<figure id=\"attachment_195922\" class=\"wp-caption aligncenter\" data-caption=\"true\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-195922 size-full\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2021\/03\/digital-ocean.png\" alt=\"DigitalOcean\" width=\"600\" height=\"247\" \/><figcaption class=\"wp-caption-text\">Let&#8217;s navigate to DigitalOcean and set up a DIY VPS.<\/figcaption><\/figure>\n<p><em>Note:<\/em> The tutorial below will take you through DigitalOcean&#8217;s WordPress-optimized VPS setup process. Alternatively, you can use a tool like <a href=\"https:\/\/spinupwp.com\/\" rel=\"noopener\" target=\"_blank\">SpinupWP<\/a> to set up, configure, access, and manage your server remotely using NGINX.<\/p>\n<p>DigitalOcean makes it easy to set up your own WordPress-optimized VPS, as they have a one-click solution that will build a Ubuntu 20.04 VPS with WordPress and all its required software pre-installed.<\/p>\n<p>That being said, there is still some configuration to be done to finish the installation of WordPress and to harden both WordPress and the server itself.<\/p>\n<p>Let&#8217;s go through each step.<\/p>\n<h3 id=\"ssh\">1. Create a non-root user to SSH to the server<\/h3>\n<p>First, create a Digital Ocean One-Click WordPress 5.5.1 on Ubuntu 20.04 droplet.<\/p>\n<figure id=\"attachment_195923\" class=\"wp-caption aligncenter\" data-caption=\"true\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-195923 size-full\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2021\/03\/wordpress.png\" alt=\"Set up WordPress.\" width=\"600\" height=\"264\" \/><figcaption class=\"wp-caption-text\">Select WordPress.<\/figcaption><\/figure>\n<p><em>Note:<\/em> Make sure to <a href=\"https:\/\/wpmudev.com\/blog\/a-complete-guide-to-wordpress-password-security\/\" target=\"_blank\" rel=\"noopener\">use a strong password<\/a> for the root account (e.g. use a 32-character password)<\/p>\n<p>Keep a copy of this password handy in a notepad on your computer. It will make connecting to the droplet easier. You will create a separate user to connect with in the future, so this is simply setting a strong password for the root user that will no longer be actively used.<\/p>\n<figure id=\"attachment_195924\" class=\"wp-caption aligncenter\" data-caption=\"true\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-195924 size-full\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2021\/03\/secure-password-generator.png\" alt=\"A 32-character password.\" width=\"600\" height=\"413\" \/><figcaption class=\"wp-caption-text\">Choose a strong password &#8211; at least 32-characters is recommended. Source: passwordsgenerator.net<\/figcaption><\/figure>\n<p>Once you have done this, <a href=\"https:\/\/wpmudev.com\/blog\/what-is-ssh-wordpress\/\" target=\"_blank\" rel=\"noopener\">SSH<\/a> to the server using the IP and root password from your initial setup.<\/p>\n<p>You will be prompted to enter your domain name. Press <code>CTRL+C<\/code> to exit this script for now. We&#8217;ll come back to this configuration later.<\/p>\n<p>Create a non-root user (replace <code>myusername<\/code> with your username):<\/p>\n<pre><code>adduser myusername\r\nusermod -aG sudo myusername\r\nusermod -aG www-data myusername<\/code><\/pre>\n<p>Test to make sure that <em>myusername<\/em> has sudo access:<\/p>\n<pre><code>su myusername\r\nls -la \/root\r\nsudo ls -la \/root<\/code><\/pre>\n<p><strong>Note:<\/strong> The second command above should give an error for permission denied, but prefixing the command with sudo will allow you to escalate your privilege to that of root.<\/p>\n<h3 id=\"secure-mysql\">2. Secure the MySQL installation<\/h3>\n<p>Use the following command to view your root mysql account password.<\/p>\n<p><code>cat \/root\/.digitalocean_password<\/code><\/p>\n<p><code>mysql_secure_installation<\/code><\/p>\n<p>At the prompts for the command above, enter:<\/p>\n<p><em>NO &gt; root password &gt; YES &gt; YES &gt; YES &gt; YES<\/em><\/p>\n<p>Then, delete the file containing your default passwords so that they are not plainly available on your server directory:<\/p>\n<p><code>rm -rf \/root\/.digitalocean_password<\/code><\/p>\n<h3 id=\"configure-virtual-hosts\">3. Configure Virtual Hosts for your Domain(s)<\/h3>\n<p>This is so that your Apache server can handle serving numerous domains from your droplet.<\/p>\n<p>Even though you may only be serving one domain from this droplet, it&#8217;s best practice to set up Virtual Hosts so that you are ready should the need arise in the future.<\/p>\n<pre><code>mkdir -p \/var\/www\/mydomainname.com\/html\/\r\nchown -R www-data:www-data \/var\/www\/mydomainname.com\/html\/\r\nrsync -avP \/var\/www\/html\/ \/var\/www\/mydomainname.com\/html\/\r\ncp \/etc\/apache2\/sites-available\/000-default.conf \/etc\/apache2\/sites-available\/mydomainname.com.conf\r\nvi \/etc\/apache2\/sites-available\/mydomainname.com.conf<\/code><\/pre>\n<p>Edit your mydomainname.com.conf file with the following lines, modifying existing content if needed:<\/p>\n<pre><code>ServerAdmin admin@mydomainname.com\r\nServerName www.mydomainname.com\r\nServerAlias mydomainname.com\r\nDocumentRoot \/var\/www\/mydomainname.com\/html\r\n\r\n&lt;Directory \/var\/www\/mydomainname.com\/html\/&gt;<\/code><\/pre>\n<p>Save the changes to your .conf and run the following commands to let the web server know about your new Virtual Host:<\/p>\n<pre><code>a2ensite mydomainname.com.conf\r\na2dissite 000-default.conf\r\na2enmod expires\r\nservice apache2 reload<\/code><\/pre>\n<p>Your web server is now aware of your custom Virtual Host!<\/p>\n<p>Archive the pre-built one-click WordPress folder structure<\/p>\n<p><code>mv \/var\/www\/html \/var\/www\/html.bak<\/code><\/p>\n<h3 id=\"install-phpmyadmin\">4. Install PHPMyAdmin so you can manage your database via a Web GUI\u00a0(optional)<\/h3>\n<pre><code>apt-get update\r\napt-get install phpmyadmin<\/code><\/pre>\n<p>&#8220;After this operation, 51.4 MB of additional disk space will be used.&#8221; &gt;&gt; Yes<\/p>\n<p>&#8220;Auto-configure web server&#8221; or &#8220;Web server to reconfigure automatically&#8221; &gt;&gt; No (TAB then OK)<\/p>\n<p>&#8220;Configure database for phpmyadmin with dbconfig-common?&#8221; &gt;&gt; No<\/p>\n<p><code>echo \"#Include \/etc\/phpmyadmin\/apache.conf\"&gt;&gt;\/etc\/apache2\/sites-enabled\/mydomainname.com.conf<\/code><\/p>\n<p><strong>Note:<\/strong> Simply SSH to your droplet and remove the comment delimiter (#) from the line above to quickly disable PHPMyAdmin should you want to keep it disabled until you need it.<\/p>\n<p><code>vi \/etc\/phpmyadmin\/apache.conf<\/code><\/p>\n<p>Update Alias to:<\/p>\n<p><code>\/my_db \/usr\/share\/phpmyadmin<\/code><\/p>\n<p><strong>Note:<\/strong> This last line makes it so that you can access your PHPMyAdmin installation at mydomainname.com\/my_db<\/p>\n<p><code>service apache2 reload<\/code><\/p>\n<h3 id=\"wp-db\">5. Change the default WordPress database table prefix<\/h3>\n<p>Let&#8217;s harden the one-click WordPress database prior to installation.<\/p>\n<p>We&#8217;ll do this by renaming the default wp_ database prefix to something custom so that attempts by hackers to extract your database table data based on the default names will fail:<\/p>\n<p><code>sed -i 's\/wp_\/wp_510942_\/g' \/var\/www\/mydomainname.com\/html\/wp-config.php<\/code><\/p>\n<p><strong>Note:<\/strong> This will make your database tables prefixed with <code>wp_510942_<\/code> instead of just <code>wp_<\/code>. You can use any random number or word to make it unique.<\/p>\n<h3 id=\"dns\">6. Configure your new droplet&#8217;s domain DNS settings<\/h3>\n<p>Log in to DigitalOcean and go to Networking.<\/p>\n<p>For the droplet in question, use the following configurations:<\/p>\n<pre><code>NS ns1.digitalocean.com\r\nNS ns2.digitalocean.com\r\nNS ns3.digitalocean.com\r\nA mydomainname.com\r\nCNAME\u00a0<a href=\"http:\/\/www.mydomainname.com\/\" rel=\"nofollow\" target=\"_blank\">http:\/\/www.mydomainname.com<\/a>\r\nCNAME *.mydomainname.com<\/code><\/pre>\n<h3 id=\"https\">7. Install Let&#8217;s Encrypt certificate<\/h3>\n<p><code>sudo certbot --apache -d www.mydomainname.com -d mydomainname.com<\/code><\/p>\n<ul>\n<li>Support email: <a href=\"mailto:admin@mydomainname.com\" rel=\"nofollow\" target=\"_blank\">admin@mydomainname.com<\/a><\/li>\n<li>Select <code>YES<\/code> to Terms of Service and <code>NO<\/code> to Share Email Address<\/li>\n<li>Choose Option 2: SECURE \u2013 MAKE ALL REQUESTS REDIRECT TO SECURE HTTPS<\/li>\n<\/ul>\n<h3 id=\"path-server\">8. Patch Common Vulnerabilities on Your Server<\/h3>\n<h4>Additional hardening #1: Prevent LIBWWW-PERL vulnerabilities:<\/h4>\n<p>Edit your .htaccess and paste these two lines after RewriteEngine On<\/p>\n<p><code>sudo vi \/var\/www\/mydomainname.com\/html\/.htaccess<\/code><\/p>\n<pre><code>RewriteCond %{HTTP_USER_AGENT} libwww-perl.*\r\nRewriteRule .* ? [F,L]<\/code><\/pre>\n<h4>Additional hardening #2: Disable server signature<\/h4>\n<p>Edit apache2.conf, search for the two strings or append at the end of the file if they are not present, then reload apache2:<\/p>\n<p><code>sudo vi \/etc\/apache2\/apache2.conf<\/code><\/p>\n<pre><code>ServerSignature Off\r\nServerTokens Prod<\/code><\/pre>\n<p><code>service apache2 reload<\/code><\/p>\n<h4>Additional hardening #3: Prevent Apache information disclosure via .htaccess:<\/h4>\n<p><code>sudo vi \/var\/www\/mydomainname.com\/html\/.htaccess<\/code><\/p>\n<pre><code>## Prevent information disclosure ##\r\n&lt;FilesMatch \".(txt|md|exe|sh|bak|inc|pot|po|mo|log|sql)$\"&gt;\r\nRequire all denied\r\n&lt;\/FilesMatch&gt;\r\n&lt;Files robots.txt&gt;\r\nRequire all granted\r\n&lt;\/Files&gt;\r\n&lt;Files ads.txt&gt;\r\nRequire all granted\r\n&lt;\/Files&gt;\r\n## End ## <\/code><\/pre>\n<h4>Additional hardening #4: Use keys for non-root SSH and disable passwords and root login<\/h4>\n<p>SSH keys provide an easy, secure way to log into your server and are recommended for all users.<\/p>\n<p>For this step, we recommend following DigitalOcean&#8217;s detailed tutorial on <a href=\"https:\/\/www.digitalocean.com\/community\/tutorials\/how-to-set-up-ssh-keys-on-ubuntu-20-04\" rel=\"noopener\" target=\"_blank\">setting up SSH keys for an Ubuntu 20.04 installation<\/a>.<\/p>\n<p><em>Note:<\/em> The above is by no means an exhaustive, all-encompassing list of hardening measures (that&#8217;s a whole topic on its own), but it&#8217;s a really good start if you plan to set up and run your own VPS.<\/p>\n<h3 id=\"increase-php-limits\">9. Increase PHP limits for WordPress performance:<\/h3>\n<p><code>sudo vi \/etc\/php\/7.0\/apache2\/php.ini<\/code><\/p>\n<p>Search for these settings, and raise any existing values to the following:<\/p>\n<ul>\n<li>max_execution_time: 60<\/li>\n<li>memory_limit: 128M<\/li>\n<li>post_max_size: 48M<\/li>\n<li>upload_max_filesize: 48M<\/li>\n<\/ul>\n<p><code>sudo service apache2 restart<\/code><\/p>\n<p>Once you have done this, navigate to your domain and step through the WordPress installation wizard.<\/p>\n<h2 id=\"diy-vps-pros-cons\">DIY WordPress VPS vs Managed WordPress Hosting<\/h2>\n<p>If this all seems like a lot of work just to have a secure VPS server running WordPress, you&#8217;re right!<\/p>\n<p>Thankfully, many of the above steps could be put into a script to automate the process, but the truth remains that the price to pay to have a self-managed VPS is&#8230;well&#8230;managing it all yourself!<\/p>\n<p>This requires not only having the technical experience to set up and run the server but also troubleshoot and fix any problems.<\/p>\n<p>Alternatively, if you&#8217;d prefer to have the equivalent performance and security of a DigitalOcean VPS without having to do it all yourself, then consider <a href=\"https:\/\/wpmudev.com\/hosting\/\" target=\"_blank\" rel=\"noopener\">hosting with WPMU DEV<\/a>! For just a few more dollars a month over the cost of a self-hosted DigitalOcean droplet, you get world-class VPS performance with world-class 24\/7 technical and hosting support&#8230;<em>all done for you!<\/em><\/p>\n<h3>Contributors<\/h3>\n<p>This article was written in collaboration with:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-195926 alignright\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2021\/03\/capital-web-design-ottawa.png\" alt=\"Capital Web Design - Ottawa Web Design\" width=\"300\" height=\"71\" \/><\/p>\n<p><strong>Phil Martin<\/strong> &#8211;\u00a0 <a href=\"https:\/\/capitalwebdesign.ca\" rel=\"noopener\" target=\"_blank\">Capital Web Design<\/a>.\u00a0 Phil uses his twenty years of web design experience to achieve one goal: give back to his hometown by building modern websites for businesses and nonprofits in the Canadian capital!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>With WordPress optimized hosting, should you DIY or have someone else manage it for you? In this guide, we explore both options and show you how to set up your own VPS&#8230; There are many options when it comes to setting up hosting for your WordPress website. You can choose a shared hosting plan (where [&hellip;]<\/p>\n","protected":false},"author":774618,"featured_media":177364,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"blog_reading_time":"","wds_primary_category":0,"wds_primary_tutorials_categories":0,"footnotes":""},"categories":[263],"tags":[],"tutorials_categories":[],"class_list":["post-195884","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials"],"_links":{"self":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/195884","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/users\/774618"}],"replies":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/comments?post=195884"}],"version-history":[{"count":41,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/195884\/revisions"}],"predecessor-version":[{"id":200445,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/195884\/revisions\/200445"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media\/177364"}],"wp:attachment":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media?parent=195884"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/categories?post=195884"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tags?post=195884"},{"taxonomy":"tutorials_categories","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tutorials_categories?post=195884"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}