DEV Community

Cover image for Moving from Apache2 to Nginx Webserver
Davinderpal Singh Rehal
Davinderpal Singh Rehal

Posted on

37 8

Moving from Apache2 to Nginx Webserver

Recently at work I had to move our dev, staging and production web servers from Apache2 to Nginx. The reason for this move is that in the rest of the company we are using Nginx for all the backend services but when the web sites were set up for some reason the consultants set up Apache2. This became a problem mostly for management. In this article, I will be going step-by-step through the process. I will be using a vagrant box for all the screenshots but the steps I did were the same for the actual servers.

Server

For my test server I am using vagrant and ubuntu/bionic64. On this server I had apache2.4, php7.2 and mysql5.7 a basic LAMP stack. Which I will be moving to a LEMP stack replacing Apache with Nginx.

This server has a WordPress site running on it, with WordPress 5.2.4 running. We will have achieved our goal once we can see this WordPress site running on Nginx and PHP 7.3. Oh and we have a bunch of envvars set up of the Apache2 instance that will also have to transfer to the Nginx installation.

Installing Nginx

Pretty straight forward. Start off by checking for updates.



sudo apt update
sudo apt upgrade



Enter fullscreen mode Exit fullscreen mode

Actually install Nginx.



sudo apt install nginx


Enter fullscreen mode Exit fullscreen mode

Nginx is now installed but is not running, since we have Apache2 already installed and configured on the system, Apache2 will be using port 80 which means that to avoid conflicts we should run Nginx on a different port to test that everything is running well. I choose the port 8080.

Configure Nginx with Port 8080

There is a default website that is set up with Nginx (just like Apache) just to make sure that things work. The config can be seen at.



sudo vim /etc/nginx/sites-available/default


Enter fullscreen mode Exit fullscreen mode

This should open up a file that looks like.

##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##
# Default server configuration
#
server {
listen 80 default_server;
listen [::]:80 default_server;
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
# pass PHP scripts to FastCGI server
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php-fpm (or other unix sockets):
# fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
# listen 80;
# listen [::]:80;
#
# server_name example.com;
#
# root /var/www/example.com;
# index index.html;
#
# location / {
# try_files $uri $uri/ =404;
# }
#}
view raw default hosted with ❤ by GitHub

On line 22 and 23 we are gonna change 80 to 8080.


 nginx
listen 8080 default_server;
listen [::]:8080 default_server;


Enter fullscreen mode Exit fullscreen mode

Let's test the config quickly before we start the Nginx service.


 bash
sudo nginx -t


Enter fullscreen mode Exit fullscreen mode

If all is well, let's write a small HTML page that will just let us know that the server is up. Line 41 shows me the root of the server. I changed server root to make sure that am not using the same directory as Apache.



root /srv/www/html;


Enter fullscreen mode Exit fullscreen mode

That's the directory I will be adding the index.html file. Now we can start the server.



sudo service nginx start


Enter fullscreen mode Exit fullscreen mode

To test out the new config.



curl http://localhost:8080


Enter fullscreen mode Exit fullscreen mode

Which should return the new HTML file that I had created. Moving on to install PHP.

Installing PHP

Right now we have PHP7.2 installed on the system, since there has been a bit of a scare with the whole PHP7.2 and Nginx config, will be moving to PHP7.3.

First off, Ubuntu doesn't know where to get PHP7.3 from so we need to add the repository.



sudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt upgrade


Enter fullscreen mode Exit fullscreen mode

Actually installing PHP7.3 and some extensions. These are just the extensions I need, feel free to add or remove extensions as required.



sudo apt install php7.3
sudo apt install php7.3-cli php7.3-fpm php7.3-pdo php7.3-mysql php7.3-zip  php7.3-mbstring php7.3-curl php7.3-xml php7.3-bcmath php7.3-json


Enter fullscreen mode Exit fullscreen mode

Once all the extensions have been installed, its time to edit the Nginx config file again to tell it that the website we have uses PHP. The config file is below, with all the comments stripped out and comments only on the lines that have been changed.

server {
# Using port 8080 only for testing purposes
listen 8080 default_server;
listen [::]:8080 default_server;
# Where are the files that are being served
root /srv/www/html;
# Default Index file being served, have added `index.php`
index index.php index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# Added support for PHP routers
try_files $uri $uri/ /index.php?args =404;
}
# Adding support for PHP7.3
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# Adding environmental variables for this website
include /srv/config/default.nginx.conf;
}
}

Test the config to make sure there are no syntax errors.



sudo nginx -t


Enter fullscreen mode Exit fullscreen mode

You will probably get an error because there is no env file at /srv/config/default.nginx.conf. Just add a blank file there, for now, will explain what it does later.

Hopefully, that solved your error. Now let's change the index.html file to index.php and add some basic PHP code to see if things work. Also, be sure to set the appropriate permissions to the index.php file. I like going with.



sudo chmod 755 index.php


Enter fullscreen mode Exit fullscreen mode

Restart the Nginx server



sudo service nginx restart


Enter fullscreen mode Exit fullscreen mode

And you should see the PHP file you wrote. I printed out the phpinfo() function to make sure configurations are good.

Server Env Variables

I like having some of my app configurations saved in the $_SERVER superglobal. This comes in handy when your moving your app between dev, stage and prod servers and don't want to keep on changing your db passwords or API endpoints.

The file that we touched /srv/config/default.nginx.conf, I will be adding the following lines of code in it.



fastcgi_param   APP_ENV         dev;
fastcgi_param   APP_ENDPOINT    https://dev.server.com;
fastcgi_param   DB_HOST         localhost;
fastcgi_param   DB_USER         root;
fastcgi_param   DB_PASS         password;


Enter fullscreen mode Exit fullscreen mode

The format is usually



fastcgi_param  {VAR_NAME}      {VAR_VALUE};


Enter fullscreen mode Exit fullscreen mode

Feel free to add any other env variables. Once your happy test config and restart Nginx. You should see your new variables in the phpinfo() function output as below.

PHP Server variables

Pay close attention to the last 5 values.

And thats it, just move all your files to the relevant folder to do a final test. When ready you can stop the Apache service.



sudo service apache2 stop


Enter fullscreen mode Exit fullscreen mode

Change the port number from 8080 in the Nginx config, to 80 and restart Nginx, and we are done.

Well done!

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (5)

Collapse
 
vinayhegde1990 profile image
Vinay Hegde

Concise post there, Davinderpal. Would like to add a few things to make it even better.

  1. Make a separate file for each of your websites in the /etc/nginx/sites-available directory than making changes to the default file. It'll be helpful in production should that file be lost during an nginx upgrade or be corrupted by any chance
    (Ideally: They should be committed to a VCS repo)

  2. Do ensure the file containing the Environmental variables has the right set of permissions since it contains sensitive data that you'd not want to end up in the wrong hands.

  3. Expose the port ::8080 only if you're serving traffic on IPv6

  4. Do consider serving the traffic via TLS that terminates at Nginx for an additional layer of security.

Collapse
 
davinderpalrehal profile image
Davinderpal Singh Rehal

Thanks Vinay will definitely keep these in mind. Usually, we have multiple websites on the same server all of them following a similar suggestions to what you have made. I am hoping to do a couple of articles about tightening up web server security.

Collapse
 
vinayhegde1990 profile image
Vinay Hegde

Good to know they helped, Davinderpal. Point no. 1 of my previous comment should be useful towards your requirement of multiple sites in same server.

Looking forward to your web security posts!

Collapse
 
flatrick profile image
Patrik

A little tidbit regarding security; if possible, refrain from giving anyone besides the user actually running the website permissions to execute the files.
chmod 755 should at the very least be turned into chmod 750 :)

Collapse
 
davinderpalrehal profile image
Davinderpal Singh Rehal

Absolutely correct, on prod server there are couple of security practices that we follow. Will be doing another article soon about tightening up the security on web servers.

Image of Timescale

Timescale – the developer's data platform for modern apps, built on PostgreSQL

Timescale Cloud is PostgreSQL optimized for speed, scale, and performance. Over 3 million IoT, AI, crypto, and dev tool apps are powered by Timescale. Try it free today! No credit card required.

Try free