How to Install Nginx on Ubuntu


Nginx is unequivocally the best web server out there. It takes up less resources on your machine and is faster than Apache in most cases, especially if you’re running a static website.

In this tutorial, I will show you how to install Nginx on Ubuntu, configure it, create Server Blocks for your websites, and keep Nginx up to date. The commands that I will list in this tutorial are for Ubuntu/Debian, you may need to modify them if you are using some other Linux distro.

Last Updated: 17th January 2015.


  1. Installing Nginx
  2. Testing Nginx
  3. Controlling Nginx Daemon
  4. Basic Nginx Configuration
  5. Website Configuration
  6. Updating Nginx

Installing Nginx

There are several ways to install Nginx but the best one (in my opinion) is to use the Nginx Launchpad repo maintained by the Nginx team.

sudo add-apt-repository ppa:nginx/stable
sudo apt-get update
sudo apt-get install python-software-properties software-properties-common
sudo apt-get install nginx

Testing Nginx

To check if Nginx was installed correctly; you will first need to start Nginx, if it isn’t running already:

sudo service nginx start

Then, go to your server’s public IP address in your web browser, there you will see the Nginx landing page which looks something like this:

Nginx Welcome Page

If you don’t know your server’s public IP address then try this:


You will need curl for the above command to work, if you don’t have it installed then:

sudo apt-get install curl

If you see the Nginx landing page then it means that Nginx has been installed properly and you are ready to move on to the next step.

Controlling Nginx Daemon

If Nginx is running and you wish to stop it:

sudo service nginx stop

If Nginx is stopped, then to start it:

sudo service nginx start

To restart Nginx (stop and then start it again):

sudo service nginx restart

If you have made any changes to the Nginx configuration files then you don’t necessarily need to restart Nginx, you can just reload the configuration files:

sudo nginx -t && sudo service nginx reload

Basic Nginx Configuration

Now that you have Nginx installed, the first thing that you should do is configure the main Nginx configuration file.

You can use the Nginx defaults, but I like to optimize and fine-tune the configuration file:

sudo mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.default
sudo touch /etc/nginx/nginx.conf
  • The first command will backup the current nginx.conf file; just a precautionary measure.
  • The second command will create a new blank nginx.conf file for us to work on.

Open the .conf that you just created sudo nano /etc/nginx/nginx.conf and then paste the following configuration in it:

# nginx Configuration File

# Run as a less privileged user for security reasons.
user www-data;

# How many worker threads to run;
# "auto" sets it to the number of CPU cores available in the system, and
# offers the best performance. Don't set it higher than the number of CPU
# cores if changing this parameter.

# The maximum number of connections for Nginx is calculated by:
# max_clients = worker_processes * worker_connections
worker_processes auto;

# Maximum open file descriptors per process;
# should be > worker_connections.
worker_rlimit_nofile 8192;

events {
  # When you need > 8000 * cpu_cores connections, you start optimizing your OS,
  # and this is probably the point at which you hire people who are smarter than
  # you, as this is *a lot* of requests.
  worker_connections 8000;

# Default error log file
# (this is only used when you don't override error_log on a server{} level)
error_log  /var/log/nginx/error.log warn;
pid        /var/run/;

http {

  # Hide nginx version information.
  server_tokens off;

  # Define the MIME types for files.
  include       /etc/nginx/mime.types;
  default_type  application/octet-stream;

  # Update charset_types due to updated mime.types
  charset_types text/xml text/plain text/vnd.wap.wml application/x-javascript application/rss+xml text/css application/javascript application/json;

  # Format to use in log files
  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

  # Default log file
  # (this is only used when you don't override access_log on a server{} level)
  access_log /var/log/nginx/access.log main;

  # How long to allow each connection to stay idle; longer values are better
  # for each individual client, particularly for SSL, but means that worker
  # connections are tied up longer. (Default: 65)
  keepalive_timeout 20;

  # Speed up file transfers by using sendfile() to copy directly
  # between descriptors rather than using read()/write().
  sendfile        on;

  # Tell Nginx not to send out partial frames; this increases throughput
  # since TCP frames are filled up before being sent out. (adds TCP_CORK)
  tcp_nopush      on;

  # Compression

  # Enable Gzip compressed.
  gzip on;

  # Compression level (1-9).
  # 5 is a perfect compromise between size and cpu usage, offering about
  # 75% reduction for most ascii files (almost identical to level 9).
  gzip_comp_level    5;

  # Don't compress anything that's already small and unlikely to shrink much
  # if at all (the default is 20 bytes, which is bad as that usually leads to
  # larger files after gzipping).
  gzip_min_length    256;

  # Compress data even for clients that are connecting to us via proxies,
  # identified by the "Via" header (required for CloudFront).
  gzip_proxied       any;

  # Tell proxies to cache both the gzipped and regular version of a resource
  # whenever the client's Accept-Encoding capabilities header varies;
  # Avoids the issue where a non-gzip capable client (which is extremely rare
  # today) would display gibberish if their proxy gave them the gzipped version.
  gzip_vary          on;

  # Compress all output labeled with one of the following MIME-types.
  # text/html is always compressed by HttpGzipModule

  # This should be turned on if you are going to have pre-compressed copies (.gz) of
  # static files available. If not it should be left off as it will cause extra I/O
  # for the check. It is best if you enable this in a location{} block for
  # a specific directory, or on an individual server{} level.
  # gzip_static on;

  include sites-enabled/*;

Website Configuration

Once you have configured the main Nginx configuration file then you can start creating server blocks to serve your websites.

You will need to create a configuration file on a per site basis. These files will be located in /etc/nginx/sites-available/ and will house the server block for your website.

For the sake of this tutorial, I will use You will need to substitute with your website’s domain name, wherever it is mentioned.

Create the website configuration file:

sudo nano /etc/nginx/sites-available/

And then paste the following configuration in it:

# www to non-www redirect -- duplicate content is BAD:
# Choose between www and non-www, listen on the *wrong* one and redirect to
# the right one --

server {
  # don't forget to tell on which port this server listens
  listen 80;

  # listen on the www host

  # and redirect to the non-www host (declared below)
  rewrite ^$request_uri permanent;

server {
  listen 80;

  # The host name to respond to

  # Path for website directory
  root /sites/;

  index index.html;

  #Specify a charset
  charset utf-8;

  # Custom 404 page (if you have one), otherwise comment out the following line
  error_page 404 /404.html;

  # Redirect URLs with /index.html (this is optional, you can comment it out)
  if ($request_uri ~ /index\.html($|\?)) {
    rewrite ^(.*)/index\.html$ $1/ permanent;

  # Expires for static assets
  location ~* \.(?:manifest|appcache|html?|xml|json)$ {
    expires -1;
    access_log logs/static.log;

  location ~* \.(?:rss|atom)$ {
    expires 1h;
    add_header Cache-Control "public";

  location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
    expires max;
    access_log off;
    add_header Cache-Control "public";

  location ~* \.(?:css|js)$ {
    expires max;
    access_log off;
    add_header Cache-Control "public";

  location ~* \.(?:ttf|ttc|otf|eot|woff)$ {
    expires max;
    access_log off;
    add_header Cache-Control "public";

  # Protect System Files
  location ~* (?:^|/)\. {
    deny all;

  location ~* (?:\.(?:bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)|~)$ {
    deny all;

  # Force the latest IE version
  # Use ChromeFrame if it's installed for a better experience for the poor IE folk
  add_header "X-UA-Compatible" "IE=Edge";

  # Try to serve static files
  try_files $uri $uri/ /index.html =404;

Be sure to change /sites/ to your website’s root directory.

In order to take the site live on the internet, you will need to symlink it to /etc/nginx/sites-enabled/.

sudo rm -R /etc/nginx/sites-enabled/default
sudo ln -s /etc/nginx/sites-available/ /etc/nginx/sites-enabled/

Updating Nginx

If a new version of Nginx gets released, you can easily upgrade to it thanks to the Nginx Launchpad repo being constantly maintained.

Check which version of Nginx you are using:

nginx -v

Go to and check if a new stable version of Nginx has been released. If your version of Nginx is outdated then proceed to the next step.

Upgrade to the latest stable version:

sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup
sudo apt-get update
sudo apt-get install --only-upgrade nginx
  • The first command will backup your current Nginx configuration file because sometimes when you upgrade, the configuration file gets overwritten by the new version of Nginx therefore you should always backup.
  • The second command will refresh the package list and download information on new versions of packages including Nginx.
  • The third command will upgrade Nginx to the latest version in the Launchpad repo.

Thats it!