Based on Debian 11 "Bullseye" environment.

Nginx

Set up nginx, a webserver.

nginx

Install

“nginx” package has some variation according to the included modules. For general purposes, normal nginx (meta-package for nginx-core) should work. The list of modules for each package can be found from the package explanation. If you need more than nginx-extras, you have to build whatever you need by yourself.

# apt install nginx ssl-cert

Open the port for HTTP/HTTPS.

# firewall-cmd --add-service=http --permanent
# firewall-cmd --add-service=https --permanent
# firewall-cmd --reload

Site configuration

The simplest example

Like Apache2, nginx stores website configuration files at /etc/nginx/sites-available. To enable the site, add a symlink to that config file at /etc/nginx/sites-enabled.
The default file is a template of a site configuration file.
The simplest version should look like below.
(I don’t explain each line in detail. Please refer to the default configuration file or manuals.)

/etc/nginx/sites-available/example

server {
        listen 80;
        listen [::]:80;

        server_name example.jp;

        root /var/www/html;

        index index.html;

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

        access_log /var/log/nginx/example.jp-access.log;
        error_log /var/log/nginx/example.jp-error.log;
}

To enable this configuration, make a symlink at /etc/nginx/sites-enabled/example.jp and reload nginx.
You need to reload nginx whenever configurations are changed.

# cd /etc/nginx/sites-enabled
# ln -s /etc/nginx/sites-available/example.jp example.jp
# systemctl reload nginx

Enable PHP

PHP is required for common CMS such as WordPress or ConcreteCMS. Integrate PHP fpm to this site configuration. (They are also written in the default configuration.)

server {
        listen 80;
        listen [::]:80;

        server_name example.jp;

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.php;

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

        access_log /var/log/nginx/example.jp-access.log;
        error_log /var/log/nginx/example.jp-error.log;

        # pass PHP scripts to FastCGI server
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
        
                # With php-fpm (or other unix sockets):
                fastcgi_pass unix:/run/php/php-fpm.sock;
        }
}

PHP and fpm are already installed at the beginning, so the snippets and the socket are ready.

Enable HTTPS (with http2)

You need a server certificate to enable HTTPS. Before getting the proper certificate, you can start with the testing certificate 'snakeoil" installed with ssl-cert package.
The snakeoil certificate private key is stored in /etc/ssl/private/ssl-cert-snakeoil.key, and the snippet for this certificate is /etc/nginx/snippets/snakeoil.conf

server {
        listen 443 ssl http2; # Add http2
        listen [::]:443 ssl http2; # Add http2

        include snippets/snakeoil.conf; # include TLS config

        server_name example.jp;

        root /var/www/html;

        index index.html index.php;

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

        access_log /var/log/nginx/example.jp-access.log;
        error_log /var/log/nginx/example.jp-error.log;

        # pass PHP scripts to FastCGI server
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
        
                # With php-fpm (or other unix sockets):
                fastcgi_pass unix:/run/php/php-fpm.sock;
        }
}

With the above settings, the https connection is available (with the security alert about the certificate problem).

Redirect HTTP to HTTPS

To redirect the http connection to https, use “return” according to the nginx documents.

server {
        listen 80;
        listen [::]:80;
        server_name example.jp;
        return 301 https://$host$request_uri;
}

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

        include snippets/snakeoil.conf;

        server_name example.jp;

        root /var/www/html;

        index index.html index.php;

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

        access_log /var/log/nginx/example.jp-access.log;
        error_log /var/log/nginx/example.jp-error.log;

        # pass PHP scripts to FastCGI server
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
        
                # With php-fpm (or other unix sockets):
                fastcgi_pass unix:/run/php/php-fpm.sock;
        }
}

Gzip

Gzip compression is turned on by default, but only for the text/html. Enable compression for other text type contents.
NOTE: If you care about the BREACH attacks, do not turn on this compression. See gzip module explanation for details.

Global configurations

For example, if the server is in the local network and you don't have to care about the BREACH attacks, you can turn this on globally.
Uncomment all the gzip configurations in /etc/nginx/nginx.conf

gzip on;

gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

Reload nginx to enable.

# systemctl reload nginx

Per-site configuration

Gzip can be enabled within "server" section.

/etc/nginx/snippets/gzip.conf

gzip on;

gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

Include the snippet above.

server {
        listen 80;
        listen [::]:80;
        server_name example.jp;
        return 301 https://example.jp$request_uri;
}

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

        include snippets/snakeoil.conf;
        include snippets/gzip.conf;

        server_name example.jp;

        root /var/www/html;

        index index.html index.php;

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

        access_log /var/log/nginx/example.jp-access.log;
        error_log /var/log/nginx/example.jp-error.log;

        # pass PHP scripts to FastCGI server
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
        
                # With php-fpm (or other unix sockets):
                fastcgi_pass unix:/run/php/php-fpm.sock;
        }
}

Update History

2021-08-22

  • Correct some sentences
  • Change firewall configuration from UFW to firewalld
  • Add general configuration section to explain gzip

2021-09-02

  • Correct access log file name from "$host-access.log" to "example.jp-access.log"
    $host variable doesn't work in the log lines.