A self-signed SSL certificate lets you run Apache over HTTPS on Rocky Linux 10 without buying one from a Certificate Authority, which makes it the right call for staging servers, internal apps, and local lab setups where a publicly trusted cert isn’t needed.

A self-signed SSL certificate is a simple way to enable HTTPS on Apache without purchasing a certificate from a Certificate Authority (CA).

Many older tutorials still use a basic openssl req -x509 command to create a certificate. While that works, it often creates a certificate without a Subject Alternative Name (SAN) that modern web browsers such as Chrome and Firefox have required SAN support for years. Without it, visitors will see errors like ERR_CERT_COMMON_NAME_INVALID, even if the certificate’s Common Name appears correct.

In this guide, you’ll create a proper self-signed certificate using a san.cnf configuration file that includes SAN entries. You’ll then configure a complete Apache SSL VirtualHost for store.linuxapp.com and apply a few recommended TLS security settings. The same procedure also works on RHEL 10 and AlmaLinux 10.

Prerequisites

Before starting, make sure you have:

  • Rocky Linux 10 is installed with a non-root sudo user.
  • A domain name pointed to your server’s IP address (the guide uses store.tecmint.com as the example).
  • Port 80 and 443 are accessible, or firewall rules you can modify.
If you need a Linux server to follow along, DigitalOcean offers reliable cloud VPS plans starting at $4/month. You also get $200 in free credits to spin up your first server and try it yourself, available for TecMint members. We may earn a commission at no extra cost to you.
TecMint Weekly Newsletter
Get the Learn Linux 7 Days Crash Course free when you join 34,000+ Linux professionals reading every Thursday.
Check your email for a magic link to get started.
Something went wrong. Please try again.

Step 1: Install Apache and mod_ssl

Rocky Linux 10 already includes OpenSSL in the base operating system, so you don’t need to install it separately. What you do need is Apache (httpd) and the mod_ssl package, which adds SSL/TLS support to the web server.

sudo dnf install httpd mod_ssl -y

When mod_ssl is installed, it automatically creates a default SSL configuration file at:

/etc/httpd/conf.d/ssl.conf

Next, start Apache and configure it to launch automatically whenever the server boots:

sudo systemctl start httpd
sudo systemctl enable --now httpd

Now verify that Apache is running correctly:

sudo systemctl status httpd
Check Apache Server Status
Check Apache Server Status
If this helped you get Apache running on Rocky Linux 10, who’s still fighting the old setup.

Step 2: Open Ports 80 and 443 in the Firewall

Rocky Linux uses firewalld to control incoming network traffic. By default, only approved services and ports are allowed through the firewall.

Since Apache serves regular web traffic on port 80 (HTTP) and encrypted traffic on port 443 (HTTPS), both ports must be opened. Otherwise, visitors won’t be able to reach your website even if Apache is running correctly.

Run the following commands:

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

To verify that both services are allowed through the firewall, run:

sudo firewall-cmd --list-services

You can also confirm that Apache is listening on both web ports with:

sudo ss -tlnp | grep httpd
Allow Web Traffic Through Firewalld
Allow Web Traffic Through Firewalld

With the firewall ready, the next step is to create a proper self-signed SSL certificate with Subject Alternative Name (SAN) support.

Step 3: Create the OpenSSL Configuration File with SAN

A Subject Alternative Name (SAN) specifies the hostnames and IP addresses that a certificate is valid for and modern browsers no longer rely on the Common Name (CN) alone when verifying certificates.

If a certificate doesn’t contain a SAN entry, browsers such as Chrome, Firefox, and Edge will reject it with an error like:

ERR_CERT_COMMON_NAME_INVALID

First, create a directory to store the certificate, private key, and configuration file:

sudo mkdir -p /etc/ssl/store.linuxapp.com

Next, create the OpenSSL configuration file:

sudo vi /etc/ssl/store.linuxapp.com/san.cnf

Add the following contents:

[req]
default_bits       = 2048
prompt             = no
default_md         = sha256
distinguished_name = dn
x509_extensions    = v3_req

[dn]
C  = IN
ST = Maharashtra
L  = Mumbai
O  = LinuxApp
OU = IT
CN = store.linuxapp.com

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = store.linuxapp.com
DNS.2 = www.store.linuxapp.com

Here’s what the important sections do:

  • [dn] contains the certificate identity information.
  • CN (Common Name) specifies the primary hostname.
  • [v3_req] enables certificate extensions.
  • subjectAltName tells OpenSSL to use the entries defined in [alt_names].
  • DNS.1 and DNS.2 define the hostnames that browsers will trust for this certificate.

In this example:

  • store.linuxapp.com is the main website.
  • www.store.linuxapp.com covers the www version of the same site.

If your server uses a different domain name, replace every occurrence of store.linuxapp.com with your own hostname.

You can also add additional domains or subdomains by creating more entries:

[alt_names]
DNS.1 = store.linuxapp.com
DNS.2 = www.store.linuxapp.com
DNS.3 = api.store.linuxapp.com
DNS.4 = admin.store.linuxapp.com

For internal applications accessed by IP address, you can include IP-based SAN entries as well:

[alt_names]
DNS.1 = store.linuxapp.com
IP.1  = 192.168.1.100

Once you’ve finished editing the file, save it and exit the editor.

If the SAN requirement was news to you, who’s been getting browser cert errors they can’t explain.

Step 4: Generate the Private Key and Self-Signed Certificate

Now that the san.cnf file is in place, you can generate both the private key and the self-signed certificate in a single command.

sudo openssl req -x509 -nodes -days 365 
  -newkey rsa:2048 
  -keyout /etc/ssl/store.linuxapp.com/apache.key 
  -out /etc/ssl/store.linuxapp.com/apache.crt 
  -config /etc/ssl/store.linuxapp.com/san.cnf

During the process, OpenSSL displays progress indicators while generating the RSA key.

Create a Self-Signed SSL Certificate
Create a Self-Signed SSL Certificate

After the command finishes, you’ll have two new files:

  • apache.key – Your private key.
  • apache.crt – Your self-signed SSL certificate.

Next, you need to secure the private key, which is the most sensitive file in the entire setup, because if anyone can obtains it can impersonate your website.

sudo chmod 600 /etc/ssl/store.linuxapp.com/apache.key
sudo chmod 644 /etc/ssl/store.linuxapp.com/apache.crt

Verify both files exist with the right permissions.

ls -l /etc/ssl/store.linuxapp.com/

Output:

total 12
-rw-r--r--. 1 root root 1371 Jun  1 11:24 apache.crt
-rw-------. 1 root root 1704 Jun  1 11:24 apache.key
-rw-r--r--. 1 root root  334 Jun  1 11:24 san.cnf

Now verify that the SAN entries were actually embedded into the certificate.

openssl x509 -in /etc/ssl/store.linuxapp.com/apache.crt -text -noout | grep -A2 "Subject Alternative"
Confirm SAN Configuration in Your SSL Certificate
Confirm SAN Configuration in Your SSL Certificate

If you see your hostnames listed under Subject Alternative Name, the certificate was generated correctly.

If the SAN section is missing or empty, browsers such as Chrome and Firefox will reject the certificate with hostname validation errors, even if the Common Name (CN) matches the site name.

Step 5: Configure the Apache SSL VirtualHost

Although mod_ssl installs a default SSL configuration file (ssl.conf), it’s better to create a separate VirtualHost file for each website, which keeps your configuration organized and makes it easier to manage multiple sites on the same server.

Before configuring Apache, create a simple test website under your DocumentRoot directory so you have something to serve over HTTPS.

sudo mkdir -p /var/www/store.linuxapp.com
echo "<h1>store.linuxapp.com is running over HTTPS on Rocky Linux 10</h1>" | sudo tee /var/www/store.linuxapp.com/index.html

Now create a dedicated Apache configuration file:

sudo vi /etc/httpd/conf.d/store.linuxapp.com-ssl.conf

Add the following configuration:

<VirtualHost *:443>
    ServerName store.linuxapp.com
    ServerAlias www.store.linuxapp.com
    DocumentRoot /var/www/store.linuxapp.com

    SSLEngine on
    SSLCertificateFile    /etc/ssl/store.linuxapp.com/apache.crt
    SSLCertificateKeyFile /etc/ssl/store.linuxapp.com/apache.key

    SSLProtocol         -all +TLSv1.2 +TLSv1.3
    SSLHonorCipherOrder on
    SSLSessionTickets   off

    <Directory /var/www/store.linuxapp.com>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog  /var/log/httpd/store.linuxapp.com-ssl-error.log
    CustomLog /var/log/httpd/store.linuxapp.com-ssl-access.log combined
</VirtualHost>

Save the file and exit the editor.

At this point, Apache knows where your website files are located and which SSL certificate to use.

If the VirtualHost config here saved you from a late-night Apache rabbit hole, .

Step 6: Add an HTTP to HTTPS Redirect

At this point, Apache is configured to serve HTTPS traffic on port 443. However, users may still access your site using an http:// URL or by simply typing the domain name into their browser.

To ensure all traffic is encrypted, create a second VirtualHost that listens on port 80 and automatically redirects visitors to HTTPS.

Create a new configuration file:

sudo vi /etc/httpd/conf.d/store.linuxapp.com.conf

Add the following configuration:

<VirtualHost *:80>
    ServerName store.linuxapp.com
    ServerAlias www.store.linuxapp.com

    Redirect permanent / https://store.linuxapp.com/
</VirtualHost>

Before reloading Apache, always verify that the configuration is free of syntax errors.

sudo apachectl configtest

If Apache finds a problem, it displays the configuration file and line number where the error occurred.

AH00526: Syntax error on line 12 of /etc/httpd/conf.d/store.linuxapp.com-ssl.conf

Correct any reported errors and run configtest again until you see Syntax OK.

Once the configuration passes validation, reload Apache to apply the changes without interrupting existing connections:

sudo systemctl reload httpd

You can confirm that Apache is listening for both HTTP and HTTPS connections with:

sudo ss -tlnp | grep httpd

Example output:

LISTEN 0      511                *:443             *:*    users:(("httpd",pid=6076,fd=6)
LISTEN 0      511                *:80              *:*    users:(("httpd",pid=6076,fd=4)

If you see entries for both 80 and 443, Apache is ready to serve HTTP requests and redirect them to HTTPS.

Step 7: Test the HTTPS Setup

With Apache reloaded and the SSL VirtualHost active, it’s time to verify that HTTPS is working correctly.

Add a Temporary Hosts Entry (Optional)

If your domain isn’t pointing to the server yet, add a temporary entry to the local machine you’re testing from.

Replace 192.168.1.10 with your server’s actual IP address, which allows your system to resolve the hostname locally without requiring a DNS record:

echo "192.168.1.10  store.linuxapp.com www.store.linuxapp.com" | sudo tee -a /etc/hosts

You can verify the hostname resolves correctly:

getent hosts store.linuxapp.com

Example output:

192.168.1.10  store.linuxapp.com

Test the HTTPS Connection

Since the certificate is self-signed, curl will not trust it by default, so use the -k option to bypass certificate validation during testing.

curl -kv https://store.linuxapp.com 2>&1 | grep -E "SSL|subject|issuer|Connected"

Example output:

* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519MLKEM768 / RSASSA-PSS
*  subject: C=IN; ST=Maharashtra; L=Mumbai; O=LinuxApp; OU=IT; CN=store.linuxapp.com
*  issuer: C=IN; ST=Maharashtra; L=Mumbai; O=LinuxApp; OU=IT; CN=store.linuxapp.com
*  SSL certificate verify result: self-signed certificate (18), continuing anyway.
* Connected to store.linuxapp.com (192.168.122.247) port 443
Server: Apache/2.4.63 (Rocky Linux) OpenSSL/3.5.1

Verify the HTTP Redirect

Next, confirm that all HTTP traffic is being redirected to HTTPS.

curl -I http://store.linuxapp.com

Example output:

HTTP/1.1 301 Moved Permanently
Date: Mon, 01 Jun 2026 06:20:10 GMT
Server: Apache/2.4.63 (Rocky Linux) OpenSSL/3.5.1
Location: https://store.linuxapp.com/
Content-Type: text/html; charset=iso-8859-1

This confirms that visitors using an unencrypted URL are automatically redirected to the secure HTTPS version of the site.

Test in a Web Browser

Open https://store.linuxapp.com in a browser, and you’ll see a certificate warning, which is expected since no recognized CA signed this cert, so click Advanced and proceed to confirm the page loads and the connection is encrypted.

Browser Warning on Self-Signed SSL Certificates
Browser Warning on Self-Signed SSL Certificates
If this setup is running cleanly on your server now, who’s still running plain HTTP on an internal Apache setup.

A Note on Crypto Policies

One of the biggest advantages of Rocky Linux 10 is that you don’t have to spend much time tuning SSL/TLS settings manually. The distribution inherits RHEL 10’s system-wide cryptographic policy framework, which provides secure defaults for TLS-enabled applications such as Apache, Nginx, OpenSSH, and others.

The default policy, appropriately named DEFAULT, already disables outdated protocols and enforces modern cryptographic standards across the operating system.

You can check the currently active policy with:

sudo update-crypto-policies --show

With the DEFAULT policy active, Rocky Linux 10 enforces a minimum of TLS 1.2 and uses strong cipher suites by default. That means you don’t need to manually maintain long SSLCipherSuite strings in your Apache configuration just to achieve a secure baseline.

This is why the VirtualHost configuration in this guide only specifies:

SSLProtocol -all +TLSv1.2 +TLSv1.3

The operating system handles the lower-level cryptographic details, making SSL/TLS configuration simpler and more consistent.

If you’re hardening the server behind this web setup, the SSH Course walks through key-based auth, tunneling, and SSH config hardening on Rocky Linux step by step.
Conclusion

In this guide, you installed Apache with SSL support, opened the required firewall ports, generated a self-signed certificate with proper Subject Alternative Name (SAN) entries, configured a dedicated HTTPS VirtualHost, and redirected all HTTP traffic to HTTPS.

The SAN verification step is particularly important because it’s what ensures modern browsers can validate the certificate correctly. Many older tutorials skip this step and end up producing certificates that browsers reject immediately.

For internal services, development environments, and lab systems, a self-signed certificate provides an easy way to enable encrypted HTTPS connections without relying on an external Certificate Authority.

When you’re ready to publish a site to the internet, you can swap in a trusted certificate from Let’s Encrypt while keeping the same Apache VirtualHost structure you’ve already built.

If this article helped, with someone on your team.
TecMint Weekly Newsletter
Get the Learn Linux 7 Days Crash Course free when you join 34,000+ Linux professionals reading every Thursday.
Check your email for a magic link to get started.
Something went wrong. Please try again.

Similar Posts