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.
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
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.
Recommended Free Tools
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
sudoprivileges 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
firewalldis 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:
#1 Best Overall
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.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsOpen 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:
Rank #2
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.
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.
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:
- Add the port to the active
firewalldpolicy and reload the firewall. - Tell SELinux that the port is permitted for HTTP by assigning the
http_port_ttype.
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.
Rank #4
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.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →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.
Best Value
Verification checklist
- Package:
dnf install httpdcompleted without a repository or dependency error. - Service:
systemctl status httpdreports an active service. - Boot behavior: the service is enabled, either with
systemctl enable --now httpdor separate enable and start commands. - Syntax:
apachectl configtestorhttpd -treturnsSyntax 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.
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.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11For 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.
Quick Recap
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.




