Web server notes

Nginx

Basic nginx.conf this redirects all http to https and uses conf.d to configure other servers

user  nginx;
worker_processes auto;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

http {
    sendfile on;
    tcp_nopush on;
    types_hash_max_size 2048;
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    gzip on;

    # Security

    # Certbot recommends : 
    ssl_session_cache shared:le_nginx_SSL:10m;
    ssl_session_timeout 1440m;
    ssl_session_tickets off;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";

    server_tokens off;
    client_header_buffer_size 1k;
    large_client_header_buffers 2 1k;
    add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";

    # Logs
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    # Default
    server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name _;
        # Redirect to https
        return 301 https://$host$request_uri;
    }

    # Include services
    include /etc/nginx/conf.d/*.conf;

}

For running services you need to create a service.conf on the conf.d directory, something like this

server {
    server_name your.domain;

    listen 443 ssl http2;

    ssl_certificate /etc/letsencrypt/live/your.domain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your.domain/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_http_version 1.1;
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

}

For cases when you need to send more data through nginx.

server {
    server_name bigfiles.domain.tld;
    client_max_body_size 512M;
    ...
}

If you only want it on IPv6

server {
    listen [::]:80 default_server ipv6only=on;
    server_name _;
    ...
}

For proxy pass with selinux use:

setsebool -P httpd_can_network_connect on 

Problems with files permissions and selinux , solve them with

sudo grep nginx /var/log/audit/audit.log | audit2allow -M nginx > nginx.te \ 
&& sudo semodule -i nginx.pp

Serving files

server {
    ...
    root /directorie/to/serve;
    autoindex on;
    autoindex_exact_size off;
    autoindex_localtime on;
}

Authentication

To generate a password file

Only use -c when creating the file

sudo htpasswd -c /etc/nginx/.htpasswd first_user

Add this to your server config

server {
    auth_basic "Private sharing files";
    auth_basic_user_file /etc/nginx/.htpasswd; 
}

Common error codes

code class
1xx Informational
2xx Success
3xx Redirection
4xx Client Error
5xx Server Error

return 400; - Bad Request: the HTTP request that was sent to the server has invalid syntax.

return 401; - Unauthorized: that the user trying to access the resource has not been authenticated or has not been authenticated correctly.

return 403; - Forbidden: that the user made a valid request but the server is refusing to serve the request, due to a lack of permission to access the requested resource

return 404; - Not found: that the user is able to communicate with the server but it is unable to locate the requested file or resource.

return 444; - Not return anything

return 500; - Internal server error: that server cannot process the request for an unknown reason. Sometimes this code will appear when more specific 5xx errors are more appropriate.

return 502; - Bad Gateway: that the server is a gateway or proxy server, and it is not receiving a valid response from the backend servers that should actually fulfill the request.

return 503; - Gateway timeout: that the server is a gateway or proxy server, and it is not receiving a response from the backend servers within the allowed time period.

Certbot

Let's encrypt, has a service so you can easily get ssl certificates, the basic cerbot command can be installed with

sudo dnf install certbot
# If you want to use pluggins like nginx do it with pip
sudo dnf install python3 augeas-libs
sudo python3 -m venv /opt/certbot/
sudo /opt/certbot/bin/pip install --upgrade pip
sudo /opt/certbot/bin/pip install certbot
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot
echo "0 0,12 * * * root /usr/bin/certbot renew -q" | sudo tee -a /etc/crontab > /dev/null

It is possible to get a certificate modifying a TXT record on the dns, the advantage is that you can use wildcards like *.domain.tld and there is no need to have a web server running or exposed. But you will have to renew this certificates manually every 90 days.

sudo certbot --manual --preferred-challenges dns certonly

The automated way is having a webserver exposed so letsencrypt can verify you own the domain, the requirements is having nginx up and running and public DNS records pointing to that server, but the advantage is that those certificates will automatically renew.

sudo /opt/certbot/bin/pip install certbot-nginx
sudo certbot certonly --nginx -d sub.domain.tld

Using private SSL certificates and Certification Authority

From vaultwarden wiki

In cases you want ssl certificates but not need them to be public, you can sign your own ones and only trust them on your devices, this way there is no need of external authorities like letsencrypt and free use of any domain you want, even if not registrated. In the example, example.lan is the domain being example the name of the service

The first step is creating the key of the Certification Authority.

openssl genpkey -algorithm RSA -aes128 -out private-ca.key -outform PEM -pkeyopt rsa_keygen_bits:2048

And for creating the certificate, that will work for 10 years, this is the certificate that need to be trusted by the client devices.

openssl req -x509 -new -nodes -sha256 -days 3650 -key private-ca.key -out self-signed-ca-cert.crt

In order to create domain certificates, create a key

openssl genpkey -algorithm RSA -out service.key -outform PEM -pkeyopt rsa_keygen_bits:2048

And create a certificate request

openssl req -new -key service.key -out service.csr

Fill the configuration file service.ext, change the dns alt_names accordingly.

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = service.lan
DNS.2 = www.service.lan

And finaly generate the certificate signed from the C.A.

openssl x509 -req -in service.csr -CA self-signed-ca-cert.crt -CAkey private-ca.key -CAcreateserial -out service.crt -days 365 -sha256 -extfile service.ext

To use this certificates on Nginx copy the service.crt and service.key file to the server in a directory it can be accessed by the nginx process. CHANGE PERMITIONS TO 400 AND CHOWN TO ROOT

ssl_certificate /etc/nginx/certs/service.crt;
ssl_certificate_key /etc/nginx/certs/vaultwarden.key;

Finally, copy the self-signed-ca-cert.crt to every device and authorize it.