Skip to main content

Nginx Tutorial: HTTP, HTTPS, Reverse Proxy for Apache2

1329 words·
Nginx Reverse Proxy Apache Certbot Webserver
Table of Contents

Install Nginx, Command Overview
#

Installation
#

# Update package index
sudo apt update

# Install Nginx
sudo apt install nginx -y

# Check version
nginx -v

Start & Enable
#

# Start Nginx
sudo systemctl start nginx

# Stop Nginx
sudo systemctl stop nginx

# Restart Nginx
sudo systemctl restart nginx

# Enable Nginx
sudo systemctl enable nginx

Status & Logs
#

# Check status
sudo systemctl status nginx

# Check error details
journalctl -xeu nginx.service
# Error logs
sudo tail /var/log/nginx/error.log

# Access logs
sudo tail /var/log/nginx/access.log

Default paths
#

# Default website path
/var/www/html/
# Available website configuration files
/etc/nginx/sites-available/

# Enabled website configuration files
/etc/nginx/sites-enabled/

# Create symlink from sites-available to site-enabled
sudo ln -s /etc/nginx/sites-available/your_config /etc/nginx/sites-enabled/

Main Configuration
#

# Main configuration file
sudo vi /etc/nginx/nginx.conf

# Enable sites-enabled configurations: Should be enabled by default
include /etc/nginx/sites-enabled/*;

Website Configurations
#

HTTP (Testing Environment)
#

Create Configuration
#

# Copy default configuration
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/mywebsite.jklug.work
# Edit config
sudo vi /etc/nginx/sites-available/mywebsite.jklug.work

# /etc/nginx/sites-available/mywebsite.jklug.work
server {
       listen 80; # Listen to IPv4
       listen [::]:80; # Listen to IPv6

       server_name mywebsite.jklug.work; # Define domain name

       root /var/www/mywebsite.jklug.work; # Define website path
       index index.html;

       location / {
               try_files $uri $uri/ =404;
       }
}

HTML Testfile
#

# Create folder for website
sudo mkdir -p /var/www/mywebsite.jklug.work

# Change permissions
sudo chmod 0755 /var/www/mywebsite.jklug.work

# Create html file
sudo vi /var/www/mywebsite.jklug.work/index.html

# Change permissions
sudo chmod 644 /var/www/mywebsite.jklug.work/index.html
<!-- /var/www/mywebsite.jklug.work/index.html -->
<!DOCTYPE html>
<html>

<head>
	<title>jklug.work</title>
</head>

<body>
	<h1>Nginx Test</h1>
</body>

</html>

Enable Configuration
#

# Test configuration
sudo nginx -t

# Disable default configuration
sudo rm /etc/nginx/sites-enabled/default

# Enable configuration
sudo ln -s /etc/nginx/sites-available/mywebsite.jklug.work /etc/nginx/sites-enabled/

# Restart Nginx
sudo systemctl restart nginx

HTTPS
#

Certbot
#

# Install Certbot
sudo apt install certbot -y

# Stop Nginx / make port 80 available for Let's Encrypt
sudo systemctl stop nginx

# Create certificate
sudo certbot certonly --standalone -d mywebsite.jklug.work

# Renew certificate
sudo certbot renew
Note: A fully qualified domain name (FQDN) that points to the public IP of your server is necessary to issue certificates with Let’s Encrypt.

Create Configuration
#

# Copy default configuration
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/mywebsite.jklug.work

# Edit config
sudo vi /etc/nginx/sites-available/mywebsite.jklug.work
  • Configuration with Comments
# /etc/nginx/sites-available/mywebsite.jklug.work
server {
    listen 80; # Listen on port 80 IPv4
    listen [::]:80; # Listen on port 80 IPv6
    server_name mywebsite.jklug.work; # Define domain name
    return 302 https://$server_name$request_uri; # Redirect to port 443
}

server {

    listen 443 ssl http2; # Listen on port 443 IPv4
    listen [::]:443 ssl http2; # Listen on port 443 IPv6

    ssl_certificate         /etc/letsencrypt/live/mywebsite.jklug.work/fullchain.pem; # Define path to cert
    ssl_certificate_key     /etc/letsencrypt/live/mywebsite.jklug.work/privkey.pem; # Define path to cert

    server_name mywebsite.jklug.work; # Define domain name

    root /var/www/mywebsite.jklug.work; # Define website path
    index index.html index.htm;


    location / { # Define root block of website
            try_files $uri $uri/ =404; # Define served files
    }
}
  • Configuration without Comments
# /etc/nginx/sites-available/mywebsite.jklug.work
server {
    listen 80;
    listen [::]:80;
    server_name mywebsite.jklug.work;
    return 302 https://$server_name$request_uri;
}

server {

    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    ssl_certificate         /etc/letsencrypt/live/mywebsite.jklug.work/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/mywebsite.jklug.work/privkey.pem;

    server_name mywebsite.jklug.work;

    root /var/www/mywebsite.jklug.work;
    index index.html index.htm;


    location / {
            try_files $uri $uri/ =404;
    }
}

HTML Testfile
#

# Create folder for website
sudo mkdir -p /var/www/mywebsite.jklug.work

# Change permissions
sudo chmod 0755 /var/www/mywebsite.jklug.work

# Create html file
sudo vi /var/www/mywebsite.jklug.work/index.html

# Change permissions
sudo chmod 644 /var/www/mywebsite.jklug.work/index.html
<!-- /var/www/mywebsite.jklug.work/index.html -->
<!DOCTYPE html>
<html>

<head>
	<title>jklug.work</title>
</head>

<body>
	<h1>Nginx Test</h1>
</body>

</html>

Enable Configuration
#

# Test configuration
sudo nginx -t

# Disable default configuration
sudo rm /etc/nginx/sites-enabled/default

# Enable configuration
sudo ln -s /etc/nginx/sites-available/mywebsite.jklug.work /etc/nginx/sites-enabled/

# Restart Nginx
sudo systemctl restart nginx

Add PW Protection
#

Create User
#

# Update package index
sudo apt update

# Install apache2-utils
sudo apt install apache2-utils -y
# Create directory
sudo mkdir -p /etc/apache2/

# Create file to store the passwords
sudo touch /etc/apache2/.htpasswd

# Create user: Prompt for pw
sudo htpasswd /etc/apache2/.htpasswd user1

Edit Configuration
#

# Edit config
sudo vi /etc/nginx/sites-available/mywebsite.jklug.work
# /etc/nginx/sites-available/mywebsite.jklug.work
server {
    listen 80;
    listen [::]:80;
    server_name mywebsite.jklug.work;
    return 302 https://$server_name$request_uri;
}

server {

    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    ssl_certificate         /etc/letsencrypt/live/mywebsite.jklug.work/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/mywebsite.jklug.work/privkey.pem;

    server_name mywebsite.jklug.work;

    root /var/www/mywebsite.jklug.work;
    index index.html index.htm;


    location / {
            auth_basic           "Administrator’s Area"; # Define name of password-protected area
            auth_basic_user_file /etc/apache2/.htpasswd; # Define path to pw file
            try_files $uri $uri/ =404;
    }
}

Enable Configuration
#

# Test configuration
sudo nginx -t

# Restart Nginx
sudo systemctl restart nginx

Reverse Proxy
#

Redirect to another website
#

This configuration can be helpful for debugging, it just redirects to another domain: google.com

Edit Configuration
#

# Copy default configuration
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/mywebsite.jklug.work

# Edit config
sudo vi /etc/nginx/sites-available/mywebsite.jklug.work
# /etc/nginx/sites-available/mywebsite.jklug.work
server {
    listen 80;
    listen [::]:80;
    server_name mywebsite.jklug.work;
    return 302 https://$server_name$request_uri;
}

server {

    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    ssl_certificate         /etc/letsencrypt/live/mywebsite.jklug.work/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/mywebsite.jklug.work/privkey.pem;

    server_name mywebsite.jklug.work;


    location / {
        proxy_pass https://www.google.com;
        proxy_set_header Host www.google.com;
        proxy_set_header Referer https://www.google.com;
    }
}

Enable Configuration
#

# Test configuration
sudo nginx -t

# Restart Nginx
sudo systemctl restart nginx

Redirect to Apache Webserver
#

Apache2 Installation
#

Install Apache and change the default port to “8080”.

# Update package index
sudo apt update

# Install Apache webserver
sudo apt install apache2 -y

Default Website
#

Change the default HTML file.

# Change default html file
sudo vi /var/www/html/index.html
<!-- /var/www/html/index.html -->
<!DOCTYPE html>
<html>

<head>
	<title>jklug.work</title>
</head>

<body>
	<h1>Apache Test</h1>
</body>

</html>

Change Ports
#

# Open configuration
sudo vi /etc/apache2/ports.conf
# /etc/apache2/ports.conf
Listen 8080 # Define port

<IfModule ssl_module>
        Listen 443
</IfModule>

<IfModule mod_gnutls.c>
        Listen 443
</IfModule>

Default Configuration
#

# Open the default website configuration
sudo vi /etc/apache2/sites-enabled/000-default.conf

Change <VirtualHost *:80> to port 8080. It should look like this:

<VirtualHost *:8080>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        #ServerName www.example.com

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html

        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
</VirtualHost>
# Test configuration
sudo apache2ctl -t -f /etc/apache2/sites-enabled/000-default.conf

Restart Apache
#

# Restart Apache
sudo systemctl restart apache2

# Check status
sudo systemctl status apache2

# Check logs
sudo tail /var/log/apache2/error.log
# Test website in browser
IP:8080

Redirect Nginx to Apache: http
#

# Edit Nginx configuration
sudo vi /etc/nginx/sites-available/mywebsite.jklug.work
server {
    listen 80;
    server_name mywebsite.jklug.work; # Define domain name

    location / {
        proxy_pass http://127.0.0.1:8080/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
# Enable configuration
sudo ln -s /etc/nginx/sites-available/mywebsite.jklug.work /etc/nginx/sites-enabled/

# Test configuration
sudo nginx -t

# Restart Nginx
sudo systemctl restart nginx

Redirect Nginx to Apache: https
#

# Edit Nginx configuration
sudo vi /etc/nginx/sites-available/mywebsite.jklug.work
server {
    listen 80;
    listen [::]:80;
    server_name mywebsite.jklug.work;
    return 302 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name mywebsite.jklug.work;

    ssl_certificate         /etc/letsencrypt/live/mywebsite.jklug.work/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/mywebsite.jklug.work/privkey.pem;


    location / {
        proxy_pass http://127.0.0.1:8080/; # Redirect to localhost port 8080
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
# Enable configuration
sudo ln -s /etc/nginx/sites-available/mywebsite.jklug.work /etc/nginx/sites-enabled/

# Test configuration
sudo nginx -t

# Restart Nginx
sudo systemctl restart nginx

Open your domain in a browser the Apache website should now be secure.


Links #

# Nginx Official Documentation
https://docs.nginx.com/nginx/admin-guide/