Appearance
How to Install Nginx
Introduction
Nginx is a highly popular web server used for deploying web servers, reverse proxies, load balancers, and more. In this guide, we’ll walk through the process of installing Nginx specifically on a Rocky Linux-based operating system, configuring the firewall, and setting up self-signed certificates to enable HTTPS for our web server.
Prerequisites
Before deploying Nginx, ensure you have a regular user account with sudo privileges.
Step 1 - Installing Nginx
Nginx is available by default in Rocky Linux repositories. You can install it using the dnf package manager with the following command:
sudo dnf install nginxWhen prompted, review the installation details and press y to proceed. Once the installation is complete, enable and start the Nginx service with this command:
sudo systemctl enable --now nginxThis ensures Nginx starts automatically on boot and is running immediately.
Step 2 - Configuring the Firewall and SELinux
If firewalld and SELinux are enabled (which is the default on Rocky Linux), you won’t be able to access Nginx’s default homepage on port 80 without additional configuration. You’ll need to allow HTTP traffic through the firewall and permit network connections for HTTP in SELinux.
Run the following commands to allow the HTTP service in firewalld and reload the configuration:
sudo firewall-cmd --add-service=http --permanent && sudo firewall-cmd --reloadTo verify the rule has been applied, check the firewall settings:
sudo firewall-cmd --list-allYou should see output similar to this:
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0
sources:
services: cockpit dhcpv6-client http ssh
ports:
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:Next, allow HTTP network access in SELinux:
sudo setsebool -P httpd_can_network_connect trueStep 3 - Verifying the Nginx Service
Your web server should now be running. To confirm, check the status of the Nginx service:
sudo systemctl status nginxIf it’s running correctly, you’ll see output like this:
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled)
Active: active (running) since Wed 2025-03-19 01:56:22 UTC; 31s ago
Process: 362284 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
Process: 362285 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
Process: 362286 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Main PID: 362287 (nginx)
Tasks: 2 (limit: 10892)
Memory: 2.0M
CPU: 36ms
CGroup: /system.slice/nginx.service
├─362287 "nginx: master process /usr/sbin/nginx"
└─362288 "nginx: worker process"
Mar 19 01:56:22 homelab.immanuelbint.com systemd[1]: Starting The nginx HTTP and reverse proxy server...
Mar 19 01:56:22 homelab.immanuelbint.com nginx[362285]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Mar 19 01:56:22 homelab.immanuelbint.com nginx[362285]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Mar 19 01:56:22 homelab.immanuelbint.com systemd[1]: Started The nginx HTTP and reverse proxy server.You can now access the default Nginx homepage by entering your server’s IP address in a browser, like this: http://<ip-address>:80 (replace <ip-address> with your server’s actual IP).

Step 4 - Managing Nginx
With your web server running, here are some essential commands to manage the Nginx service:
Stop the Nginx service:
sudo systemctl stop nginxStart the Nginx service:
sudo systemctl start nginxRestart the Nginx service:
sudo systemctl restart nginx
Earlier, we enabled Nginx to start on boot. To disable this behavior, use:
sudo systemctl disable nginxNow, let’s explore key Nginx directories:
Main Configuration Folders
/etc/nginx: The primary Nginx configuration directory./etc/nginx/nginx.conf: The default configuration file for the homepage served on port 80./etc/nginx/conf.d: A directory for additional server block configurations, such as hosted websites or reverse proxy settings.
Nginx Logs
/var/log/nginx/access.log: Stores logs of all requests to the web server./var/log/nginx/error.log: Records all Nginx-related errors.
Step 5 - Setting Up TLS/SSL
To enhance security, we’ll upgrade our HTTP connection to HTTPS. Since we’re not using a public domain or paid certificate, we’ll create a self-signed certificate for learning purposes.
First, create a directory to store certificates and keys:
sudo mkdir -p /data/self-managed-ca/{certs,keys}
cd /data/self-managed-caCreate a Certificate Authority (CA)
Generate a CA configuration file (you can name it as desired):
tee -a ca.cnf <<EOF
# OpenSSL CA configuration file
[ ca ]
default_ca = CA_default
[ CA_default ]
default_days = 365
database = index.txt
serial = serial.txt
default_md = sha256
copy_extensions = copy
unique_subject = no
[ req ]
prompt=no
distinguished_name = distinguished_name
x509_extensions = extensions
[ distinguished_name ]
organizationName = Hostmaster
commonName = Hostmaster CA
[ extensions ]
keyUsage = critical,digitalSignature,nonRepudiation,keyEncipherment,keyCertSign
basicConstraints = critical,CA:true,pathlen:1
[ signing_policy ]
organizationName = supplied
commonName = optional
[ signing_node_req ]
keyUsage = critical,digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth,clientAuth
[ signing_client_req ]
keyUsage = critical,digitalSignature,keyEncipherment
extendedKeyUsage = clientAuth
EOFGenerate the CA key and set restrictive permissions:
sudo openssl genrsa -out keys/ca.key 4096
sudo chmod 400 keys/ca.keyCreate the CA certificate:
openssl req \
-new -x509 \
-config ca.cnf \
-key keys/ca.key \
-out certs/ca.crt \
-days 365 \
-batchCreate a Client Certificate
To simplify configuration, use variables for the hostname and IP address:
ip=$(hostname -I | awk '{print $1}')
hostname=$(hostname -f)Verify the variables:
echo $ip # Example output: 172.30.2.4
echo $hostname # Example output: homelab.immanuelbint.comReset the CA database:
rm -f index.txt serial.txt
touch index.txt
echo '01' > serial.txtCreate a node configuration file:
tee -a node.cnf <<EOF
[ req ]
prompt=no
distinguished_name = distinguished_name
req_extensions = extensions
[ distinguished_name ]
organizationName = Hostmaster
[ extensions ]
subjectAltName = critical,DNS:"$hostname",DNS:"$hostname",IP:"$ip"
EOFGenerate the client key:
openssl genrsa -out certs/"$hostname".key 4096
chmod 400 certs/"$hostname".keyCreate a Certificate Signing Request (CSR):
openssl req \
-new \
-config node.cnf \
-key certs/"$hostname".key \
-out "$hostname".csr \
-batchSign the CSR with the CA:
openssl ca \
-config ca.cnf \
-keyfile keys/ca.key \
-cert certs/ca.crt \
-policy signing_policy \
-extensions signing_node_req \
-in "$hostname".csr \
-out certs/"$hostname".crt \
-outdir certs/ \
-batchIf successful, you’ll see output like this:
Using configuration from ca.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
organizationName :ASN.1 12:'Hostmaster'
Certificate is to be certified until Mar 19 02:43:58 2026 GMT (365 days)
Write out database with 1 new entries
Database updatedVerify the certificate:
openssl x509 -in certs/"$hostname".crt -text | grep "X509v3 Subject Alternative Name" -A 1Expected output:
X509v3 Subject Alternative Name: critical
DNS:homelab.immanuelbint.com, DNS:homelab.immanuelbint.com, IP Address:172.30.2.4Update Nginx Configuration
Modify the Nginx configuration to use the SSL certificate. Replace the paths below with your actual certificate locations (e.g., /data/self-managed-ca):
sudo tee /etc/nginx/nginx.conf <<EOF
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
'\$status \$body_bytes_sent "\$http_referer" '
'"\$http_user_agent" "\$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name "$ip";
return 301 https://\$host\$request_uri; # Redirect to HTTPS
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
location / {
}
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name "$ip";
root /usr/share/nginx/html;
ssl_certificate "/data/self-managed-ca/certs/$hostname.crt";
ssl_certificate_key "/data/self-managed-ca/certs/$hostname.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2;
include /etc/nginx/default.d/*.conf;
location / {
}
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
EOFTest the configuration:
sudo nginx -tIf successful, you’ll see:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successfulRestart Nginx to apply the changes:
sudo systemctl restart nginxAllow HTTPS in the Firewall
Before testing, allow HTTPS traffic through the firewall:
sudo firewall-cmd --add-service=https --permanent && sudo firewall-cmd --reloadNow, access your server at https://<hostname>:443 (replace <hostname> with your actual hostname). You may see a "not secure" warning due to the self-signed certificate. To bypass this temporarily, import the CA certificate (certs/ca.crt) into your browser.

Related Scripts
- Content under construction