October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
VGSources
Blog

How to Install the Apache Web Server on CentOS Stream 9

Install and verify Apache on CentOS Stream 9, then configure firewalld, SELinux, virtual hosts, custom ports and HTTPS without the usual 403 or connection errors.
Length9 min Posted Quest giverVGSources Team
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

On CentOS Stream 9, install Apache from the distribution repository as the httpd package, allow inbound TCP port 80 if firewalld is active, then enable and start the service with systemd. A working first page can be served from /var/www/html and checked locally with curl. The procedure below follows the CentOS Stream 9 and compatible RHEL 9 layout; older CentOS Linux releases can have different repository availability and lifecycle conditions.

What Apache is called on CentOS

CentOS packages the Apache HTTP Server under the name httpd. Installing that RPM supplies the web-server daemon, its systemd service definition, the default configuration tree and logging locations. The main configuration directory is /etc/httpd; Apache’s standard logs are written under /var/log/httpd. The default web content directory is /var/www/html.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A minimal installation serves one document root for every request. That is sufficient for a single site, a private status page or a local development endpoint. If one server must answer for several host names, use name-based virtual hosts so each domain has its own ServerName, document root and logs.

Before you install

  • Use CentOS Stream 9 or a compatible RHEL 9 family system for the commands in this guide.
  • Have an account with sudo privileges and network access to the configured package repositories.
  • Know the server’s reachable IP address or host name if other computers will connect.
  • Check whether firewalld is enabled. Its rules determine whether remote HTTP requests can reach Apache even when the service itself is healthy.
  • Keep SELinux enabled unless you have a specific, documented reason to change policy. Correct file labels are safer than disabling enforcement.

Install the httpd package

Install Apache with the repository package manager:

sudo dnf install httpd

dnf resolves and installs the package and its required dependencies. If the command reports that no package is available, verify that the system is actually running a supported CentOS Stream 9 repository configuration rather than an older CentOS Linux release whose repositories may no longer be available in the same form.

Installation places configuration under /etc/httpd, logs under /var/log/httpd and the default document root at /var/www/html. Installing the RPM does not by itself make Apache start at boot or make port 80 reachable through the firewall; those are separate steps.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Open HTTP in firewalld

If firewalld is enabled, permit TCP port 80 and reload the active rules:

sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --reload

The service-oriented equivalent is:

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

Use one of these approaches, not both. The permanent change survives a firewall restart; --reload applies it without stopping the firewall daemon. A successful local curl test does not prove that a remote browser can connect: remote access also depends on this host firewall, upstream routing and any cloud security-group rules.

Enable and start Apache

Enable the service for future boots and start it immediately:

sudo systemctl enable --now httpd
sudo systemctl status httpd

The combined command creates the boot-time enablement and starts the daemon in one operation. CentOS documentation also presents the equivalent two-command form:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo systemctl enable httpd
sudo systemctl start httpd

systemctl status httpd should show an active service. If it is inactive or failed, inspect the startup journal before changing configuration:

sudo journalctl -u httpd

Publish and verify a first page

Create a small test page in the default document root:

echo 'Apache is working' | sudo tee /var/www/html/index.html

Test the request on the server itself:

curl http://127.0.0.1/

The response should contain Apache is working. From another machine, open http://server_IP_or_host_name/, replacing that text with the server’s actual address. If /var/www/html is empty, RHEL documentation says the server returns the Red Hat Enterprise Linux test page instead. That page still demonstrates that Apache is answering; replacing it with your own index.html confirms that the intended content directory is being used.

Understand the important files and paths

Path or setting Role Why you use it
/etc/httpd Apache configuration tree Stores the server and module configuration that Apache reads at startup or reload.
/var/www/html Default document root Place the initial index.html and other public files here.
/var/log/httpd Apache logs Inspect access and error information when a request or startup fails.
httpd Systemd service and RPM name Use it with systemctl, journalctl and dnf.
DocumentRoot Virtual-host content setting Defines which directory supplies files for a host name.
ServerName Virtual-host identity Associates a request host name with the appropriate name-based virtual host.

File permissions and SELinux contexts

Apache must be able to read every directory component and file beneath its document root. RHEL documentation states that content under /var/www receives the SELinux type httpd_sys_content_t by default. Keep ordinary website files in that tree when possible, and make sure their Unix permissions allow the account running httpd to read them.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A Unix permission that appears readable can still be denied by SELinux when the label is wrong. An HTTP 403 response, an error-log denial or an audit message after moving content is therefore not automatically a firewall problem.

Use a document root outside /var/www

For a custom root such as /srv/example.com, assign the web-content type persistently and then restore the label:

sudo semanage fcontext -a -t httpd_sys_content_t '/srv/example.com(/.*)?'
sudo restorecon -Rv /srv/example.com/

The regular-expression form applies the rule to the directory and everything below it. The policycoreutils-python-utils package supplies semanage and related utilities on systems where they are not already installed. Install that package if the semanage command is missing, then run the labeling commands again.

After labeling, verify that the Apache process can read the files and repeat the local curl request. Do not “fix” a labeling denial by recursively making all files world-writable; that weakens the host without addressing the policy mismatch.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use a nonstandard listening port

Port 80 is the conventional HTTP port, but an application may require another TCP port. Two independent controls must allow that port:

  1. Add the port to the active firewalld policy and reload the firewall.
  2. Tell SELinux that the port is permitted for HTTP by assigning the http_port_t type.

For example, CentOS guidance uses port 3131 with:

sudo semanage port -a -t http_port_t -p tcp 3131

The SELinux type already covers standard HTTP ports such as 80 and 443. The explicit assignment is needed for an additional port such as 3131. If a nonstandard-port request fails, check both the firewall rule and the port label; changing only one leaves the other control blocking the connection.

Configure several domains with name-based virtual hosts

A single-instance, single-root setup sends all host names to the same content. For multiple domains, create a separate name-based <VirtualHost> block for each site. Each block should define its own ServerName, DocumentRoot, CustomLog and ErrorLog.

Prepare each site’s content

Create a directory for every site, place its files there and ensure that Apache can traverse and read the directory. If the root is outside /var/www, apply a persistent httpd_sys_content_t rule with semanage fcontext and run restorecon as shown above. Keeping each site’s logs separate makes it easier to distinguish a missing file or permission error from another domain’s traffic.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Define the host mappings

In the Apache configuration, give each block a unique ServerName and matching document root. A request whose host header matches that name is served from the corresponding block. DNS must point each domain to the server’s address; Apache cannot compensate for a name that resolves elsewhere.

Before applying a virtual-host change, run a syntax check:

sudo apachectl configtest

The equivalent command is sudo httpd -t. The expected result is Syntax OK. Only after a successful check should you restart or reload the service.

Add HTTPS on port 443

For TLS, install and configure Apache’s SSL module, commonly provided by mod_ssl. The HTTPS virtual host must reference the certificate and private key with SSLCertificateFile and SSLCertificateKeyFile. When an applicable certificate chain is supplied separately, configure SSLCACertificateFile as well.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Protect the private key so only root can read it; the documented minimum mode is 600. Permit TCP port 443 through firewalld, run apachectl configtest, and restart httpd after the TLS configuration is valid. A certificate file that is readable by the daemon but a private key that is broadly readable creates an avoidable security exposure.

HTTPS introduces a second listener and a second firewall requirement; opening port 80 does not open 443. If you retain HTTP, decide whether it should serve content independently or redirect users to HTTPS in the virtual-host configuration.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Verification checklist

  • Package: dnf install httpd completed without a repository or dependency error.
  • Service: systemctl status httpd reports an active service.
  • Boot behavior: the service is enabled, either with systemctl enable --now httpd or separate enable and start commands.
  • Syntax: apachectl configtest or httpd -t returns Syntax OK.
  • Local request: curl http://127.0.0.1/ returns the expected page.
  • Remote HTTP: the host firewall and any cloud security-group policy allow TCP 80.
  • Content access: the document root and files are readable by the account running Apache and carry the correct SELinux type.
  • HTTPS: TCP 443 is allowed, certificate directives point to the right files and the private key is restricted to root.

Troubleshoot by symptom

The service will not start

Run sudo apachectl configtest. A result other than Syntax OK identifies a configuration error that must be corrected before restart. Then inspect sudo journalctl -u httpd for bind failures, missing files or module errors. If the service previously worked, compare the most recent configuration change with the journal timestamp.

The browser cannot connect at all

First test locally with curl http://127.0.0.1/. If that fails, the issue is inside Apache, its configuration or the local host. If it succeeds but a remote client times out, investigate DNS, routing, the host’s firewalld rules and any cloud security-group rules. A timeout is not normally fixed by changing website file permissions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The server returns HTTP 403

Check that the requested file and every parent directory are readable and traversable by the Apache runtime account. For content outside /var/www, verify the persistent SELinux mapping and run restorecon. Review the Apache error log and SELinux audit messages for a denial. A 403 commonly indicates readability or an incorrect SELinux context rather than a blocked network port.

A custom port is refused or denied

Confirm that Apache is configured to listen on the intended port, that firewalld allows it, and that SELinux labels it http_port_t. The example command for port 3131 is sudo semanage port -a -t http_port_t -p tcp 3131. Test locally on that port before testing through external routing.

The wrong site’s page appears

Check each virtual host’s ServerName and DocumentRoot, then verify that DNS points the requested host name to this server. Run the syntax check after editing. A name-based virtual host cannot select a site when the request arrives with a different host name or reaches another IP address.

Choosing an installation and layout

Decision Option 1 Option 2 Practical consequence
Operating system CentOS Stream 9 Another RHEL 9 family release The commands and httpd layout are aligned with the Stream 9/RHEL 9 family; older CentOS Linux releases may differ in repository availability.
Apache delivery Repository RPM Source build The RPM integrates with dnf, systemd, standard paths and the distribution’s SELinux policy. A source build requires you to manage its integration and paths yourself.
Site layout One shared document root Name-based virtual hosts A shared root is simplest for one site; virtual hosts isolate domains, content paths and logs on one Apache instance.
Transport HTTP on 80 TLS on 443 HTTP needs port 80. HTTPS additionally needs mod_ssl, certificate directives, a protected private key and a firewall rule for 443.
Content path /var/www Custom path such as /srv/example.com /var/www receives the expected SELinux content type by default; a custom path needs persistent semanage fcontext labeling and restorecon.

Operational habits after installation

Keep configuration changes small and run apachectl configtest before every restart. When a change affects only content, test the page without restarting the daemon. Use the separate access and error logs under /var/log/httpd to distinguish client requests from server-side failures, and retain the systemd journal when diagnosing startup problems.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For a multi-domain server, document each ServerName, document root, log path, listening port and SELinux labeling rule. That record prevents a later move from /var/www to a custom path from silently producing 403 responses. Treat firewall rules, SELinux port labels and Apache’s own listen settings as three separate layers whenever you introduce a new port.

Result

After the package is installed, port 80 is allowed where necessary, httpd is enabled and active, and the test page responds locally and remotely, Apache is serving correctly on CentOS Stream 9. Virtual hosts, custom roots, alternate ports and HTTPS can then be added one layer at a time, with syntax checks, firewall rules and SELinux labels verified for each change.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More quests from Patch Notes

  1. How to Set Up a RedM (RDR2) Server in 2026: License Key, txAdmin and server.cfg, Step by StepBlog11min
  2. Best RedM (RDR2) Server Hosting in 2026: Comparing Four Hosts on Slots, Memory and PriceBlog10min
  3. How to Host a Mindustry Server in 2026: server-release.jar, Port 6567 and the Commands That MatterBlog7min
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.