<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Rewaant</title><description>Insights and Commerce Lab from Rewaant.</description><link>https://rewaant.com/</link><atom:link href="https://rewaant.com/rss.xml" rel="self" type="application/rss+xml"/><item><title>Deep Dive into Shopify &amp; WooCommerce</title><link>https://rewaant.com/labs/shopify-woocommerce-deep-dive/</link><guid isPermaLink="true">https://rewaant.com/labs/shopify-woocommerce-deep-dive/</guid><description>Over the past decade, I’ve worked across different layers of the web, from Linux-based systems and cloud hosting environments to frontend development and web platforms like WordPress. Like many developers, I’ve used a wide range of technologies along the way.</description><pubDate>Wed, 04 Mar 2026 17:48:53 GMT</pubDate><content:encoded>&lt;img src=&quot;https://rewaant.com/images/labs/shopify-woocommerce-deep-dive/hero.png&quot; alt=&quot;Title card reading Starting a Deep Dive into Shopify and WooCommerce.&quot;&gt;&lt;h2 id=&quot;studying-systems&quot;&gt;Studying systems deeply&lt;/h2&gt;
&lt;p&gt;Over the past decade, I’ve worked across different layers of the web, from Linux-based systems and cloud hosting environments to frontend development and web platforms like WordPress.&lt;/p&gt;
&lt;p&gt;Like many developers, I’ve used a wide range of technologies along the way. But over time, I’ve come to appreciate the value of studying systems deeply rather than just using them at the surface level.&lt;/p&gt;
&lt;p&gt;Modern ecommerce platforms are a great example of this.&lt;/p&gt;
&lt;h2 id=&quot;shopify-and-woocommerce&quot;&gt;Shopify and WooCommerce&lt;/h2&gt;
&lt;p&gt;Platforms like &lt;strong&gt;Shopify and WooCommerce&lt;/strong&gt; power millions of businesses today. Yet most development around them focuses on themes, plugins, or quick integrations, without much attention to how the systems themselves actually work.&lt;/p&gt;
&lt;p&gt;This site is my space to explore those platforms more deliberately.&lt;/p&gt;
&lt;h2 id=&quot;what-this-covers&quot;&gt;What this deep dive covers&lt;/h2&gt;
&lt;p&gt;Over the coming months, I’ll be documenting a structured deep dive into the technologies behind modern ecommerce platforms, starting with Shopify and eventually expanding into WooCommerce as well.&lt;/p&gt;
&lt;p&gt;That means looking at things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how Shopify stores are structured&lt;/li&gt;
&lt;li&gt;how Liquid templates work&lt;/li&gt;
&lt;li&gt;how themes render and interact with the browser&lt;/li&gt;
&lt;li&gt;how APIs and apps extend the platform&lt;/li&gt;
&lt;li&gt;how performance and architecture affect real stores&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some posts will be short notes while I learn and experiment. Others will go deeper into specific technical areas.&lt;/p&gt;
&lt;h2 id=&quot;the-goal&quot;&gt;The goal&lt;/h2&gt;
&lt;p&gt;The goal is simple: understand these systems properly and document the process along the way.&lt;/p&gt;
&lt;p&gt;If you’re interested in how modern ecommerce platforms actually work under the hood, you’ll probably enjoy following along.&lt;/p&gt;
</content:encoded><dc:creator>Rewaant Chhabra</dc:creator><category>Ecommerce Architecture</category></item><item><title>Why You Still Need a Website in 2024: A Personalized Perspective</title><link>https://rewaant.com/blog/why-you-still-need-a-website-in-2024/</link><guid isPermaLink="true">https://rewaant.com/blog/why-you-still-need-a-website-in-2024/</guid><description>Discover why having a website in 2024 is crucial for your digital success! Explore the personalized journey of control, branding, and e-commerce opportunities that await you. Embrace the future with your own corner of the internet.</description><pubDate>Mon, 29 Apr 2024 01:21:35 GMT</pubDate><content:encoded>&lt;img src=&quot;https://rewaant.com/insights/why-you-still-need-a-website-in-2024/hero.png&quot; alt=&quot;Title card reading Website in 2024?&quot;&gt;&lt;p&gt;Hey there, fellow digital wanderer! As we navigate through the ever-evolving digital realm of 2024, you might be wondering: “Do I really need a website?” It’s a valid question, especially with the plethora of online platforms vying for our attention. Let’s embark on a journey to explore why having your own corner of the internet is more important than ever.&lt;/p&gt;
&lt;h2 id=&quot;digital-identity&quot;&gt;Your Digital Identity: Make it Count&lt;/h2&gt;
&lt;p&gt;Think of your website as your virtual home. It’s where you welcome visitors, showcase your talents, and share your story with the world. In a survey conducted by Wix, it was found that 84% of consumers believe that having a website makes a business more credible. That’s right – your website isn’t just a digital storefront; it’s a stamp of legitimacy in the online arena.&lt;/p&gt;
&lt;h2 id=&quot;control-freak&quot;&gt;Control Freak? Embrace it!&lt;/h2&gt;
&lt;p&gt;Okay, maybe not to the extreme, but having control over your online presence is crucial. With social media platforms constantly changing their algorithms and policies, your visibility can be at the mercy of their whims. But with your own website, you call the shots. According to a report by HubSpot, businesses with a website are 61% more likely to reach their marketing goals. That’s the power of being in the driver’s seat!&lt;/p&gt;
&lt;h2 id=&quot;brand-swagger&quot;&gt;Show Off Your Brand Swagger&lt;/h2&gt;
&lt;p&gt;Your brand is unique, so why settle for a cookie-cutter social media profile? Your website is your canvas, waiting for your creative brushstrokes. From the colors and fonts to the tone of your content, every element tells your brand’s story. Plus, did you know that 48% of people cited a website’s design as the number one factor in determining the credibility of a business? That’s the visual impact of a well-crafted website speaking volumes about your brand.&lt;/p&gt;
&lt;h2 id=&quot;roads-to-your-website&quot;&gt;All Roads Lead to Your Website&lt;/h2&gt;
&lt;p&gt;Imagine your website as Grand Central Station, with information trains arriving and departing at all hours. Whether it’s potential clients seeking your services or customers looking to make a purchase, your website is where they’ll find all the information they need. According to a study by Clutch, 29% of small businesses with a website say their site is the primary source of leads. Talk about being the ultimate information hub!&lt;/p&gt;
&lt;h2 id=&quot;ecommerce&quot;&gt;E-Commerce: It’s Where the Action Is&lt;/h2&gt;
&lt;p&gt;If you’re in the business of selling, an e-commerce-enabled website is your golden ticket to success. The global e-commerce market is projected to reach a staggering $6.5 trillion by 2023, according to Statista. With a website, you can tap into this lucrative market, offering your products or services to customers around the globe, 24/7.&lt;/p&gt;
&lt;h2 id=&quot;google-helps&quot;&gt;Google is Your Best Friend&lt;/h2&gt;
&lt;p&gt;In the vast wilderness of the internet, Google is the ultimate compass. And having a website ensures that you’re not lost in obscurity. By optimizing your website for search engines, you can climb the ranks and bask in the glory of organic traffic. After all, 75% of users never scroll past the first page of search results, as revealed by a study from ImForza. So, let Google be your guide to digital prominence!&lt;/p&gt;
&lt;h2 id=&quot;its-the-future&quot;&gt;Embrace the Future, One Click at a Time&lt;/h2&gt;
&lt;p&gt;As we sail into the uncharted waters of the digital future, having a website ensures that you’re ready to navigate whatever comes your way. Whether it’s embracing new technologies, adapting to emerging trends, or expanding your online presence, your website is your anchor in the ever-changing sea of the internet.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion: Your Digital Odyssey Awaits!&lt;/h2&gt;
&lt;p&gt;So, dear digital adventurer, do you really need a website in 2024? Absolutely! It’s not just a digital necessity; it’s your ticket to online success. Whether you’re a budding entrepreneur, a creative soul, or a seasoned professional, your website is the cornerstone of your digital identity. So, seize the moment, embark on your digital odyssey, and let your website be the guiding star in your online journey!&lt;/p&gt;
</content:encoded><dc:creator>Rewaant Chhabra</dc:creator><category>Business &amp; Technology</category></item><item><title>Cross-Platform Mobile App Development in 2024: A Comparative Overview</title><link>https://rewaant.com/blog/cross-platform-mobile-app-development-in-2024/</link><guid isPermaLink="true">https://rewaant.com/blog/cross-platform-mobile-app-development-in-2024/</guid><description>Cross-Platform Mobile App Development in 2024: A Comparative Overview</description><pubDate>Fri, 19 Apr 2024 03:49:46 GMT</pubDate><content:encoded>&lt;img src=&quot;https://rewaant.com/insights/cross-platform-mobile-app-development-in-2024/hero.png&quot; alt=&quot;Logos for Flutter, Xamarin, React, Ionic, and NativeScript.&quot;&gt;&lt;p&gt;&lt;strong&gt;In the dynamic realm of mobile app development, choosing the right framework is pivotal for success. Let’s explore the top contenders in cross-platform mobile app development, along with key usage and growth statistics for 2024:&lt;/strong&gt;&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/cross-platform-mobile-app-development-in-2024/01.png&quot; alt=&quot;React Native logo with the line Learn once, write anywhere.&quot; /&gt;
&lt;h2 id=&quot;react-native&quot;&gt;React Native&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Usage Percentage (2024):&lt;/strong&gt; 42%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Growth Rate (2024):&lt;/strong&gt; 8%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Estimated No. of Devs:&lt;/strong&gt; 1.2M&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Average Dev Time:&lt;/strong&gt; 30-50% faster than native development.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Primary languages:&lt;/strong&gt; JavaScript, with the option for TypeScript.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;React Native, backed by Facebook, remains a favorite, boasting a 42% usage rate in 2024. With its steady 8% growth, it’s praised for delivering native-like experiences across platforms using JavaScript and React.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/cross-platform-mobile-app-development-in-2024/02.png&quot; alt=&quot;Flutter logo.&quot; /&gt;
&lt;h2 id=&quot;flutter&quot;&gt;Flutter&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Usage Percentage (2024):&lt;/strong&gt; 28%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Growth Rate (2024):&lt;/strong&gt; 12%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Estimated No. of Devs:&lt;/strong&gt; 800K&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Average Dev Time:&lt;/strong&gt; Comparable to native development.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Primary language:&lt;/strong&gt; Dart&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Google’s Flutter has seen a surge, reaching a 28% usage rate in 2024 with a notable 12% growth. Its Dart-based framework enables visually appealing, high-performance apps with a single codebase.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/cross-platform-mobile-app-development-in-2024/03.png&quot; alt=&quot;Xamarin logo.&quot; /&gt;
&lt;h2 id=&quot;xamarin&quot;&gt;Xamarin&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Usage Percentage (2024):&lt;/strong&gt; 18%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Growth Rate (2024):&lt;/strong&gt; 5%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Estimated No. of Devs:&lt;/strong&gt; 600K&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Average Dev Time:&lt;/strong&gt; 20-30% faster than native development.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Primary language:&lt;/strong&gt; C#&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Acquired by Microsoft, Xamarin maintains its position with an 18% usage rate in 2024. Leveraging C# and .NET, it’s favored for building native apps across platforms.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/cross-platform-mobile-app-development-in-2024/04.png&quot; alt=&quot;Ionic logo.&quot; /&gt;
&lt;h2 id=&quot;ionic&quot;&gt;Ionic&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Usage Percentage (2024):&lt;/strong&gt; 8%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Growth Rate (2024):&lt;/strong&gt; 4%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Estimated No. of Devs:&lt;/strong&gt; 300K&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Average Dev Time:&lt;/strong&gt; 20-40% faster than native development.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Primary languages:&lt;/strong&gt; HTML, CSS, JavaScript&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Built atop Angular and Apache Cordova, Ionic holds its ground with 8% usage in 2024. It’s preferred for rapid prototyping and deployment of web-centric mobile apps.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/cross-platform-mobile-app-development-in-2024/05.png&quot; alt=&quot;NativeScript logo.&quot; /&gt;
&lt;h2 id=&quot;nativescript&quot;&gt;NativeScript&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Usage Percentage (2024):&lt;/strong&gt; 4%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Growth Rate (2024):&lt;/strong&gt; 6%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Estimated No. of Devs:&lt;/strong&gt; 150K&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Average Dev Time:&lt;/strong&gt; Comparable to native development.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Primary languages:&lt;/strong&gt; JavaScript or TypeScript&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;NativeScript offers truly native mobile app development, capturing a niche but growing market with a 4% usage rate in 2024.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In a crowded landscape, the choice of cross-platform mobile app development technology depends on project requirements and developer expertise. React Native stands out for its robust ecosystem and market dominance, making it our preferred choice at Rewaant LLC, given our expertise and market analysis.&lt;/p&gt;
</content:encoded><dc:creator>Rewaant Chhabra</dc:creator><category>Software Engineering</category></item><item><title>How to increase PHP upload limit (Apache)</title><link>https://rewaant.com/blog/increase-php-upload-limit-apache/</link><guid isPermaLink="true">https://rewaant.com/blog/increase-php-upload-limit-apache/</guid><description>A brief how-to for increasing upload limit for you PHP application served by an Apache host.</description><pubDate>Mon, 19 Dec 2022 22:44:40 GMT</pubDate><content:encoded>&lt;img src=&quot;https://rewaant.com/insights/increase-php-upload-limit-apache/hero.png&quot; alt=&quot;Title card reading Increase PHP upload limit on Apache.&quot;&gt;&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;
&lt;p&gt;You’ve probably found yourself in a predicament where you have to upload a file to a PHP application like WordPress or PHPMyAdmin but the default server configuration only allows you to upload files up to 2048 Kbs or 2Mibs. In this short how-to, we’ll quickly explain how you can increase this limit. We’ll be demonstrating this on an AWS EC2 instance running Ubuntu 22.04.&lt;/p&gt;
&lt;p&gt;Let’s cut to the chase…&lt;/p&gt;
&lt;h2 id=&quot;steps&quot;&gt;Steps&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Connect to your server using SSH. If you don’t know how, please follow our guide on &lt;a href=&quot;https://rewaant.com/blog/setup-ssh-keys-on-your-linux-server/&quot;&gt;How to connect to a virtual server using SSH&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Once connected, navigate to the directory containing your &lt;code&gt;php.ini&lt;/code&gt; configuration file. This should be &lt;code&gt;/etc/php/[php_ver]/apache2&lt;/code&gt; which in our case is &lt;code&gt;/etc/php/8.1/apache2&lt;/code&gt; as this server is using PHP version 8.1. Use &lt;code&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;cd&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /etc/php/[php_ver]/apache2&lt;/span&gt;&lt;/code&gt; to navigate and &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; vim&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php.ini&lt;/span&gt;&lt;/code&gt; to open the file in the vim editor. You can also use the nano text editor if you prefer.&lt;/li&gt;
&lt;li&gt;Find the directive &lt;code&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;upload_max_filesize&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; = 2M&lt;/span&gt;&lt;/code&gt; and change this line to &lt;code&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;upload_max_filesize&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; = 128M&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/increase-php-upload-limit-apache/01.png&quot; alt=&quot;php.ini with upload_max_filesize set to 128M.&quot; /&gt;
&lt;ol&gt;
&lt;li&gt;Next, find &lt;code&gt;&lt;span style=&quot;color:#24292E&quot;&gt;max &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;post_max_size&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; = 8M&lt;/span&gt;&lt;/code&gt; and change this line to &lt;code&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;post_max_size&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; = 128M&lt;/span&gt;&lt;/code&gt; as well. Please note in some installations, these directives can have different values as per default or set by a sys admin. The initial values like &lt;code&gt;2M&lt;/code&gt; and &lt;code&gt;8M&lt;/code&gt; are just for reference. What matters is we’re switching it to &lt;code&gt;128M&lt;/code&gt; which should suffice for most basic use cases.&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/increase-php-upload-limit-apache/02.png&quot; alt=&quot;php.ini with post_max_size set to 128M.&quot; /&gt;
&lt;ol&gt;
&lt;li&gt;Exit the editor and restart apache with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; service&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; apache2&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; restart&lt;/span&gt;&lt;/code&gt; . This should reflect the changes.&lt;/li&gt;
&lt;li&gt;Logging in to PHPMyAdmin shows us that we can indeed upload files up to &lt;code&gt;128M&lt;/code&gt; in size.&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/increase-php-upload-limit-apache/03.png&quot; alt=&quot;phpMyAdmin showing an upload limit of 128M.&quot; /&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We should now have PHP applications accept files as big as &lt;code&gt;128MiB&lt;/code&gt; to be uploaded. Keep in mind these changes reflect in the complete server environment. If you’re running an application within some sort of virtualization like a Docker image, you need to make changes in there accordingly.&lt;/p&gt;
&lt;p&gt;Stay tuned for our upcoming how-to’s and technical guides.&lt;/p&gt;
</content:encoded><dc:creator>Rewaant Chhabra</dc:creator><category>Infrastructure</category></item><item><title>Complete guide to Hosting WordPress on Ubuntu or Debian in 2023</title><link>https://rewaant.com/blog/hosting-wordpress-on-ubuntu-or-debian/</link><guid isPermaLink="true">https://rewaant.com/blog/hosting-wordpress-on-ubuntu-or-debian/</guid><description>If you&apos;ve been looking for setting up a WordPress installation on a Ubuntu or Debian server, you&apos;ve come to the right place. In this guide, we take you step by step to setting up your own server, securing and taking WordPress live on your domain.</description><pubDate>Mon, 19 Dec 2022 21:37:58 GMT</pubDate><content:encoded>&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/hero.png&quot; alt=&quot;Title card reading Self-Hosting WordPress on your Linux Server.&quot;&gt;&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;
&lt;p&gt;If you’re looking to build a website or a blog it’s highly likely you’ve decided to use WordPress as your platform of choice which makes up around 43% of all websites on the web. WordPress, as you might know, comes in two flavors:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://WordPress.com&quot;&gt;WordPress.com&lt;/a&gt; → CMS as a service provided by none other than &lt;a href=&quot;https://automattic.com/&quot;&gt;Automattic&lt;/a&gt; a company that officially backs the platform and is headed by &lt;a href=&quot;https://www.google.com/search?q=Matt+Mullenweg&amp;amp;stick=H4sIAAAAAAAAAOPgE-LUz9U3sExPz7NUAjNNU9IKirQUs5Ot9POL0hPzMqsSSzLz81A4Vsmp-YtY-XwTS0oUfEtzclLzylPTd7Ay7mJn4mAAAKqVd29UAAAA&amp;amp;sa=X&amp;amp;ved=2ahUKEwjKhYupsJr7AhWoIzQIHSD9C2UQmxMoAHoECC8QAg&quot;&gt;Matt Mullenweg&lt;/a&gt; one of the original authors/founders of WordPress. Now, this is an excellent offering if you plan to run a blog or a small business website that doesn’t need extensive customization or the need to control plugins. It’s also agreed in the community that once you get past a certain point in your journey as a site owner/administrator, your options for control and customization start becoming limited.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://WordPress.org&quot;&gt;WordPress.org&lt;/a&gt; → An open-source offering of the same CMS by one of the largest communities with 100% control over its setup and customization and all for free. Keep in mind this does expose you to a bit of complexity that you might not want to deal with but when someone says WordPress, it’s highly likely they’re referring to this flavor.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As you might know, self-hosting WordPress is a job in itself and there are many options out there like shared hosting (GoDaddy, NameCheap, Bluehost), quick installs, managed hosting offerings (WPEngine, Kinsta) and some of these companies also offer cloud hosting services that might be useful if you’re on their shared plan and looking to upgrade but still prefer services from a hosting company.&lt;/p&gt;
&lt;p&gt;But, there’s another way that is a little complicated but in our opinion one of the most controllable and customizable options for running your own self-hosted WordPress install. Cloud infrastructure services like AWS, Google Cloud Platform, DigitalOcean, Linode, and more allow you to run a virtual machine (VPS) which essentially acts as your own server with a public-facing IP address attached to it that can serve your WordPress installation. It exposes you to some complexity but is a great option for site and blog owners who are tech/cloud savvy but want to run one or multiple sites or applications on their very own virtual server for as little as $5/mo.&lt;/p&gt;
&lt;p&gt;What’s more, you can even start hosting your site for free (up to 12 months) with offerings like the free tier from AWS and Google Cloud. AWS even offers the first 3 months free on its lesser-priced LightSail instances (one of its less complicated offerings) with similar options from other providers in form of credits. Oracle cloud even has a free forever plan.&lt;/p&gt;
&lt;p&gt;In this complete guide, we’re going to explain in detail how to set up the LAMP stack on Ubuntu 22.04 and configure everything from the domain, and SSL certificates to setting up the WordPress installation and securing the server.&lt;/p&gt;
&lt;p&gt;We’ll get it up and running on one of our subdomains: &lt;a href=&quot;http://testwp.rewaant.com&quot;&gt;testwp.rewaant.com&lt;/a&gt; and also go through some add-ons which make using the server for hosting additional PHP apps and WordPress websites easier in the long run. One of those applications is PHPMyAdmin which is highly useful but optional.&lt;/p&gt;
&lt;p&gt;Let’s shoot!&lt;/p&gt;
&lt;h2 id=&quot;ubuntu-server&quot;&gt;Setting up your Ubuntu server&lt;/h2&gt;
&lt;p&gt;We now need SSH access to the server running Ubuntu, we’re using an AWS EC2 instance in this guide but for the most part, this guide should be good for almost any other service and the steps remain similar once you’re authenticated to an Ubuntu 22.04 server using SSH.&lt;/p&gt;
&lt;p&gt;If you need help connecting to the server with SSH, consider reading our &lt;a href=&quot;https://rewaant.com/blog/setup-ssh-keys-on-your-linux-server/&quot;&gt;Connecting with SSH&lt;/a&gt; guide.&lt;/p&gt;
&lt;p&gt;Once you’re authenticated, you’ll see a screen similar to this one:&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/01.png&quot; alt=&quot;Hosting account dashboard after signing in.&quot; /&gt;
&lt;p&gt;Before working through the initial steps, I’ll recommend updating the server packages and reboot with the following commands:&lt;/p&gt;
&lt;pre class=&quot;shiki github-dark site-ink&quot; style=&quot;background-color:#162538;color:#ffffff&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; apt&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; update&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;shiki github-dark site-ink&quot; style=&quot;background-color:#162538;color:#ffffff&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; apt&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; upgrade&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;shiki github-dark site-ink&quot; style=&quot;background-color:#162538;color:#ffffff&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; reboot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reconnect the server with the SSH command from the terminal. Once you’re connected, our first order of business is to create an administrative user other than the root or default user, the reasons for which are well explained all over the internet. Long story short → root is a superuser and therefore has superuser privileges, executing commands unknowingly can completely break a system and may lead to a loss of hundreds of hours of effort in some cases in addition to financial loss. Hence, we’ll be setting up a user with limited privileges and then add it to sudoers so occasionally when we’re running commands that need attention, the sysadmin will first need to authenticate.&lt;/p&gt;
&lt;h3 id=&quot;setting-up-a-new-user&quot;&gt;Setting up a new user&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; adduser&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; [username] &lt;/span&gt;&lt;/code&gt; → Creates a new user. This will trigger the following screen:&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/02.png&quot; alt=&quot;Prompt for creating a new server user.&quot; /&gt;
&lt;ol&gt;
&lt;li&gt;Fill in all the information as required.&lt;/li&gt;
&lt;li&gt;Once it’s created, we’ll add the user to the sudo group with the command &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; usermod&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -aG&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; [username] &lt;/span&gt;&lt;/code&gt; This will make sure the user can sudo commands which require superuser privileges.&lt;/li&gt;
&lt;li&gt;We now need to create a keypair so that we can SSH into the server with key-based authentication. We’ve written a complete guide on securing SSH access to the server with key-based authentication, please read &lt;a href=&quot;https://rewaant.com/blog/hardening-ssh-on-your-linux-server/&quot;&gt;here&lt;/a&gt; and follow the rest of the tutorial afterward. For the sake of brevity, we’ll continue to set up the rest of the server with the default user.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;securing-with-firewall&quot;&gt;Securing with Firewall&lt;/h3&gt;
&lt;p&gt;Setting up a firewall can help us filter internal traffic sources which add an additional layer of security. Many cloud services offer similar services which are built into the platform like AWS security groups but we’ll be covering native firewall configuration with a program called UFW.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check if the service is already active with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; ufw&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; status&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Make sure that the OpenSSH service is allowed so you don’t get locked out of the system. Use &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; ufw&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; allow&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; OpenSSH&lt;/span&gt;&lt;/code&gt; → This allows all connections over port 22 for both IPv4 and IPv6.&lt;/li&gt;
&lt;li&gt;As we’ll be using this as a web server, we’ll also need to allow port 80 for HTTP and port 443 for HTTPS. Use &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; ufw&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; allow&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; 80&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; ufw&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; allow&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; 443&lt;/span&gt;&lt;/code&gt; . It’s already enabled on our server so it’s skipping adding existing rules.&lt;/li&gt;
&lt;li&gt;Enable firewall with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; ufw&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; enable&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Check the status again with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; ufw&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; status&lt;/span&gt;&lt;/code&gt; You should now see a similar screen:&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/03.png&quot; alt=&quot;UFW status after the firewall rules are added.&quot; /&gt;
&lt;p&gt;This should set up the firewall for good. Other than SSH, HTTP, and HTTPS, all connections to the server are rejected.&lt;/p&gt;
&lt;p&gt;Our initial server setup is complete, we’ll now set up the LAMP stack which stands for Linux, Apache, MySQL, and PHP that enables us to run WordPress off an Ubuntu server.&lt;/p&gt;
&lt;h2 id=&quot;lamp-stack&quot;&gt;Setting up the LAMP stack&lt;/h2&gt;
&lt;h3 id=&quot;installing-the-apache-web-server&quot;&gt;Installing the Apache web server&lt;/h3&gt;
&lt;p&gt;On the terminal window, type in the following commands:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; apt&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; install&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; apache2&lt;/span&gt;&lt;/code&gt; → Installs the Apache web server.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; ufw&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; status&lt;/span&gt;&lt;/code&gt; → Make sure ports 80 and 443 are allowed.&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/04.png&quot; alt=&quot;UFW status showing ports 80 and 443 allowed.&quot; /&gt;
&lt;ol&gt;
&lt;li&gt;Access the server homepage to verify that apache’s up and running. Type in the public IP address of your server in the following format: &lt;code&gt;http://[your_server_ip_address]&lt;/code&gt; It should look something like this:&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/05.png&quot; alt=&quot;Apache&apos;s default page opened at the server IP address.&quot; /&gt;
&lt;h3 id=&quot;installing-the-mysql-database-server&quot;&gt;Installing the MySQL database server&lt;/h3&gt;
&lt;p&gt;Once the web server is installed and we can access the Apache home page, we’ll install MySQL as our choice of database server. Execute the following commands:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; apt&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; install&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; mysql-server&lt;/span&gt;&lt;/code&gt; → This will install MySQL along with all of its dependencies. Type in &lt;code&gt;Y&lt;/code&gt; when prompted to continue.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; mysql_secure_installation&lt;/span&gt;&lt;/code&gt; → This will secure the database server as we’re using it in a production environment. Make sure you keep the &lt;code&gt;VALIDATE PASSWORD&lt;/code&gt; plugin disabled. Choose the root password of your choice and make sure to remember or write it down. If you get a failed error, we’ll set the root password using the &lt;code&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; USER&lt;/span&gt;&lt;/code&gt; command: use &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; mysql&lt;/span&gt;&lt;/code&gt; then, once you’re in at the repl interface, use &lt;code&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; USER&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; &apos;root&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;%&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; IDENTIFIED &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;WITH&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; mysql_native_password &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;by&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;your_new_password&apos;&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;;&lt;/span&gt;&lt;/code&gt; . Re-run &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; mysql_secure_installation&lt;/span&gt;&lt;/code&gt; again.&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/06.png&quot; alt=&quot;mysql_secure_installation prompts.&quot; /&gt;
&lt;ol&gt;
&lt;li&gt;Try entering the mysql server with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;mysql&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -u&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -p&lt;/span&gt;&lt;/code&gt; command. It should now prompt for the root password and let you in.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We’ve finished the initial configuration of MySQL on our server.&lt;/p&gt;
&lt;h3 id=&quot;installing-and-configuring-php-and-its-dependencies&quot;&gt;Installing and configuring PHP and its dependencies&lt;/h3&gt;
&lt;p&gt;Type in the following commands:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; apt&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; install&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; libapache2-mod-php&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php-mysql&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php-curl&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php-gd&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php-mbstring&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php-xml&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php-xmlrpc&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php-soap&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php-intl&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php-zip&lt;/span&gt;&lt;/code&gt; → Installs PHP module for apache, mysql, and other extensions for WordPress.&lt;/li&gt;
&lt;li&gt;Test PHP installation with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;php&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -v&lt;/span&gt;&lt;/code&gt; . If you get a similar output, you’re good to go.&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/07.png&quot; alt=&quot;Output of php -v confirming PHP is installed.&quot; /&gt;
&lt;h3 id=&quot;creating-an-apache-virtual-host&quot;&gt;Creating an Apache virtual host&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;First of all, we’ll create a directory where our website will be served from. Navigate to &lt;code&gt;/var/www&lt;/code&gt; and execute &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; mkdir&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/domain_name&lt;/span&gt;&lt;/code&gt; . In our case, it’ll be &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; mkdir&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/testwp.rewaant.com&lt;/span&gt;&lt;/code&gt; .&lt;/li&gt;
&lt;li&gt;Next, we’ll assign the ownership of the directory to the apache user which is &lt;code&gt;www-data&lt;/code&gt; . Type in &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; chown&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -R&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; www-data:www-data&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/your_domain&lt;/span&gt;&lt;/code&gt; this grants apache’s user, the directory ownership. Make sure you also add your admin user to the &lt;code&gt;www-data&lt;/code&gt; group so you can write files in the directory with FTP or if a need arises in the future.&lt;/li&gt;
&lt;li&gt;Navigate to &lt;code&gt;/etc/apache2/sites-available/&lt;/code&gt; and type in &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; vim&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; your_domain.conf&lt;/span&gt;&lt;/code&gt; . In our case, it’ll be &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; vim&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; testwp.rewaant.com.conf&lt;/span&gt;&lt;/code&gt; . You can also use the nano text editor if you prefer.&lt;/li&gt;
&lt;li&gt;Type in the following to configure the server:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;shiki github-dark site-ink&quot; style=&quot;background-color:#162538;color:#ffffff&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;VirtualHost&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; *:80&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ServerName testwp.rewaant.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ServerAlias www.testwp.rewaant.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ServerAdmin rewaant@rewaant.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    DocumentRoot /var/www/testwp.rewaant.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ErrorLog ${APACHE_LOG_DIR}/error.log&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    CustomLog ${APACHE_LOG_DIR}/access.log combined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;Directory&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt; /var/www/testwp.rewaant.com/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        AllowOverride All&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;Directory&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;VirtualHost&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Make sure you replace the domain configuration with your own and save the file by pressing &lt;code&gt;Esc&lt;/code&gt; typing &lt;code&gt;:wq!&lt;/code&gt; and exit.&lt;/li&gt;
&lt;li&gt;Type in &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; a2ensite&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; your_domain&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; a2dissite&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; 000-default&lt;/span&gt;&lt;/code&gt; → This enables vhost for your site and disables default access to the server.&lt;/li&gt;
&lt;li&gt;Test apache configuration with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; apache2ctl&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; configtest&lt;/span&gt;&lt;/code&gt; make sure it returns &lt;code&gt;Syntax OK&lt;/code&gt; .&lt;/li&gt;
&lt;li&gt;Reload the configuration with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; systemctl&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; reload&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; apache2&lt;/span&gt;&lt;/code&gt; .&lt;/li&gt;
&lt;li&gt;Remember, at this point, we haven’t pointed the domain to our server’s IP. We’ll do that next.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;configuring-the-domain&quot;&gt;Configuring the domain&lt;/h3&gt;
&lt;p&gt;We simply need to add two records to our DNS manager (in our case it’s Cloudflare.) An A record should point to the IP address and a CNAME record for www should point to the apex domain. This should be configured just like in the screenshots:&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/08.png&quot; alt=&quot;DNS records pointing the domain at the server.&quot; /&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/09.png&quot; alt=&quot;DNS records pointing the domain at the server.&quot; /&gt;
&lt;p&gt;We’ll now go back to the terminal and create a file &lt;code&gt;index.html&lt;/code&gt; with the following content:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span style=&quot;color:#24292E&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;&amp;gt;Our Site Works!&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt; → This isn’t the cleanest HTML site but gets the job done for us 😉&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Navigate: &lt;code&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;cd&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/site_directory&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create a file with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; vim&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; index.html&lt;/span&gt;&lt;/code&gt; and paste the above HTML code. Save and exit with &lt;code&gt;Esc&lt;/code&gt; + &lt;code&gt;:wq!&lt;/code&gt; and test the link with the URL. In our case, &lt;code&gt;testwp.rewaant.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;You should see something similar and this means that the site’s configured with our domain name.&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/10.png&quot; alt=&quot;The site responding on its domain name.&quot; /&gt;
&lt;h3 id=&quot;configuring-the-direcotryindex-on-apache&quot;&gt;Configuring the DirecotryIndex on Apache&lt;/h3&gt;
&lt;p&gt;We need the server to make sure that &lt;code&gt;*.php&lt;/code&gt; take precedence over other extensions like &lt;code&gt;*.html&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Type in &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; vim&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /etc/apache2/mods-enabled/dir.conf&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Add index.php before index.html as shown below&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/11.png&quot; alt=&quot;Apache directory index with index.php listed first.&quot; /&gt;
&lt;ol&gt;
&lt;li&gt;Reload apache configuration with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; systemctl&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; reload&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; apache2&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create a new file &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; vim&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/site_directory/info.php&lt;/span&gt;&lt;/code&gt; and add the following content: &lt;code&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;php&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; phpinfo&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Test the link with the site URL and you should something similar:&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/12.png&quot; alt=&quot;The site URL after the directory index change.&quot; /&gt;
&lt;ol&gt;
&lt;li&gt;Make sure you remove the index.html and index.php files before proceeding as they are a security risk to be exposed to the public.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We now have the LAMP stack up and running properly. Next up, we’ll secure the domain on the server with Let’s Encrypt certificates.&lt;/p&gt;
&lt;h2 id=&quot;ssl-certs&quot;&gt;Setting up Let’s Encrypt SSL Certificates&lt;/h2&gt;
&lt;p&gt;In order to setup free SSL certificates with Let’s Encrypt, we need a command line program called certbot setup on our server.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Execute &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; apt&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; install&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; certbot&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; python3-certbot-apache&lt;/span&gt;&lt;/code&gt; → This will install certbot and its apache supported plugin that’ll automate the whole process.&lt;/li&gt;
&lt;li&gt;Type in &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; certbot&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -d&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; domain_name&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -d&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; www.domain_name&lt;/span&gt;&lt;/code&gt; . In our case, this becomes &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; certbot&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -d&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; testwp.rewaant.com&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -d&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; www.testwp.rewaant.com&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;It’ll prompt you for an admin email and acceptance of TOS. After that, it’ll validate and authenticate the domains.&lt;/li&gt;
&lt;li&gt;If it asks you to either set a redirect, select &lt;code&gt;2&lt;/code&gt; so all requests are routed to HTTPS.&lt;/li&gt;
&lt;li&gt;Verify that certificate’s auto-renewal service is active. Use &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; systemctl&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; status&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; certbot.timer&lt;/span&gt;&lt;/code&gt; and make sure it outputs as &lt;code&gt;“active (waiting)”&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Also, test the renewal process with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; certbot&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; renew&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; --dry-run&lt;/span&gt;&lt;/code&gt; . This will simulate a renewal and let you know if it’s working properly.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Your domain should now be secured and served automatically through HTTPS. Next up, we’ll setup WordPress itself.&lt;/p&gt;
&lt;h2 id=&quot;installing-wordpress&quot;&gt;Installing WordPress&lt;/h2&gt;
&lt;p&gt;Finally, let’s set up WordPress:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We need to create a database and a user for the WordPress installation. Enter mysql with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;mysql&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -u&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -p&lt;/span&gt;&lt;/code&gt; provide the root password you selected earlier in the tutorial.&lt;/li&gt;
&lt;li&gt;Create a new database with &lt;code&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; DATABASE&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; wp_test&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; DEFAULT&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; CHARACTER&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; SET&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; utf8 &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;COLLATE&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; utf8_unicode_ci;&lt;/span&gt;&lt;/code&gt; Feel free to type in your preferred database name in place of wp_test. Make sure to replace in the following lines.&lt;/li&gt;
&lt;li&gt;Create a new user specific to this WordPress installation with &lt;code&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; USER&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; &apos;&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;testuser&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;&apos;@&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;%&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; IDENTIFIED &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;WITH&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; mysql_native_password &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;BY&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; &apos;password&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;;&lt;/span&gt;&lt;/code&gt; Replace with appropriate credentials.&lt;/li&gt;
&lt;li&gt;Now we need to grant all privileges on the WordPress database to this newly created user. Use &lt;code&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;GRANT&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; ALL &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; wp_test.&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; TO&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; &apos;testuser&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;%&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Let’s make the credentials work by flushing privileges, type in &lt;code&gt;&lt;span style=&quot;color:#24292E&quot;&gt;FLUSH PRIVILEGES;&lt;/span&gt;&lt;/code&gt; . Type &lt;code&gt;&lt;span style=&quot;color:#24292E&quot;&gt;EXIT;&lt;/span&gt;&lt;/code&gt; to get out of mysql repl. We now have the database part all set.&lt;/li&gt;
&lt;li&gt;Download WordPress to the temporary directory. Use &lt;code&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;cd&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /tmp&lt;/span&gt;&lt;/code&gt; . Download with the command: &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -O&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; https://wordpress.org/latest.tar.gz&lt;/span&gt;&lt;/code&gt; . Extract into its directory structure with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;tar&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; xzvf&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; latest.tar.gz&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Add a .htaccess file with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;touch&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /tmp/wordpress/.htaccess&lt;/span&gt;&lt;/code&gt; and copy the configuration file for production with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;cp&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /tmp/wordpress/wp-config-sample.php&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /tmp/wordpress/wp-config.php&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Lastly, create a &lt;code&gt;upgrade&lt;/code&gt; directory so it can process updates automatically. Type in &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;mkdir&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /tmp/wordpress/wp-content/upgrade&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Now copy the WordPress directory files to the site’s root directory. In our case, this command becomes: &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; cp&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -a&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /tmp/wordpress/.&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/testwp.rewaant.com&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Now, we’ll adjust the ownership and set the adequate file and directory permission values for WordPress. Use &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; chown&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -R&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; www-data:www-data&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/site_dir&lt;/span&gt;&lt;/code&gt; in our case it’s &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; chown&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -R&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; www-data:www-data&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/testwp.rewaant.com&lt;/span&gt;&lt;/code&gt; . For setting directory permissions, use &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; find&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/site_dir/&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -type&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -exec&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; chmod&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; 750&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; {}&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; \;&lt;/span&gt;&lt;/code&gt; and for file permissions, use &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; find&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/site_dir/&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -type&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; f&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -exec&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; chmod&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; 640&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; {}&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; \;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Let’s set up the WordPress configuration file now. Grab salt values with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -s&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; https://api.wordpress.org/secret-key/1.1/salt/&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;You’ll see something similar:&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/13.png&quot; alt=&quot;WordPress secret keys returned by the salt API.&quot; /&gt;
&lt;ol&gt;
&lt;li&gt;Copy and replace the values in the wp-config.php file. Use vim wp-config.php and replace copied values in place of all the define(…, ‘put your unique values here’) constants. It should look like this once values are replaced:&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/14.png&quot; alt=&quot;Unique keys pasted into wp-config.php.&quot; /&gt;
&lt;ol&gt;
&lt;li&gt;We now need to update the database configuration as well. Make sure you have the database name and the user privileged to perform CRUD ops on that DB. Once you’re ready, replace the constants with the database name, username and it’s password. Use vim wp-config.php again and once it’s updated should look something like this:&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/15.png&quot; alt=&quot;Database name and user filled in on wp-config.php.&quot; /&gt;
&lt;ol&gt;
&lt;li&gt;Hit Esc and use: &lt;code&gt;wq!&lt;/code&gt; to save changes and exit.&lt;/li&gt;
&lt;li&gt;If we’ve set up the configuration file correctly and completed all these steps in sequence properly, we should now be ready to complete our installation through the web interface. Head over to the web address which in our case is &lt;code&gt;https://testwp.rewaant.com/&lt;/code&gt; Once we’re there we should have the WordPress-guided installation available for use. From then on setting it up is a piece of cake. You now have a basic WordPress self-hosted installation up and running.&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/16.png&quot; alt=&quot;WordPress installation screen for choosing a language.&quot; /&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/17.png&quot; alt=&quot;WordPress form for the site title, username, and email.&quot; /&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/18.png&quot; alt=&quot;WordPress success screen after installation.&quot; /&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/19.png&quot; alt=&quot;WordPress login screen.&quot; /&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/20.png&quot; alt=&quot;The new WordPress site showing the Hello world post.&quot; /&gt;
&lt;p&gt;So that’s it, folks! We’re now running a completely self-hosted copy of WordPress on an Ubuntu server we almost set up from scratch. A lot of the things we’ve done could be further elaborated on or followed for specific requirements but there you have it for setting up a basic WordPress installation on a cloud server.&lt;/p&gt;
&lt;p&gt;In the next (optional) section, we’ll be setting up PHPMyAdmin on the server which is a tool highly recommended if you regularly need maintenance work done or are planning to serve several websites from this server.&lt;/p&gt;
&lt;h2 id=&quot;configuring-phpmyadmin&quot;&gt;Configuring PHPMyAdmin (optional)&lt;/h2&gt;
&lt;p&gt;PHPMyAdmin is a great tool for site administrators who maintain PHP and MySQL websites. We’ll cut to the chase and quickly show how you can get it up and running on your Ubuntu server.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We’ll start by updating all the packages: &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; apt&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; update&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;We’ll install all the required packages: &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; apt&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; install&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; phpmyadmin&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php-mbstring&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php-zip&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php-gd&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php-json&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; php-curl&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Make sure you choose &lt;code&gt;apache2&lt;/code&gt; in the following screen:&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/21.png&quot; alt=&quot;phpMyAdmin setup screen with Apache selected.&quot; /&gt;
&lt;ol&gt;
&lt;li&gt;Choose Yes to use dconfig-common in the following screen:&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/22.png&quot; alt=&quot;phpMyAdmin prompt to use dbconfig-common.&quot; /&gt;
&lt;ol&gt;
&lt;li&gt;Type in the MySQL application password when prompted:&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/23.png&quot; alt=&quot;Prompt for the MySQL application password.&quot; /&gt;
&lt;ol&gt;
&lt;li&gt;Once done, enable the php mbstring module with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; phpenmod&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; mbstring&lt;/span&gt;&lt;/code&gt; and restart apache with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; systemctl&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; restart&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; apache2&lt;/span&gt;&lt;/code&gt; .&lt;/li&gt;
&lt;li&gt;You should now be able to access PHPMyAdmin at &lt;code&gt;https://[your_domain]/phpmyadmin&lt;/code&gt; . Make sure you can log in with the root user.&lt;/li&gt;
&lt;li&gt;In the event that you’re getting a 404 Not Found Error, open &lt;code&gt;/etc/apache2/apache2.conf&lt;/code&gt; and append &lt;code&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;Include&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; /etc/phpmyadmin/apache.conf&lt;/span&gt;&lt;/code&gt; to the end of the file. Restart the apache2 service with &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; systemctl&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; restart&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; apache2&lt;/span&gt;&lt;/code&gt; . It should now work well.&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/24.png&quot; alt=&quot;Apache configuration updated so phpMyAdmin can load.&quot; /&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-wordpress-on-ubuntu-or-debian/25.png&quot; alt=&quot;Apache configuration updated so phpMyAdmin can load.&quot; /&gt;
&lt;ol&gt;
&lt;li&gt;You may also need to increase the allowed upload limit for PHPMyAdmin from 2Mib to 128Mib or 256Mib to allow for importing larger database sizes. We’ve written a quick blog post on how to do that here .&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are a few more things that can be done to improve site/server performance as well as the flexibility to allow larger file uploads and requirement-specific configuration for PHP, Apache, and MySQL but I believe this guide is already getting too long. Please check other guides on related topics as well as keep a check on upcoming content.&lt;/p&gt;
&lt;p&gt;If you face any issues following this guide, feel free to comment for help below or reach out directly to us at: &lt;a href=&quot;mailto:hello@rewaant.com&quot;&gt;hello@rewaant.com&lt;/a&gt;&lt;/p&gt;
</content:encoded><dc:creator>Rewaant Chhabra</dc:creator><category>WordPress</category></item><item><title>Complete guide to hosting Ghost CMS on Ubuntu or Debian</title><link>https://rewaant.com/blog/hosting-ghost-on-ubuntu-or-debian/</link><guid isPermaLink="true">https://rewaant.com/blog/hosting-ghost-on-ubuntu-or-debian/</guid><description>If you&apos;ve been thinking about setting up and self-hosting your own Ghost CMS blog or publication, you&apos;ve come to the right place. In this guide, we take you step by step to setting up your own server, securing and taking Ghost live on your domain.</description><pubDate>Sun, 18 Sep 2022 13:00:49 GMT</pubDate><content:encoded>&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/hero.png&quot; alt=&quot;Title card reading Self-Hosting Ghost CMS on your Linux Server.&quot;&gt;&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#overview&quot;&gt;Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#setting-up-vps&quot;&gt;Setting up your VPS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#updating-dns-records&quot;&gt;Updating DNS records to point the domain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#server-setup&quot;&gt;Setting up your server for serving Ghost&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#setting-up-publication&quot;&gt;Setting up the publication and going live&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://Ghost.org&quot;&gt;Ghost.org&lt;/a&gt; is a modern, open-source CMS and a full-fledged publishing platform used by content creators, news outlets, businesses, bloggers, and professional publishers. There are many CMS options to choose from but one thing that differentiates Ghost from all the other solutions is an exceptional focus on being the most approachable publishing solution.&lt;/p&gt;
&lt;p&gt;While you can build almost anything with WordPress, Ghost’s competency as a CMS which is primarily focused on content creation, publishing, and building your audience sets it apart in an ocean of platforms. Other attributes like embracing minimalism while also providing common tools for publishing such as newsletters and membership features out of the box and on top of it being open source gives it a serious edge and we suggest you give them serious consideration if those are your goals. Not to mention, these features may require plugins/extensions and third-party solutions with alternatives.&lt;/p&gt;
&lt;p&gt;Another thing to mention is that Ghost is built on top of a modern tech stack using Node.js which makes it fast and snappy as compared to many alternatives. Safe to say your content will be in good hands.&lt;/p&gt;
&lt;p&gt;Ghost comes in two flavors:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ghost Pro: Think of this as being similar to &lt;a href=&quot;https://WordPress.com&quot;&gt;WordPress.com&lt;/a&gt; . We recommend visiting the official &lt;a href=&quot;https://ghost.org/pricing/&quot;&gt;pricing page&lt;/a&gt; , analyzing your requirements, calculating estimated costs, and reading the FAQs to see if this will be a good option. They don’t offer a free plan but you can sign up with a 14-day free trial. However, we’ll NOT be focusing on this offering in this guide.&lt;/li&gt;
&lt;li&gt;Self-hosting Ghost: Ghost is open source software which means you can use it as a self-hosted publishing platform (just like &lt;a href=&quot;http://WordPress.org&quot;&gt;WordPress.org&lt;/a&gt; ) on your own server if you want complete control over your publication, have some cost constraints and you plan on using a cost-effective VPS or for any other reason. You lose official support and bear additional responsibilities of managing everything on your own with this option but the official community forums are generally helpful in case you need some help. This also gives you complete control.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this comprehensive guide, we’ll try to help you set up an Ubuntu production server from scratch, configure an ideal production environment, set things up with your domain, and install Ghost to get started on serving your audience. You can also use DigitalOcean, AWS, GCP, or other cloud platforms as per your preference but the process varies from platform to platform.&lt;/p&gt;
&lt;p&gt;Let’s get started.&lt;/p&gt;
&lt;h2 id=&quot;setting-up-vps&quot;&gt;Setting up your VPS&lt;/h2&gt;
&lt;p&gt;If you already have a VPS up and running, you can skip to the next section. For simplicity, we’ll be using Linode in our reference material but the principles should apply to other cloud providers as well.&lt;/p&gt;
&lt;p&gt;Once you have signed in/up on Linode, you’ll see a screen similar to the one below:&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/01.jpeg&quot; alt=&quot;Linode dashboard after signing in.&quot; /&gt;
&lt;p&gt;Click on the “Create Linode”. This should take you to a detailed screen where you can customize an instance. We’re using Ubuntu 22.04 LTS as our distribution, for most use cases we recommend you choose Ubuntu’s latest LTS release. The region of choice should be closest to your or your ideal traffic location geographically. We’re setting up a test server so we’ll choose London.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/02.jpeg&quot; alt=&quot;Linode create screen with Ubuntu 22.04 selected.&quot; /&gt;
&lt;p&gt;For the plan, we’re selecting “Shared CPU, Linode (4GB)” which goes for $20/month. This should be more than enough for most individual publishers starting out with not much traffic.&lt;/p&gt;
&lt;p&gt;The label is just for your reference, set it as per your preference. You can skip the tags for now.&lt;/p&gt;
&lt;p&gt;Set a strong root password that you can remember or write it down somewhere. This is very important!&lt;/p&gt;
&lt;p&gt;SSH Keys are the recommended way to authenticate and administer your remote servers for multiple reasons. More on this later.&lt;/p&gt;
&lt;p&gt;Skip the VLAN section.&lt;/p&gt;
&lt;p&gt;We highly recommend choosing a backup plan, can’t count how many times clients have reached out with bad news that their site’s gone (wiped out) and they’re looking for options to somehow retrieve all their lost efforts. Bad for them they didn’t have backups in place.&lt;/p&gt;
&lt;p&gt;Backups in Linode are priced according to the plan you choose. In our case, it’s $5/month, for the $5/month instance they go for $2/month. Keep in mind the pricing included here is just for reference and as of the day, it’s last updated. Please check the updated pricing on Linode’s official pricing pages.&lt;/p&gt;
&lt;p&gt;You can skip the Private IP section for now.&lt;/p&gt;
&lt;p&gt;Review the summary, check the required checkboxes and hit “Create Linode”&lt;/p&gt;
&lt;p&gt;You should get a notification that your Linode is being created. Soon, the status should be changed to running and you should see a similar screen. Please note your instance’s IP address and the ssh command as we’ll need them in the next steps to set things up.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/03.jpeg&quot; alt=&quot;A running Linode with its IP address shown.&quot; /&gt;
&lt;h2 id=&quot;updating-dns-records&quot;&gt;Updating DNS records to point the domain&lt;/h2&gt;
&lt;p&gt;Before setting up the instance, we’ll get the domain part out of the way. In our case, we’ll be using this server for a Ghost publication reachable on a subdomain &lt;a href=&quot;https://ghost.rewaant.com/&quot;&gt;https://ghost.rewaant.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We use Cloudflare, adding/updating records for your domain might vary depending on the platform you use for managing the domain’s nameservers.&lt;/p&gt;
&lt;p&gt;For the most part, you just need to add an A and a CNAME record for your Ghost publication to be accessible publicly.&lt;/p&gt;
&lt;p&gt;Add an &lt;strong&gt;A&lt;/strong&gt; record with the following configuration:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We’re putting “ &lt;code&gt;ghost&lt;/code&gt; “in the Name field. If you’re pointing the apex/root domain to the server, use “@”. If your domain is &lt;code&gt;example.com&lt;/code&gt; , use “@” in the Name field so &lt;code&gt;https://example.com&lt;/code&gt; points to your publication.&lt;/li&gt;
&lt;li&gt;Put in the IPv4 address of your Ubuntu server. This is the IP address you noted down while creating the Linode instance. This will be your server’s IP address if you already had a server setup and didn’t follow the previous section.&lt;/li&gt;
&lt;li&gt;TTL field should be set to Auto, and hit “Save”.&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/04.jpeg&quot; alt=&quot;DNS record with TTL set to Auto.&quot; /&gt;
&lt;p&gt;Add a &lt;strong&gt;CNAME&lt;/strong&gt; record with the following configuration:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We’re putting in &lt;code&gt;&amp;quot;www.ghost&lt;/code&gt; ” in the Name field. If you’re pointing the apex/root domain, use “ &lt;code&gt;www&lt;/code&gt; “. If your domain is &lt;code&gt;example.com&lt;/code&gt; , use “ &lt;code&gt;www&lt;/code&gt; ” in the Name field so &lt;code&gt;https://www.example.com&lt;/code&gt; points to your publication.&lt;/li&gt;
&lt;li&gt;We’re putting “ &lt;code&gt;ghost.rewaant.com&lt;/code&gt; ” in the Target field. We’re doing this because we want all requests for “ &lt;a href=&quot;http://www.ghost.rewaant.com&quot;&gt;&lt;code&gt;www.ghost.rewaant.com&lt;/code&gt;&lt;/a&gt; ” to be resolved to &lt;code&gt;ghost.rewaant.com&lt;/code&gt; . If your domain is &lt;a href=&quot;http://example.com&quot;&gt;&lt;code&gt;example.com&lt;/code&gt;&lt;/a&gt; use “ &lt;code&gt;example.com&lt;/code&gt; ” in the Target field so all requests to “ &lt;a href=&quot;http://www.ghost.rewaant.com&quot;&gt;&lt;code&gt;www.example.com&lt;/code&gt;&lt;/a&gt; ” will be resolved to “ &lt;a href=&quot;http://www.ghost.rewaant.com&quot;&gt;&lt;code&gt;example.com&lt;/code&gt;&lt;/a&gt; “.&lt;/li&gt;
&lt;li&gt;Hit “Save”.&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/05.jpeg&quot; alt=&quot;CNAME record pointing www at the Ghost hostname.&quot; /&gt;
&lt;p&gt;If this doesn’t work as expected, or you’re trying to set up a different structure, we recommend you follow a domain-specific guide or post your detailed issue directly in the comments section below.&lt;/p&gt;
&lt;p&gt;You can now ping your domain to check connectivity. That’s it, we’re good to go to the next step.&lt;/p&gt;
&lt;h2 id=&quot;server-setup&quot;&gt;Setting up your server for serving Ghost&lt;/h2&gt;
&lt;p&gt;To connect to your VPS, you can either use a web console provided by most cloud providers or a terminal window on your computer. If you’re using Linode, the web console is called LISH console (click “Launch LISH Console”). You can also connect via a local terminal session using the ssh command directly on a terminal window. Important: If you’re using Windows, you’ll need to use a third-party software called Putty to connect to your instance. We’ll post a guide on how to connect to an instance via SSH on Windows using Putty and PuttyGen.&lt;/p&gt;
&lt;p&gt;Once connected, you should see a window similar to the one below. Type in “yes” to continue, it’ll then ask for the root password. Type in the root password you set while creating the instance.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/06.png&quot; alt=&quot;First SSH connection prompt, asking to trust the server.&quot; /&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/07.png&quot; alt=&quot;First SSH connection prompt, asking to trust the server.&quot; /&gt;
&lt;p&gt;We’ll start with performing system updates and securing our server. If you’re setting up a production server, we highly recommend you set up key-based authentication and disable password-based authentication. We also recommend you do this before following the remaining steps of this guide. You can learn more about how to do this by following our concise guide: &lt;a href=&quot;https://rewaant.com/blog/setup-ssh-keys-on-your-linux-server/&quot;&gt;How to setup SSH keys on your Linux server&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To perform updates, type in the following commands:&lt;/p&gt;
&lt;p&gt;apt update &amp;amp;&amp;amp; apt upgrade → Once you run this command, you’ll see a somewhat similar output. Type in Y to continue. This should take a little while to complete but should upgrade all the packages and libraries.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/08.png&quot; alt=&quot;Output of apt update and apt upgrade.&quot; /&gt;
&lt;p&gt;reboot → It’s recommended to reboot after processing updates. Allow a minute or two and reconnect via SSH following steps 1 and 2.&lt;/p&gt;
&lt;p&gt;To set up the timezone, type in the following commands:&lt;/p&gt;
&lt;p&gt;dpkg-reconfigure tzdata → This should take you to the following screen, Choose the timezone with the up/down arrow &amp;amp; enter keys then use the tab key to navigate and hit “Ok”.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/09.png&quot; alt=&quot;Timezone selection in dpkg-reconfigure tzdata.&quot; /&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/10.png&quot; alt=&quot;Timezone confirmation in dpkg-reconfigure tzdata.&quot; /&gt;
&lt;p&gt;You should now get back to the console.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/11.png&quot; alt=&quot;Server console after the timezone is set.&quot; /&gt;
&lt;p&gt;Before proceeding further, we recommend not using root for system administration. It’s highly recommended to set up a new (less privileged) user for server administration. Type in the following commands to add a less privileged user:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;adduser&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;preferred_username&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;*&lt;/span&gt;&lt;/code&gt; → Type in your username in place of &lt;code&gt;*“preferred_username”*&lt;/code&gt;, we’ll be using “&lt;code&gt;rewaant&lt;/code&gt;” so the command becomes &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;adduser&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; rewaant&lt;/span&gt;&lt;/code&gt;. This will now ask for a new password, set a strong password. Type in the Full Name and skip the info for defaults that you don’t want to populate. Type in &lt;code&gt;Y&lt;/code&gt; to continue and your new user should be created.&lt;/p&gt;
&lt;p&gt;Type in &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;adduser&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;preferred_username&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; sudo&lt;/span&gt;&lt;/code&gt; → Replace &lt;code&gt;*“preferred_username”*&lt;/code&gt; with your username. In our case, the command becomes &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;adduser&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; rewaant&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; sudo&lt;/span&gt;&lt;/code&gt;. This command adds the new user to the sudo group which grants root privileges to the user when prefixed with &lt;code&gt;sudo&lt;/code&gt;.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/12.png&quot; alt=&quot;Command adding the new user to the sudo group.&quot; /&gt;
&lt;p&gt;Disconnect and reconnect using the ssh command replacing “root” with the new user. The updated ssh command becomes ssh &lt;em&gt;preferred_username&lt;/em&gt;@&lt;em&gt;server_ip_address&lt;/em&gt;. In our case, this becomes ssh rewaant@176.58.98.58. You should now be able to authenticate with the newly created user.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/13.png&quot; alt=&quot;SSH session reconnected as the new user.&quot; /&gt;
&lt;p&gt;Next, we’ll harden access through SSH and set up a firewall. Please follow our guide that explains how to do both here: &lt;a href=&quot;https://rewaant.com/blog/hardening-ssh-on-your-linux-server/&quot;&gt;Hardening SSH on your Linux server&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now that we have a server setup, domain pointed, and our server secured, we can proceed to set up the stack and install ghost itself on the server. According to the official Ghost docs, we have the following prerequisites:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ubuntu 16.04, Ubuntu 18.04, Ubuntu 20.04 or Ubuntu 22.04 → Check&lt;/li&gt;
&lt;li&gt;NGINX (minimum of 1.9.5 for SSL)&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;&lt;a href=&quot;https://ghost.org/docs/faq/node-versions/&quot;&gt;supported version&lt;/a&gt;&lt;/strong&gt; of &lt;strong&gt;&lt;a href=&quot;https://nodejs.org/&quot;&gt;Node.js&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;MySQL 8&lt;/li&gt;
&lt;li&gt;Systemd → Check&lt;/li&gt;
&lt;li&gt;A server with at least 1GB memory → Check&lt;/li&gt;
&lt;li&gt;A registered domain name → Check&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ll start with installing NGINX (Web Server), MySQL (Database Server), and the recent LTS version of Node.js. Execute the following commands:&lt;/p&gt;
&lt;p&gt;sudo apt-get install nginx → This will install Nginx. Also, make sure to allow ufw for HTTP and HTTPS connection with this command: sudo ufw allow ‘Nginx Full’&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/14.png&quot; alt=&quot;Terminal output from installing Nginx.&quot; /&gt;
&lt;p&gt;sudo apt-get install mysql-server → This will install the MySQL database server.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/15.png&quot; alt=&quot;Terminal output from installing MySQL.&quot; /&gt;
&lt;p&gt;curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash → This will add the APT repo for Node 16 to the package manager’s sources.&lt;/p&gt;
&lt;p&gt;sudo apt-get install -y nodejs → This will install Node.js&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/16.png&quot; alt=&quot;Terminal output from installing Node.js.&quot; /&gt;
&lt;p&gt;Next, we’ll install the Ghost-CLI which is a command line utility to install and manage Ghost installations. Execute sudo npm install ghost-cli@latest -g → This will install the latest version of ghost-cli globally.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/17.png&quot; alt=&quot;Terminal output from installing Ghost-CLI.&quot; /&gt;
&lt;p&gt;Before we install Ghost, it’s highly recommended that you secure MySQL. We’ll do it with the following commands:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; mysql&lt;/span&gt;&lt;/code&gt; → This will log you in to MySQL as root.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; USER&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; &apos;root&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;localhost&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; IDENTIFIED &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;WITH&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; mysql_native_password &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;by&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;your_new_password&apos;&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;;&lt;/span&gt;&lt;/code&gt; → This will set a root password. Make sure to replace &lt;code&gt;*&apos;your_new_password&apos;&lt;/code&gt;* with your password of choice and remember this for future reference or save/write it down.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/18.png&quot; alt=&quot;MySQL command setting the root password.&quot; /&gt;
&lt;p&gt;Run sudo mysql_secure_installation. Type in the root password set in the previous step, type in “No” for Validate Password Component, Type in “No” for the prompt to change the root password, type in Y to remove anonymous users, type in Y to disallow root login remotely, type in Y to remove test database, type in Y to reload privilege tables now and hit Return. It should now output an “All done!” message.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/19.png&quot; alt=&quot;mysql_secure_installation prompts.&quot; /&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/20.png&quot; alt=&quot;mysql_secure_installation prompts.&quot; /&gt;
&lt;p&gt;We’re now ready to install ghost. Execute the following commands:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; mkdir&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -p&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;sitename&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;*&lt;/span&gt;&lt;/code&gt; → Creates a directory to host your site. In our case, this command becomes &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; mkdir&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; -p&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/ghost.rewaant.com&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; chown&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;usernam&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;usernam&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;sitename&lt;/span&gt;&lt;/code&gt; →* Changes the directory owner to our limited user. This helps us run the ghost install script. In our case, this command becomes &lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; chown&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; rewaant:rewaant&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/ghost.rewaant.com&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; chmod&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; 775&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/ghost.rewaant.com&lt;/span&gt;&lt;/code&gt; → Sets the proper directory permissions.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;cd&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; /var/www/ghost.rewaant.com&lt;/span&gt;&lt;/code&gt; → Navigates to the target installation directory.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;ghost&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; install&lt;/span&gt;&lt;/code&gt; → Starts the installation process. It’ll now prompt you for more details:&lt;/p&gt;
&lt;p&gt;Blog URL → Type in your blog’s URL. In our case, this becomes &lt;code&gt;https://ghost.rewaant.com&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;MySQL hostname → Leave this to default (”localhost”) and press return/enter.&lt;/p&gt;
&lt;p&gt;MySQL username → Type in &lt;code&gt;root&lt;/code&gt; and supply the root password you set earlier.&lt;/p&gt;
&lt;p&gt;Ghost database name → Enter a database name, for us we used the default &lt;code&gt;ghost_rewaant_com_prod&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Do you wish to set up “ghost” mysql user? → Highly recommended, press &lt;code&gt;Y&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Do you wish to setup “Nginx”? → Press &lt;code&gt;Y&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Do you wish to setup SSL? → This install LetsEncrypt SSL certificates on your instance. We again recommend doing this. Keep in mind for this to work, your domain records should already be set to point to this server. Press &lt;code&gt;Y&lt;/code&gt; &lt;strong&gt;Important&lt;/strong&gt;: If you’re using Cloudflare or your domain service proxies the domain’s IP addresses, this will most likely not work. You’ll have to stop proxying the domain to verify the ownership. Once they’re verified, you can switch them back to being proxied. Please Ignore if your nameservers don’t proxy requests to your domain.&lt;/p&gt;
&lt;p&gt;Type in your email if you chose Y in the previous step.&lt;/p&gt;
&lt;p&gt;Do you wish to setup Systemd? → Press &lt;code&gt;Y&lt;/code&gt; . This will register your ghost publication as a systemd service which automatically starts on reboot. Highly recommended.&lt;/p&gt;
&lt;p&gt;Do you want to start Ghost? → Press &lt;code&gt;Y&lt;/code&gt;. This should start Ghost and it should be accessible at your chosen URL. In our case &lt;code&gt;https://ghost.rewaant.com&lt;/code&gt;&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/21.png&quot; alt=&quot;Ghost install prompt asking to start Ghost.&quot; /&gt;
&lt;p&gt;You now have your production server ready. We can disconnect now by typing in exit.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/22.jpeg&quot; alt=&quot;Terminal after exiting the server session.&quot; /&gt;
&lt;p&gt;If at any point the setup fails, you can try ghost setup to re-run the configuration process or reinstall with ghost uninstall and ghost install&lt;/p&gt;
&lt;h2 id=&quot;setting-up-publication&quot;&gt;Setting up the publication and going live&lt;/h2&gt;
&lt;p&gt;To set up the publication, visit &lt;a href=&quot;https://your_blog_url/ghost&quot;&gt;https://your_blog_url/ghost&lt;/a&gt;. In our case, it’s https://ghost.rewaant.com/ghost&lt;/p&gt;
&lt;p&gt;You’re now successfully serving a self-hosted Ghost Publication.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/23.jpeg&quot; alt=&quot;Ghost welcome screen for creating the publication account.&quot; /&gt;
&lt;img src=&quot;https://rewaant.com/insights/hosting-ghost-on-ubuntu-or-debian/24.jpeg&quot; alt=&quot;Ghost dashboard after the publication is created.&quot; /&gt;
</content:encoded><dc:creator>Rewaant Chhabra</dc:creator><category>Infrastructure</category></item><item><title>How to setup SSH keys on your Linux server</title><link>https://rewaant.com/blog/setup-ssh-keys-on-your-linux-server/</link><guid isPermaLink="true">https://rewaant.com/blog/setup-ssh-keys-on-your-linux-server/</guid><description>Simple guide on how to setup SSH keys on your Linux server. We explain setting up key based SSH authentication on an Ubuntu or a Debian server.</description><pubDate>Sun, 04 Sep 2022 06:03:28 GMT</pubDate><content:encoded>&lt;img src=&quot;https://rewaant.com/insights/setup-ssh-keys-on-your-linux-server/hero.png&quot; alt=&quot;Title card for setting up SSH keys, with a padlock marked $ssh.&quot;&gt;&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;
&lt;p&gt;SSH stands for “Secure Shell” which is both a protocol and a command line program that lets you administer a remote Linux computer. Here in this guide, we’ll explain setting up key-based SSH authentication for production servers. SSH keys aren’t only more secure than a regular password-based authentication but are convenient at times when you have to manage a number of remote systems.&lt;/p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;Let’s get started by first creating an Authentication key pair.&lt;/p&gt;
&lt;p&gt;Open up a terminal window on your computer. Create a key pair with the following commands:&lt;br /&gt;ssh-keygen → Creates a new public/private key pair.&lt;/p&gt;
&lt;p&gt;Type in the file names. Here we’ll use &lt;em&gt;rewaant-test&lt;/em&gt; &lt;br /&gt;&lt;strong&gt;Important&lt;/strong&gt;: If you already have existing keys with the same name in the directory, this will overwrite their content which may render them useless or worse lock you out of other systems. It’s important to choose a unique name here.&lt;/p&gt;
&lt;p&gt;It should now prompt for a passphrase. If you’ll be using this key on a personal/local computer to connect to a single instance and the key files won’t be passed around/shared, you can leave this empty. It’s highly suggested though that you use a passphrase. Whenever you’ll connect to an instance with a passphrase authenticated key, you’ll need to type in the passphrase every single time. Here for the sake of convenience, we’ll leave the passphrase empty.&lt;/p&gt;
&lt;p&gt;Your key pair should now be generated. This pair will be saved in either your user’s home directory ~/ or in the /home/&lt;em&gt;your_username&lt;/em&gt;/.ssh with the names you selected. The public key file is named with a &lt;em&gt;.pub&lt;/em&gt; suffix.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/setup-ssh-keys-on-your-linux-server/01.png&quot; alt=&quot;Terminal output from ssh-keygen after creating a key pair.&quot; /&gt;
&lt;h2 id=&quot;main-conf&quot;&gt;Main Configuration&lt;/h2&gt;
&lt;p&gt;Next, we’ll have to set up the public key as an “authorized key” to authenticate our logins. We have to upload the public key with specific permissions for the instance’s SSH server to use it for authentication. Follow these steps:&lt;/p&gt;
&lt;p&gt;Connect to your instance via SSH.&lt;br /&gt;ssh &lt;em&gt;your_username&lt;/em&gt;@&lt;em&gt;your_instance_ip_address&lt;/em&gt;which, in our case, becomes &lt;em&gt;ssh rewaant@176.58.98.58&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Once connected, type in the following commands:&lt;br /&gt;&lt;em&gt;mkdir ~/.ssh &amp;amp;&amp;amp; sudo chmod -R 700 ~/.ssh/&lt;/em&gt;→ This command creates a directory (.ssh) under the user’s home directory and modifies its permission to 700.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/setup-ssh-keys-on-your-linux-server/02.png&quot; alt=&quot;Terminal commands creating the .ssh directory and installing the public key.&quot; /&gt;
&lt;p&gt;Disconnect and copy the public key to your instance. Use the following commands:&lt;br /&gt;scp ~/.ssh/&lt;em&gt;key_name&lt;/em&gt;.pub &lt;em&gt;your_username&lt;/em&gt;@&lt;em&gt;your_instance_ip_address&lt;/em&gt;:~/.ssh/authorized_keys → SCP is a command line tool used to copy files to a remote computer. This command essentially just copies your public key file to the instance. In our case, this command becomes: &lt;em&gt;scp ~/.ssh/rewaant-test.pub rewaant@176.58.98.58:~/.ssh/authorized_keys&lt;/em&gt;&lt;br /&gt;It should prompt you for your password, once authenticated it’ll copy the file and take you back to your terminal window.&lt;/p&gt;
&lt;p&gt;Now we need to set the proper permission to the authorized keys file. Connect to your instance again, execute &lt;em&gt;sudo chmod 600 ~/.ssh/authorized_keys&lt;/em&gt;, disconnect by typing in &lt;em&gt;exit&lt;/em&gt;&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/setup-ssh-keys-on-your-linux-server/03.png&quot; alt=&quot;Terminal command setting permissions on authorized_keys.&quot; /&gt;
&lt;p&gt;Try reconnecting with the command: ssh &lt;em&gt;your_username&lt;/em&gt;@&lt;em&gt;your_instance_ip_address&lt;/em&gt;-i ~/.ssh/&lt;em&gt;key_name&lt;/em&gt;In our case, this command becomes &lt;em&gt;ssh rewaant@176.58.98.58 -i ~/.ssh/rewaant-test&lt;/em&gt;. Make sure to substitute your public key file path if it’s different from ours.&lt;/p&gt;
&lt;p&gt;You should now be able to connect to your instance with the SSH Keys. Keep in mind if you used a passphrase when generating the SSH keys, you’ll be asked for a passphrase to authenticate.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/setup-ssh-keys-on-your-linux-server/04.png&quot; alt=&quot;Terminal session connecting to the server with the SSH key.&quot; /&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Key-based authentication is much more secure and convenient if you manage multiple systems. We highly recommend using it over passwords in production environments. If you’re setting up a production server, consider reading our guide to &lt;strong&gt;Hardening SSH on your production server&lt;/strong&gt;: &lt;a href=&quot;https://rewaant.com/blog/hardening-ssh-on-your-linux-server/&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;
</content:encoded><dc:creator>Rewaant Chhabra</dc:creator><category>Infrastructure</category></item><item><title>Hardening SSH on your Linux server</title><link>https://rewaant.com/blog/hardening-ssh-on-your-linux-server/</link><guid isPermaLink="true">https://rewaant.com/blog/hardening-ssh-on-your-linux-server/</guid><description>Simple guide to securing SSH access to your linux server. Setting up SSH keys, disabling IPv6 access, changing default SSH port, disabling root login, how to setup basic rules with firewall and more.</description><pubDate>Sat, 03 Sep 2022 06:44:49 GMT</pubDate><content:encoded>&lt;img src=&quot;https://rewaant.com/insights/hardening-ssh-on-your-linux-server/hero.png&quot; alt=&quot;Title card reading Hardening SSH on your Linux server.&quot;&gt;&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;
&lt;p&gt;This guide covers important aspects of hardening SSH access for your production server so you can secure your resources against random brute-force login attempts.&lt;/p&gt;
&lt;p&gt;We’ll be mainly covering these topics:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use key-based authentication if you’re still using passwords&lt;/li&gt;
&lt;li&gt;Disable SSH access over IPv6&lt;/li&gt;
&lt;li&gt;Disable root login via SSH&lt;/li&gt;
&lt;li&gt;Disable password-based authentication once you can connect with your keys&lt;/li&gt;
&lt;li&gt;Set up a firewall&lt;/li&gt;
&lt;li&gt;Using Fail2Ban to ban IP addresses after too many login attempts&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let’s get started!&lt;/p&gt;
&lt;h2 id=&quot;setup-key-auth&quot;&gt;Setting up key-based authentication&lt;/h2&gt;
&lt;p&gt;If you’re using a password to authenticate into your production server, we highly recommend using SSH keys which are more secure and convenient for managing servers. Follow the steps in this guide and you should be good to go: &lt;a href=&quot;https://rewaant.com/blog/setup-ssh-keys-on-your-linux-server/&quot;&gt;How to setup SSH keys on your Linux server&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;disable-ipv6&quot;&gt;Disable the IPv6 access&lt;/h2&gt;
&lt;p&gt;IPv6 is a newer protocol compared to IPv4, but for most users out there, it’s likely they won’t be needing it presently. For enhancing security, we’ll disable SSH access over IPv6.&lt;/p&gt;
&lt;p&gt;Connect to your instance with a less privileged user you’ve set up previously. Do not proceed if you just have the root user’s credentials.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hardening-ssh-on-your-linux-server/01.png&quot; alt=&quot;Terminal session connected as a non-root user.&quot; /&gt;
&lt;p&gt;Once connected, type in the command: &lt;em&gt;sudo nano /etc/ssh/sshd_config&lt;/em&gt;. This should ask for your user’s password. Once you have access to the file, navigate with the arrow keys to line with the following text:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#Port 22 &lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#AddressFamily any&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It’ll most likely be on top of the file with the configuration commented out, make sure this is set to:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#Port 22 &lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;span style=&quot;color:#24292E&quot;&gt;AddressFamily inet&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This should allow access only over IPv4 connections.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hardening-ssh-on-your-linux-server/02.png&quot; alt=&quot;SSH configuration limited to IPv4.&quot; /&gt;
&lt;h2 id=&quot;disable-root&quot;&gt;Disable root login via SSH&lt;/h2&gt;
&lt;p&gt;Next, we’ll disable the root user to log in via SSH. “root” is a superuser with the highest administrative privileges that in the wrong/incompetent hands can wreak havoc in the system. Also, most brute-force login attempts target the root user so it’s important to disable this user for SSH entirely. It’s important to make sure that you have a less privileged user already set up on your system with sudo capabilities. You should also know the password to this less privileged user account or you may risk locking yourself out of the system entirely.&lt;/p&gt;
&lt;p&gt;PermitRootLogin yes Change this line to &lt;em&gt;PermitRootLogin no&lt;/em&gt;&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hardening-ssh-on-your-linux-server/03.png&quot; alt=&quot;SSH configuration with PermitRootLogin set to no.&quot; /&gt;
&lt;p&gt;We now have to write these changes to disk. Assuming you’re using the nano text editor, execute the following commands: &lt;em&gt;Ctrl+O&lt;/em&gt; or &lt;em&gt;Cmd+O&lt;/em&gt; to write changes to the file. This will confirm the filename, leave it to default, and DO NOT CHANGE. Press &lt;em&gt;Ctrl+X&lt;/em&gt; or &lt;em&gt;Cmd+X&lt;/em&gt; to exit the nano text editor.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hardening-ssh-on-your-linux-server/04.png&quot; alt=&quot;Saving the SSH configuration in the editor.&quot; /&gt;
&lt;p&gt;Now we need to restart the SSH service to make these changes active. Execute the command: &lt;em&gt;sudo systemctl restart sshd&lt;/em&gt; This will restart the SSH service.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hardening-ssh-on-your-linux-server/05.png&quot; alt=&quot;Terminal command restarting the SSH service.&quot; /&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; If at any point during or after this tutorial, you get locked out of your system, you can always fall back to using your cloud provider’s web console. They’re handy when things go awry.&lt;/p&gt;
&lt;p&gt;Let’s continue to the next section and set up a firewall.&lt;/p&gt;
&lt;h2 id=&quot;setup-firewall&quot;&gt;Set up a firewall&lt;/h2&gt;
&lt;p&gt;We’ll be using ufw in this guide which stands for Uncomplicated Firewall. This firewall program is simple to set up and more than enough for most use cases out there. To get started, let’s check if we have it pre-installed:&lt;/p&gt;
&lt;p&gt;Execute the command: &lt;em&gt;sudo apt install ufw&lt;/em&gt; You should see a similar output below.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hardening-ssh-on-your-linux-server/06.png&quot; alt=&quot;Terminal output from installing UFW.&quot; /&gt;
&lt;p&gt;Once it’s installed, we can enable/disable rules under ufw. For our use case with SSH and opening up the usual HTTP (80) and HTTPS (443) ports, we’ll execute the following commands:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; ufw&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; allow&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; ssh&lt;/span&gt;&lt;/code&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; ufw&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; allow&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; 80/tcp&lt;/span&gt;&lt;/code&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;code&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; ufw&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; allow&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; 443/tcp&lt;/span&gt;&lt;/code&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You should see a similar output below.&lt;/p&gt;
&lt;p&gt;Now that we’ve allowed the basic ports with firewall, we’ll enable it with the command sudo ufw enable. Do not enable ufw without allowing ssh or port 22 as it’s likely you WILL get locked out of your system.&lt;/p&gt;
&lt;p&gt;Check the firewall status with &lt;em&gt;sudo ufw status&lt;/em&gt;. This should have similar output with Status: active and the rules printed out below.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hardening-ssh-on-your-linux-server/07.png&quot; alt=&quot;UFW status showing the firewall is active.&quot; /&gt;
&lt;p&gt;We now have the firewall setup, we’ll proceed to the next and final step.&lt;/p&gt;
&lt;h2 id=&quot;setup-fail2ban&quot;&gt;Setting up Fail2Ban&lt;/h2&gt;
&lt;p&gt;Fail2Ban is another utility that prevents your server from brute-force attacks. It’s likely that authenticated users will be able to access your server with 3 or lesser tries. This utility will ban IP addresses used by hackers and bots which may try to break into our systems using brute-force attacks.&lt;/p&gt;
&lt;p&gt;Install Fail2Ban with &lt;em&gt;sudo apt install fail2ban&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Enable the fail2ban service with the command &lt;em&gt;sudo systemctl enable fail2ban&lt;/em&gt; this will create a systemd service for fail2ban.&lt;/p&gt;
&lt;p&gt;We’ll keep the fail2ban configuration to default for simplicity. However, we intend on writing a comprehensive guide for fail2ban later. To start the service, use &lt;em&gt;sudo systemctl start fail2ban&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;We’ll now check the service status. Type in &lt;em&gt;sudo systemctl status fail2ban&lt;/em&gt; and you should see similar output.&lt;/p&gt;
&lt;img src=&quot;https://rewaant.com/insights/hardening-ssh-on-your-linux-server/08.png&quot; alt=&quot;Fail2Ban service status.&quot; /&gt;
&lt;p&gt;You now have Fail2Ban active and running on your server.&lt;/p&gt;
&lt;p&gt;This guide helps you tighten security on your production server by hardening SSH access. Following this guide keeps your resources more secure than most production servers out there. In the end, no matter how many security measures we take it’s always better when solutions are customized specifically to our needs. We recommend you read more on these topics or feel free to reach out to schedule an intro call so we can help you with setting up your sites or app’s infrastructure properly.&lt;/p&gt;
</content:encoded><dc:creator>Rewaant Chhabra</dc:creator><category>Infrastructure</category></item></channel></rss>