This guide walks you through every essential step after launching a fresh AlmaLinux 9 Cloud VPS — from system updates and user creation through installing a complete LEMP or LAMP web server stack. AlmaLinux is a community-driven, RHEL-compatible distribution that uses dnf for package management, firewalld for firewalling, and has SELinux enabled by default. Where dedicated documentation already exists for a topic, we link directly to it.
What You'll Set Up
Prerequisites
- • A RamNode Cloud VPS running AlmaLinux 9
- • Root SSH access to the server (see SSH Keys)
- • A domain name pointed at your server's IP (optional, but required for SSL)
1. System Updates
After your first SSH login, update all packages to their latest versions using dnf:
dnf update -yIf a kernel update was installed, reboot to load it:
rebootOptionally install the EPEL (Extra Packages for Enterprise Linux) repository, which provides additional software not in the base repos:
dnf install epel-release -y2. Hostname & Timezone
Setting a proper hostname and timezone is important for logging, scheduled tasks, and SSL certificates. We have a dedicated guide covering both topics in detail:
Configure hostnames (simple or FQDN), update /etc/hosts, set the timezone with timedatectl, and enable NTP synchronization.
Quick reference:
# Set the hostname
hostnamectl set-hostname your-server.example.com
# Set timezone to UTC (recommended for servers)
timedatectl set-timezone UTC
# Verify
hostnamectl
timedatectl3. Create a Sudo User
Running everything as root is a security risk. Create a regular user and add it to the wheel group (AlmaLinux's sudo group):
# Create a new user (replace 'deploy' with your preferred username)
adduser deploy
# Set a password
passwd deploy
# Add to the wheel group for sudo access
usermod -aG wheel deployCopy your SSH key to the new user so you can log in without a password:
# As root, copy the authorized_keys file
rsync --archive --chown=deploy:deploy ~/.ssh /home/deployTest the new user before proceeding — open a new terminal and connect:
ssh deploy@YOUR_SERVER_IP⚠️ Important: Do not close your root session until you've confirmed the new user can log in and run sudo commands successfully.
4. SSH Hardening
Once your sudo user is working, harden SSH by disabling root login and password authentication:
sudo nano /etc/ssh/sshd_configFind and update these settings:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yessudo systemctl restart sshdRelated Documentation
- SSH Keys — Managing SSH key pairs for secure authentication
- SSH 2FA Setup — Add two-factor authentication for an extra layer of protection
- Fail2Ban Guide — Automatically ban IPs after failed login attempts
- Lost SSH Access Recovery — Steps to recover if you get locked out
5. Firewall Setup (firewalld)
AlmaLinux 9 uses firewalld by default instead of UFW. Enable it and allow the services you need:
# Ensure firewalld is running
sudo systemctl enable firewalld
sudo systemctl start firewalld
# Allow SSH (usually enabled by default)
sudo firewall-cmd --permanent --add-service=ssh
# Allow HTTP and HTTPS for web traffic
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
# Reload to apply changes
sudo firewall-cmd --reload
# Verify active rules
sudo firewall-cmd --list-allZones, rich rules, port forwarding, rate limiting, and advanced firewalld configuration for RHEL-based systems.
⚠️ Warning: Always ensure SSH is allowed before enabling firewalld. If you're also using Security Groups in the Cloud Control Panel, both must allow traffic for it to reach your server.
6. SELinux
AlmaLinux 9 ships with SELinux in Enforcing mode by default. SELinux provides mandatory access controls that add an important layer of security. We strongly recommend keeping it enabled.
# View current status
sestatus
# Should show: SELinux status: enabled, Current mode: enforcingWhen installing web servers and databases, you may need to set SELinux booleans to allow specific functionality. The LEMP and LAMP sections below include the necessary SELinux commands.
💡 Tip: If something isn't working as expected, check /var/log/audit/audit.log for SELinux denials. The audit2why tool (from policycoreutils-python-utils) can help diagnose them.
sudo dnf install policycoreutils-python-utils setroubleshoot-server -y7. Swap Space
Adding swap space provides a safety net when your applications temporarily exceed available RAM. This is especially useful on smaller instances.
Detailed instructions for creating swap files, tuning swappiness, and sizing recommendations per VPS plan.
Quick setup for a 2 GB swap file:
# Create a 2G swap file
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# Make it permanent
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# Verify
free -h8. Automatic Security Updates
Keeping your server patched against known vulnerabilities is critical. AlmaLinux 9 uses dnf-automatic for automated updates.
Complete walkthrough for RHEL/AlmaLinux/Rocky, Ubuntu/Debian, openSUSE, and Arch Linux — including email notifications and automatic reboots.
Quick-start for AlmaLinux 9:
# Install dnf-automatic
sudo dnf install dnf-automatic -y
# Configure for security updates only
sudo sed -i 's/apply_updates = no/apply_updates = yes/' /etc/dnf/automatic.conf
sudo sed -i 's/upgrade_type = default/upgrade_type = security/' /etc/dnf/automatic.conf
# Enable and start the timer
sudo systemctl enable --now dnf-automatic.timer
# Verify the timer is active
sudo systemctl status dnf-automatic.timer9. LEMP Stack (Nginx + MariaDB + PHP)
The LEMP stack uses Nginx as the web server, MariaDB as the database (the default RHEL-family DB), and PHP for server-side processing. It's ideal for WordPress, Laravel, and other PHP applications.
9a. Install Nginx
sudo dnf install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginxVerify Nginx is running by visiting http://YOUR_SERVER_IP — you should see the default Nginx test page. If you've already allowed HTTP in firewalld (Step 5), the page should load immediately.
SELinux: Allow Nginx to connect to the network
If your PHP application needs to make outbound HTTP requests (APIs, email, etc.), enable the httpd_can_network_connect boolean:
# Allow Nginx/PHP to make network connections
sudo setsebool -P httpd_can_network_connect 1
# Allow Nginx/PHP to connect to databases
sudo setsebool -P httpd_can_network_connect_db 1
# Allow Nginx/PHP to send mail
sudo setsebool -P httpd_can_sendmail 19b. Install MariaDB
sudo dnf install mariadb-server -y
sudo systemctl enable mariadb
sudo systemctl start mariadbRun the security script to set a root password and remove insecure defaults:
sudo mysql_secure_installationRecommended answers: set a strong root password, remove anonymous users (Y), disallow remote root login (Y), remove test database (Y), and reload privilege tables (Y).
Database Deployment Guides
For more advanced database setups, see our dedicated guides:
- MariaDB Deployment Guide — Replication, backups, performance tuning
- MySQL Deployment Guide — Alternative to MariaDB with Oracle support
- PostgreSQL Deployment Guide — Advanced relational database
9c. Install PHP
AlmaLinux 9 ships with PHP 8.1 in the AppStream repository. Install PHP-FPM and common extensions:
sudo dnf install php-fpm php-mysqlnd php-cli php-curl php-gd php-mbstring php-xml php-zip php-json php-opcache -yConfigure PHP-FPM to work with Nginx. By default on AlmaLinux, PHP-FPM listens on a Unix socket owned by apache. Change it to nginx:
sudo sed -i 's/user = apache/user = nginx/' /etc/php-fpm.d/www.conf
sudo sed -i 's/group = apache/group = nginx/' /etc/php-fpm.d/www.conf
sudo sed -i 's/listen.owner = nobody/listen.owner = nginx/' /etc/php-fpm.d/www.conf
sudo sed -i 's/listen.group = nobody/listen.group = nginx/' /etc/php-fpm.d/www.conf
sudo systemctl enable php-fpm
sudo systemctl start php-fpmphp -v
sudo systemctl status php-fpm9d. Configure an Nginx Server Block
Create a server block for your domain. Replace example.com with your actual domain:
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}# Create the web root
sudo mkdir -p /var/www/example.com/html
sudo chown -R nginx:nginx /var/www/example.com
# Save the config above to:
sudo nano /etc/nginx/conf.d/example.com.conf
# Set SELinux context for the web root
sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/example.com(/.*)?"
sudo restorecon -Rv /var/www/example.com
# Test and reload
sudo nginx -t
sudo systemctl reload nginx9e. Test PHP Processing
echo '<?php phpinfo(); ?>' | sudo tee /var/www/example.com/html/info.phpVisit http://example.com/info.php. If you see the PHP info page, your LEMP stack is working. Delete this file afterward — it exposes sensitive configuration details:
sudo rm /var/www/example.com/html/info.php10. LAMP Stack (Apache + MariaDB + PHP)
The LAMP stack uses Apache (httpd) instead of Nginx. Choose LAMP if your application relies on .htaccess files or Apache-specific modules. If you already installed Nginx in Step 9, skip this section.
⚠️ Choose one: Install either the LEMP stack (Step 9) or the LAMP stack (Step 10), not both. They serve the same purpose with different web servers.
10a. Install Apache
sudo dnf install httpd -y
sudo systemctl enable httpd
sudo systemctl start httpdVerify Apache is running by visiting http://YOUR_SERVER_IP.
10b. Install MariaDB
The MariaDB installation is the same as in the LEMP stack above (Step 9b).
sudo dnf install mariadb-server -y
sudo systemctl enable mariadb
sudo systemctl start mariadb
sudo mysql_secure_installation10c. Install PHP for Apache
Apache uses mod_php by default on RHEL-based systems:
sudo dnf install php php-mysqlnd php-cli php-curl php-gd php-mbstring php-xml php-zip php-json php-opcache -y
# Restart Apache to load the PHP module
sudo systemctl restart httpd10d. Configure an Apache Virtual Host
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/html
<Directory /var/www/example.com/html>
AllowOverride All
Require all granted
</Directory>
ErrorLog /var/log/httpd/example.com-error.log
CustomLog /var/log/httpd/example.com-access.log combined
</VirtualHost># Create web root
sudo mkdir -p /var/www/example.com/html
sudo chown -R apache:apache /var/www/example.com
# Save the config above to:
sudo nano /etc/httpd/conf.d/example.com.conf
# Set SELinux context for the web root
sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/example.com(/.*)?"
sudo restorecon -Rv /var/www/example.com
# Test and reload
sudo apachectl configtest
sudo systemctl reload httpd10e. Test PHP Processing
echo '<?php phpinfo(); ?>' | sudo tee /var/www/example.com/html/info.php
# Visit http://example.com/info.php, then remove:
sudo rm /var/www/example.com/html/info.php11. SSL Certificates
Once you have a domain pointed at your server and a web server running, add free SSL/TLS certificates from Let's Encrypt using Certbot:
Install Certbot, obtain certificates for Nginx or Apache, configure auto-renewal, and troubleshoot common issues.
Quick-start for AlmaLinux 9:
# Install Certbot (requires EPEL)
sudo dnf install epel-release -y
# For Nginx
sudo dnf install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com -d www.example.com
# For Apache
sudo dnf install certbot python3-certbot-apache -y
sudo certbot --apache -d example.com -d www.example.com
# Verify auto-renewal
sudo certbot renew --dry-runNext Steps
Your AlmaLinux 9 server is now secured, updated, and running a full web server stack. Here are some recommended next steps depending on what you plan to deploy:
Deploy an Application
Harden Security
Use Docker Instead
If you prefer containerized deployments over bare-metal stacks:
→ Docker Basics Guide→ Docker Compose Guide