Setup of a Nginx HTTP Server on Fedora 37

In this tutorial, we install and configure an HTTP server for a static website which will be available under the domain foo.net.

Prerequisites

  • Being firm in using the command line.

  • A domain name, called foo.net in this tutorial.

  • A Fedora server, set up as depicted in Setup of a Server with Fedora 37.

Install

Nginx

# Install
sudo dnf install nginx

# Start the server on each boot
sudo systemctl enable nginx.service

# Start the server now
sudo systemctl start nginx.service

Firewall

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reload
sudo ufw status

Configure

sudo mkdir /var/www/foo
sudo vi /etc/nginx/conf.d/foo.net.conf

foo.net.conf:

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

    root /var/www/foo;

    index index.html;

    server_name foo.net;
    charset     utf-8;

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

    # deny access to hidden files and directories
    location ~ /\. {
        deny  all;
        access_log off;
        log_not_found off;
    }
}

Restart

sudo systemctl restart nginx.service

SSL certificate for HTTPS connections

Nginx

sudo systemctl stop nginx.service

Certbot

sudo certbot certonly --standalone
sudo certbot --nginx

Nginx

sudo systemctl start nginx.service

Copy project to server

scp -r build/html root@h1:/var/www/foo

Avoid matching unknown host names

Nginx always has a default server. In the absence of any server block explicitly marked as default_server, nginx will use the first server with a matching listen directive. As a result, Nginx might serve content of a domain that was not intended to be served under the domain name that the user typed into the address bar of his browser.

To only match known hosts, and return a "page not found" in all other cases, you can define a catch-all server block to handle any host names that do not match your server_name value.

sudo vi /etc/nginx/nginx.conf:

http {

    # ...

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        listen       443 ssl default_server;
        listen       [::]:443 ssl default_server;
        server_name  _;

        return       404;

        # NOTE: A certificate *must* be given, which can be a certificate
        # from any domain for this default server, merely returning 404.
        ssl_certificate /etc/letsencrypt/live/foo.net/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/foo.net/privkey.pem; # managed by Certbot
    }

    # ...
}

Appendix

Redirect all requests to an encrypted connection

The following is here just for reference. It should generally be done in each domain's configuration. Certbot does configure this automatically for each domain, so you don't have to do it.

sudo vi /etc/nginx/nginx.conf:

http {

    # ...

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name _;

        return 301 https://$host$request_uri;
    }

    # ...
}

Remove

listen       80 default_server;
listen       [::]:80 default_server;

from the "return 404" server section, as it has already been configured in the redirect to port 443.