{"id":2902,"date":"2017-03-13T00:00:00","date_gmt":"2017-03-13T00:00:00","guid":{"rendered":"http:\/\/ssdnodes.billabailey.com\/2017\/03\/13\/tutorial-installing-nginx-mysql-php-lemp-on-ubuntu-16-04\/"},"modified":"2025-05-18T19:54:23","modified_gmt":"2025-05-18T19:54:23","slug":"tutorial-install-lemp-ubuntu","status":"publish","type":"post","link":"https:\/\/www.ssdnodes.com\/blog\/tutorial-install-lemp-ubuntu\/","title":{"rendered":"Installing Nginx, MySQL, PHP (LEMP) on Ubuntu 16.04"},"content":{"rendered":"<p>A virtual private server (VPS) is most often used to host dynamic websites and applications. This requires installing and configuring a web server.<\/p>\n<p>The LEMP \u201cstack\u201d involves the Linux operating system (L), the Nginx web server (E), a MySQL database (M), and PHP for dynamic webpages (P).<\/p>\n<h2 id=\"prerequisites\">Prerequisites<\/h2>\n<p>Before you start, you need the following:<\/p>\n<ul>\n<li>A VPS running Ubuntu 16.04<\/li>\n<li>A regular (non-root) account with sudo privileges. See our <a href=\"https:\/\/www.ssdnodes.com\/blog\/tutorial-setting-up-and-securing-ssh-based-authentication\"> SSH keys tutorial <\/a> for more information.<\/li>\n<\/ul>\n<div class=\"cta-inline\"><\/div>\n<h2 id=\"step-1-disabling-apache2\">Step 1: Disabling apache2<\/h2>\n<p>We need to ensure that Apache (a different web server option) isn\u2019t running. Let\u2019s remove it from the server.<\/p>\n<pre><code class=\"language-bash hljs\">sudo apt-get remove apache2\nsudo rm \/var\/www\/html\/index.html\n<\/code><\/pre>\n<h2 id=\"step-2-installing-nginx\">Step 2: Installing Nginx<\/h2>\n<p>Ubuntu\u2019s <code> apt <\/code> package management software makes installing nginx quite easy. Running the <code> update <\/code> command ensures you get the most up-to-date version.<\/p>\n<pre><code class=\"language-bash hljs\">sudo apt-get update\nsudo apt-get install nginx\n<\/code><\/pre>\n<p>Nginx will automatically start running at this point. You can double check this by navigating to the IP address of your VPS via a web browser.<\/p>\n<pre><code class=\"hljs cpp\">http:<span class=\"hljs-comment\">\/\/remote_server<\/span>\n<\/code><\/pre>\n<p>If successful, you\u2019ll see a default Nginx page.<\/p>\n<h2 id=\"step-3-installing-mysql\">Step 3: Installing MySQL<\/h2>\n<p>Next, we\u2019ll install MySQL, which is a database that will be used to store information. Install this with <code> apt <\/code> as well.<\/p>\n<pre><code class=\"language-bash hljs\">sudo apt-get install mysql-server\n<\/code><\/pre>\n<p>You will be prompted to input a password for the adminisrative user for MySQL. We recommend a strong, secure password. For additional security, you won\u2019t be able to see the characters as you type them in.<\/p>\n<p>Next, run a script to improve the security of the installation.<\/p>\n<pre><code class=\"language-bash hljs\">sudo mysql_secure_installation\n<\/code><\/pre>\n<p>You\u2019ll see the following warning about the <code> VALIDATE PASSWORD PLUGIN <\/code> .<\/p>\n<pre><code class=\"language-bash hljs\">VALIDATE PASSWORD PLUGIN can be used to <span class=\"hljs-built_in\">test<\/span> passwords\nand improve security. It checks the strength of password\nand allows the users to <span class=\"hljs-built_in\">set<\/span> only those passwords <span class=\"hljs-built_in\">which<\/span> are\nsecure enough. Would you like to setup VALIDATE PASSWORD plugin?\n\nPress y|Y <span class=\"hljs-keyword\">for<\/span> Yes, any other key <span class=\"hljs-keyword\">for<\/span> No: \n<\/code><\/pre>\n<p>This plugin will reject passwords that are not strong enough. It\u2019s not necessary if you\u2019re diligent about using strong, secure passwords. If you choose <code> Yes <\/code> , you\u2019ll be asked to define a policy for strong passwords.<\/p>\n<p>You will also be given an opportunity to change the root password if you\u2019d like.<\/p>\n<pre><code class=\"language-bash hljs\">Using existing password <span class=\"hljs-keyword\">for<\/span> root.\nChange the password <span class=\"hljs-keyword\">for<\/span> root ? ((Press y|Y <span class=\"hljs-keyword\">for<\/span> Yes, any other key <span class=\"hljs-keyword\">for<\/span> No) : \n<\/code><\/pre>\n<p>For the remainder of the questions, type in <code> y <\/code> or <code> Y <\/code> and then hit <code> Enter <\/code> . These remove anonymous users and restrict root logins, both of which are best practices.<\/p>\n<h2 id=\"step-4-installing-php\">Step 4: Installing PHP<\/h2>\n<p>PHP will be used to serve up dynamic web pages to users as they visit your site. There are other options available, such as Ruby or Node.js, but these fall beyond the scope of this tutorial.<\/p>\n<p>We need to start with installing some programs that help PHP communicate with Nginx and MySQL.<\/p>\n<pre><code class=\"language-bash hljs\">sudo apt-get install php-fpm php-mysql\n<\/code><\/pre>\n<p>You need to edit the php.ini file and change one particular line to make the configuration more secure.<\/p>\n<pre><code class=\"language-bash hljs\">sudo nano \/etc\/php\/7.0\/fpm\/php.ini\n<\/code><\/pre>\n<p>You\u2019re looking for a line that begins with <code> ;cgi.fix_pathinfo <\/code> . To find it easily in nano, type in <code> Ctrl+w <\/code> and type in <code> cgi.fix_pathinfo <\/code> . You need to uncomment this line\u2014remove the semicolon\u2014and change the setting to <code> 0 <\/code> . The end result should look like this:<\/p>\n<pre><code class=\"hljs\">cgi.fix_pathinfo=0\n<\/code><\/pre>\n<p>Once you\u2019ve saved the file, a quick restart of the PHP processor will enable this change.<\/p>\n<pre><code class=\"language-bash hljs\">sudo systemctl restart php7.0-fpm\n<\/code><\/pre>\n<h2 id=\"step-5-configuring-nginx-and-php\">Step 5: Configuring Nginx and PHP<\/h2>\n<p>As we tested earlier, Nginx is already working properly, but it defaults to using HTML to serve up a webpage, not PHP. We need to change that by editing the default Nginx server block.<\/p>\n<pre><code class=\"language-bash hljs\">sudo nano \/etc\/nginx\/sites-available\/default\n<\/code><\/pre>\n<p>Let\u2019s go step by step through the lines that you will want to edit.<\/p>\n<p>First, you might want to change the root directory of your website, if you\u2019d like to serve it from a different location. The default configuration is perfectly fine, however, so we recommend leaving it alone.<\/p>\n<pre><code class=\"hljs cs\">root \/<span class=\"hljs-keyword\">var<\/span>\/www\/html;\n<\/code><\/pre>\n<p>Next, you want to request that Nginx look for an <code> index.php <\/code> file rather than <code> index.html <\/code> .<\/p>\n<p><strong> Before: <\/strong><\/p>\n<pre><code class=\"hljs css\"># <span class=\"hljs-selector-tag\">Add<\/span> <span class=\"hljs-selector-tag\">index<\/span><span class=\"hljs-selector-class\">.php<\/span> <span class=\"hljs-selector-tag\">to<\/span> <span class=\"hljs-selector-tag\">the<\/span> <span class=\"hljs-selector-tag\">list<\/span> <span class=\"hljs-selector-tag\">if<\/span> <span class=\"hljs-selector-tag\">you<\/span> <span class=\"hljs-selector-tag\">are<\/span> <span class=\"hljs-selector-tag\">using<\/span> <span class=\"hljs-selector-tag\">PHP<\/span>\n<span class=\"hljs-selector-tag\">index<\/span> <span class=\"hljs-selector-tag\">index<\/span><span class=\"hljs-selector-class\">.html<\/span> <span class=\"hljs-selector-tag\">index<\/span><span class=\"hljs-selector-class\">.htm<\/span> <span class=\"hljs-selector-tag\">index<\/span><span class=\"hljs-selector-class\">.nginx-debian<\/span><span class=\"hljs-selector-class\">.html<\/span>;\n<\/code><\/pre>\n<p><strong> After: <\/strong><\/p>\n<pre><code class=\"hljs css\"># <span class=\"hljs-selector-tag\">Add<\/span> <span class=\"hljs-selector-tag\">index<\/span><span class=\"hljs-selector-class\">.php<\/span> <span class=\"hljs-selector-tag\">to<\/span> <span class=\"hljs-selector-tag\">the<\/span> <span class=\"hljs-selector-tag\">list<\/span> <span class=\"hljs-selector-tag\">if<\/span> <span class=\"hljs-selector-tag\">you<\/span> <span class=\"hljs-selector-tag\">are<\/span> <span class=\"hljs-selector-tag\">using<\/span> <span class=\"hljs-selector-tag\">PHP<\/span>\n<span class=\"hljs-selector-tag\">index<\/span> <span class=\"hljs-selector-tag\">index<\/span><span class=\"hljs-selector-class\">.php<\/span> <span class=\"hljs-selector-tag\">index<\/span><span class=\"hljs-selector-class\">.html<\/span> <span class=\"hljs-selector-tag\">index<\/span><span class=\"hljs-selector-class\">.htm<\/span> <span class=\"hljs-selector-tag\">index<\/span><span class=\"hljs-selector-class\">.nginx-debian<\/span><span class=\"hljs-selector-class\">.html<\/span>;\n<\/code><\/pre>\n<p>After that, you need to uncomment the area that connects to <code> php-fpm <\/code> .<\/p>\n<p><strong> Before: <\/strong><\/p>\n<pre><code class=\"hljs shell\"><span class=\"hljs-meta\">#<\/span><span class=\"bash\"> pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000<\/span>\n<span class=\"hljs-meta\">#<\/span>\n<span class=\"hljs-meta\">#<\/span><span class=\"bash\">location ~ .php$ {<\/span>\n<span class=\"hljs-meta\">#<\/span><span class=\"bash\">       include snippets\/fastcgi-php.conf;<\/span>\n<span class=\"hljs-meta\">#<\/span>\n<span class=\"hljs-meta\">#<\/span><span class=\"bash\">       <span class=\"hljs-comment\"># With php7.0-cgi alone:<\/span><\/span>\n<span class=\"hljs-meta\">#<\/span><span class=\"bash\">       fastcgi_pass 127.0.0.1:9000;<\/span>\n<span class=\"hljs-meta\">#<\/span><span class=\"bash\">       <span class=\"hljs-comment\"># With php7.0-fpm:<\/span><\/span>\n<span class=\"hljs-meta\">#<\/span><span class=\"bash\">       fastcgi_pass unix:\/run\/php\/php7.0-fpm.sock;<\/span>\n<span class=\"hljs-meta\">#<\/span><span class=\"bash\">}<\/span>\n<\/code><\/pre>\n<p><strong> After: <\/strong><\/p>\n<pre><code class=\"hljs nginx\"><span class=\"hljs-attribute\">location<\/span> <span class=\"hljs-regexp\">~ .php$<\/span> {\n        <span class=\"hljs-attribute\">include<\/span> snippets\/fastcgi-php.conf;\n\n<span class=\"hljs-comment\">#       # With php7.0-cgi alone:<\/span>\n<span class=\"hljs-comment\">#       fastcgi_pass 127.0.0.1:9000;<\/span>\n<span class=\"hljs-comment\">#       # With php7.0-fpm:<\/span>\n        <span class=\"hljs-attribute\">fastcgi_pass<\/span> unix:\/run\/php\/php7.0-fpm.sock;\n}\n<\/code><\/pre>\n<p>Finally, you should restrict access to <code> .htaccess <\/code> files, which Nginx doesn\u2019t use.<\/p>\n<p><strong> Before: <\/strong><\/p>\n<pre><code class=\"language-bash hljs\"><span class=\"hljs-comment\"># deny access to .htaccess files, if Apache's document root<\/span>\n<span class=\"hljs-comment\"># concurs with nginx's one<\/span>\n<span class=\"hljs-comment\">#<\/span>\n<span class=\"hljs-comment\">#location ~ \/.ht {<\/span>\n<span class=\"hljs-comment\">#       deny all;<\/span>\n<span class=\"hljs-comment\">#}<\/span>\n<\/code><\/pre>\n<p><strong> After: <\/strong><\/p>\n<pre><code class=\"hljs shell\"><span class=\"hljs-meta\">#<\/span><span class=\"bash\"> deny access to .htaccess files, <span class=\"hljs-keyword\">if<\/span> Apache<span class=\"hljs-string\">'s document root<\/span><\/span>\n<span class=\"hljs-meta\">#<\/span><span class=\"bash\"><span class=\"hljs-string\"> concurs with nginx'<\/span>s one<\/span>\n<span class=\"hljs-meta\">#<\/span>\nlocation ~ \/.ht {\n       deny all;\n}\n<\/code><\/pre>\n<p>Once you\u2019ve made those three changes, you can save and close the file and test out the configuration.<\/p>\n<pre><code class=\"language-bash hljs\">sudo nginx -t\n<\/code><\/pre>\n<p>If you see any errors, check the file for any syntax mistakes you might have made. Once the command returns a positive result, you can restart Nginx to load the new configuration.<\/p>\n<pre><code class=\"language-bash hljs\">sudo systemctl restart nginx\n<\/code><\/pre>\n<h2 id=\"step-6-testing-php\">Step 6: Testing PHP<\/h2>\n<p>At this point, the LEMP stack should be completely configured, but it doesn\u2019t hurt to take a few extra moments to double-check that it\u2019s running correctly. The easiest way to do that is to create a new file in your document root.<\/p>\n<pre><code class=\"language-bash hljs\">sudo nano \/var\/www\/html\/info.php\n<\/code><\/pre>\n<p>Inside that file, type or paste in these two lines:<\/p>\n<pre><code class=\"php hljs\"><span class=\"hljs-meta\">&lt;?php<\/span>\nphpinfo();\n<\/code><\/pre>\n<p>Save and close the file, and then visit your website again via a browser.<\/p>\n<pre><code class=\"hljs cpp\">http:<span class=\"hljs-comment\">\/\/remote_server\/info.php<\/span>\n<\/code><\/pre>\n<p>If you see a file like the following, you\u2019re all set up! You\u2019re now ready to host and deploy some serious content to your visitors.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2024\/01\/phpinfo.png\" alt=\"phpinfo.png\" width=\"750\" height=\"563\" \/><\/p>\n<p>In future tutorials, we\u2019ll cover h<a href=\"https:\/\/www.ssdnodes.com\/blog\/tutorial-wordpress-lemp-ubuntu\/\">ow to add a WordPress installation on top of your LEMP stack<\/a>, in addition to securing the connection between your server and your visitors with SSL certificates.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A virtual private server (VPS) is most often used to host dynamic websites and applications. This requires installing and configuring a web server.<\/p>\n","protected":false},"author":20,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[18,30],"tags":[197,177,211,222,185],"class_list":["post-2902","post","type-post","status-publish","format-standard","hentry","category-devops","category-tutorials","tag-lemp","tag-mysql","tag-nginx","tag-php","tag-ubuntu"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts\/2902","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/users\/20"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/comments?post=2902"}],"version-history":[{"count":3,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts\/2902\/revisions"}],"predecessor-version":[{"id":13075,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts\/2902\/revisions\/13075"}],"wp:attachment":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/media?parent=2902"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/categories?post=2902"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/tags?post=2902"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}