Initial Server Setup for AlmaLinux 9

    Everything you need to go from a fresh AlmaLinux 9 instance to a production-ready web server

    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

    System updates and package management
    Non-root sudo user with SSH key access
    Firewalld and SELinux configuration
    Swap space and automatic security updates
    LEMP stack (Nginx + MariaDB + PHP)
    LAMP stack (Apache + MariaDB + PHP)

    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:

    Update all packages
    dnf update -y

    If a kernel update was installed, reboot to load it:

    Reboot if needed
    reboot

    Optionally install the EPEL (Extra Packages for Enterprise Linux) repository, which provides additional software not in the base repos:

    Enable EPEL repository
    dnf install epel-release -y

    2. 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:

    Setting Hostname and Timezone →

    Configure hostnames (simple or FQDN), update /etc/hosts, set the timezone with timedatectl, and enable NTP synchronization.

    Quick reference:

    Set hostname and timezone
    # Set the hostname
    hostnamectl set-hostname your-server.example.com
    
    # Set timezone to UTC (recommended for servers)
    timedatectl set-timezone UTC
    
    # Verify
    hostnamectl
    timedatectl

    3. 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 user and grant sudo
    # 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 deploy

    Copy your SSH key to the new user so you can log in without a password:

    Copy SSH keys to new user
    # As root, copy the authorized_keys file
    rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy

    Test the new user before proceeding — open a new terminal and connect:

    Test SSH as the new user
    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:

    Edit SSH configuration
    sudo nano /etc/ssh/sshd_config

    Find and update these settings:

    /etc/ssh/sshd_config
    PermitRootLogin no
    PasswordAuthentication no
    PubkeyAuthentication yes
    Restart SSH
    sudo systemctl restart sshd

    Related Documentation

    5. Firewall Setup (firewalld)

    AlmaLinux 9 uses firewalld by default instead of UFW. Enable it and allow the services you need:

    Configure firewalld
    # 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-all
    Firewalld Basics — Full Guide →

    Zones, 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.

    Check SELinux status
    # View current status
    sestatus
    
    # Should show: SELinux status: enabled, Current mode: enforcing

    When 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.

    Install SELinux troubleshooting tools
    sudo dnf install policycoreutils-python-utils setroubleshoot-server -y

    7. Swap Space

    Adding swap space provides a safety net when your applications temporarily exceed available RAM. This is especially useful on smaller instances.

    Swap Partition — Full Guide →

    Detailed instructions for creating swap files, tuning swappiness, and sizing recommendations per VPS plan.

    Quick setup for a 2 GB swap file:

    Create a 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 -h

    8. Automatic Security Updates

    Keeping your server patched against known vulnerabilities is critical. AlmaLinux 9 uses dnf-automatic for automated updates.

    Automatic Security Updates — Full Guide →

    Complete walkthrough for RHEL/AlmaLinux/Rocky, Ubuntu/Debian, openSUSE, and Arch Linux — including email notifications and automatic reboots.

    Quick-start for AlmaLinux 9:

    Enable dnf-automatic
    # 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.timer

    9. 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

    Install Nginx
    sudo dnf install nginx -y
    sudo systemctl enable nginx
    sudo systemctl start nginx

    Verify 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:

    SELinux booleans for Nginx
    # 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 1

    9b. Install MariaDB

    Install MariaDB
    sudo dnf install mariadb-server -y
    sudo systemctl enable mariadb
    sudo systemctl start mariadb

    Run the security script to set a root password and remove insecure defaults:

    Secure MariaDB installation
    sudo mysql_secure_installation

    Recommended 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:

    9c. Install PHP

    AlmaLinux 9 ships with PHP 8.1 in the AppStream repository. Install PHP-FPM and common extensions:

    Install PHP 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 -y

    Configure PHP-FPM to work with Nginx. By default on AlmaLinux, PHP-FPM listens on a Unix socket owned by apache. Change it to nginx:

    Configure PHP-FPM for 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-fpm
    Verify PHP
    php -v
    sudo systemctl status php-fpm

    9d. Configure an Nginx Server Block

    Create a server block for your domain. Replace example.com with your actual domain:

    /etc/nginx/conf.d/example.com.conf
    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;
        }
    }
    Enable the site
    # 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 nginx

    9e. Test PHP Processing

    Create a test file
    echo '<?php phpinfo(); ?>' | sudo tee /var/www/example.com/html/info.php

    Visit 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:

    Remove test file
    sudo rm /var/www/example.com/html/info.php

    10. 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

    Install Apache
    sudo dnf install httpd -y
    sudo systemctl enable httpd
    sudo systemctl start httpd

    Verify 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).

    Install and secure MariaDB
    sudo dnf install mariadb-server -y
    sudo systemctl enable mariadb
    sudo systemctl start mariadb
    sudo mysql_secure_installation

    10c. Install PHP for Apache

    Apache uses mod_php by default on RHEL-based systems:

    Install PHP with Apache module
    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 httpd

    10d. Configure an Apache Virtual Host

    /etc/httpd/conf.d/example.com.conf
    <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>
    Enable the site
    # 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 httpd

    10e. Test PHP Processing

    Create and test
    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.php

    11. 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:

    Let's Encrypt via Certbot — Full Guide →

    Install Certbot, obtain certificates for Nginx or Apache, configure auto-renewal, and troubleshoot common issues.

    Quick-start for AlmaLinux 9:

    Install Certbot and obtain SSL
    # 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-run

    Next 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: