Server Setup for Rocky Linux 9
Login with Root
ssh root@your_server_ip
Install Package Updates
dnf check-update
dnf upgrade
Setup Firewall (firewalld)
dnf install firewalld -y
systemctl start firewalld
systemctl status firewalld
Check Status and Add HTTP/HTTPS
firewall-cmd --permanent --list-all
firewall-cmd --get-services
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
Create User
wheel
= sudo
group
adduser your_user
passwd your_user
usermod -aG wheel your_user
Setup SSH for New User
On local machine:
ssh-keygen -b 4096 -f /home/your_user/.ssh/ssh_key_name
ssh-copy-id -i /home/your_user/.ssh/ssh_key_name your_user@your_server_ip
To automatically use key (and optional different port) when connecting:
nano ~/.ssh/config
And in there add entry:
Host your_server_ip
IdentityFile ~/.ssh/ssh_key_name
IdentitiesOnly yes
Port your_ssh_port
Now to connect to server with user:
ssh your_user@your_server_ip
Common SSH Configuration
Disabling Password Authentication
sudo nano /etc/ssh/sshd_config
...
PasswordAuthentication no
...
sudo systemctl restart sshd
Changing SSH Port Number
Make sure to open the new SSH port in your firewall before you restart the SSH daemon with the new port setting, otherwise you will be locked out of your server.
sudo firewall-cmd --permanent --add-port=your_ssh_port/tcp
sudo nano /etc/ssh/sshd_config
...
# Port 22
Port your_ssh_port
...
If SELinux is installed (e.g. for CentOS or RockyLinux), add the ssh port to the SELinux port management too.
sudo dnf install policycoreutils-python-utils
sudo semanage port -a -t ssh_port_t -p tcp your_ssh_port
sudo systemctl restart sshd
After confirming you can login via SSH through the new port, you can remove the default SSH port from the open firewall ports.
sudo firewall-cmd --permanent --remove-service ssh
Disable Root Login
sudo nano /etc/ssh/sshd_config
...
PermitRootLogin no
...
sudo systemctl restart sshd
Setup Nginx
sudo dnf install nginx
sudo systemctl enable nginx
sudo systemctl start nginx
systemctl status nginx
Visiting the server IP in your browser should give you the Nginx test page.
http://your_server_ip
Setup Nginx Site
Add new directory to host the site from.
sudo mkdir -p /var/www/your_domain/web
sudo chown -R $USER:$USER /var/www/your_domain/web
nano /var/www/your_domain/web/index.html
<html>
<head>
<title>Welcome to your_domain</title>
</head>
<body>
<h1>
Success! Your Nginx server is successfully configured for
<em>your_domain</em>.
</h1>
<p>This is a sample page.</p>
</body>
</html>
Add configuration file for the new site.
sudo nano /etc/nginx/conf.d/your_domain.conf
server {
server_name your_domain www.your_domain;
listen 80;
listen [::]:80;
root /var/www/your_domain/web;
index index.html index.htm index.nginx-debian.html;
location / {
try_files $uri $uri/ =404;
}
}
Check configuration syntax
sudo nginx -t
sudo systemctl restart nginx
To serve site from non-default directory, add new directory to SELinux security context.
sudo chcon -vR system_u:object_r:httpd_sys_content_t:s0 /var/www/your_domain/web/
Setup SSL for the new site
Install certbot
via the EPEL repository.
sudo dnf install epel-release
sudo dnf install certbot python3-certbot-nginx
Generate certificates for the site.
sudo certbot --nginx -d your_domain -d www.your_domain certonly
Update the nginx configuration for the site.
sudo nano /etc/nginx/conf.d/your_domain.conf
server {
server_name your_domain www.your_domain;
listen 443 ssl;
listen [::]:443 ssl;
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;
root /var/www/your_domain/web;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
server {
server_name your_domain www.your_domain;
listen 80;
listen [::]:80;
return 301 https://$host$request_uri;
}
To redirect all non-www requests to the www domain, use this server configuration instead.
server {
server_name www.your_domain;
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/www.your_domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.your_domain/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
root /var/www/your_domain/web;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
server {
server_name your_domain;
listen 443 ssl;
listen [::]:443 ssl;
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;
return 301 https://www.$host$request_uri;
}
server {
server_name your_domain www.your_domain;
listen 80;
listen [::]:80;
return 301 https://www.$host$request_uri;
}
Note that this server configuration uses a different certificate for the non-www and www domain respectively. Alternatively, you can use the same certificate for both domains by defining the second domain as Subject Alternative Name.
Test the renewal process.
sudo certbot renew --dry-run
Usually the certbot installation comes with automated renewals directly configured. This can be confirmed by checking either the crontab or systemd timers for the certbot renew
command.
For systemd timers:
sudo systemctl list-timers --all
In case the systemd timer is inactive, you can enable and start it manually with:
sudo systemctl enable certbot-renew.timer
sudo systemctl start certbot-renew.timer
sudo systemctl status certbot-renew.timer
For crontab:
sudo crontab -e
TODO
- fail2ban (https://www.digitalocean.com/community/tutorials/how-to-protect-ssh-with-fail2ban-on-rocky-linux-9)
- automatic updates (https://www.digitalocean.com/community/tutorials/how-to-keep-rocky-linux-9-servers-updated)