Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
On CentOS Stream 9, Apache is packaged as httpd. Install it with DNF, allow web traffic through firewalld, start and enable the service, then place your site in /var/www/html. The commands below also cover SELinux labeling, virtual hosts, HTTPS, custom ports, and the diagnostics that explain most 403, connection, and startup failures.
This procedure targets CentOS Stream 9 and the compatible Red Hat Enterprise Linux 9 family. CentOS Linux 7 and other older releases may have different repositories, package versions, and lifecycle status, so do not assume every command or repository is available there.
What Apache installs on CentOS
Apache HTTP Server is the web daemon; on CentOS its RPM package and service are named httpd. The repository package integrates with systemd, SELinux, the standard log locations, and the operating system’s update mechanism. A normal installation does not require compiling Apache from source.
The package keeps its main configuration under /etc/httpd. Access and error logs are written under /var/log/httpd, and the default document root is /var/www/html. A single default installation can answer requests regardless of the hostname used. Name-based virtual hosts are the appropriate next step when several domains must receive different content.
#1 Best Overall
Check prerequisites before installing
- A running CentOS Stream 9 server with network access to its configured repositories.
- An account with
sudoprivileges, or a root shell. - A planned hostname or IP address for remote testing.
- Permission to change the host firewall and, in a cloud environment, any provider security-group or network ACL rules.
Use the server’s fully qualified name in DNS when you are ready for production. DNS is not required for the local test; 127.0.0.1 is enough to prove that the daemon is serving requests.
Install and start Apache
-
Install the
httpdpackagesudo dnf install httpdConfirm the transaction when DNF asks. DNF resolves the package’s dependencies and places the service unit and default configuration on the host.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy. -
Permit HTTP through firewalld
If
firewalldis enabled, open TCP port 80 and reload the active rules:sudo firewall-cmd --permanent --add-port=80/tcp sudo firewall-cmd --reloadThe service-oriented equivalent is:
sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --reloadUse one of these approaches, not both. The permanent change is stored for future boots; the reload applies it to the running firewall.
-
Enable Apache at boot and start it now
sudo systemctl enable --now httpd sudo systemctl status httpdenable --nowperforms both actions in one command. If you prefer separate operations, runsudo systemctl enable httpdfollowed bysudo systemctl start httpd. A successful status shows the unit as active and running. -
Publish a first page
echo 'Apache is working' | sudo tee /var/www/html/index.html curl http://127.0.0.1/The second command should print
Apache is working. From another machine, openhttp://server_IP_or_host_name/. If you leave the document root empty, a RHEL-family test page may be shown instead of your own index file.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.
Know the important Apache paths
| Path | Purpose | What to change carefully |
|---|---|---|
/etc/httpd |
Main configuration tree, including the server configuration and module settings. | Keep a backup before editing and run a syntax check before restarting. |
/var/www/html |
Default document root for the first site. | Deploy readable web content here; preserve its SELinux labeling. |
/var/log/httpd |
Apache access and error logs. | Inspect the error log when a request returns 403, 500, or another unexpected response. |
/var/run/httpd and systemd state |
Runtime state is managed by the service unit rather than by manually launching a daemon. | Use systemctl for start, stop, reload, and restart operations. |
Make files readable under SELinux
SELinux is normally enforcing on CentOS Stream. Content below /var/www receives the httpd_sys_content_t context by default, which allows Apache to read it. Unix ownership and mode bits still matter: files must be readable by the account under which httpd runs, and every parent directory must be searchable.
Use the default document root
When you publish under /var/www/html, the default policy is usually sufficient. If files were copied from another location, restore the expected contexts:
sudo restorecon -Rv /var/www/html/
A 403 response after a deployment is commonly caused by unreadable files, a directory without execute permission, or a context that no longer matches the path.
Label a document root outside /var/www
For a site stored at /srv/example.com, install the SELinux management utilities if they are absent, assign a persistent file-context rule, and apply it:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
sudo dnf install policycoreutils-python-utils
sudo semanage fcontext -a -t httpd_sys_content_t '/srv/example.com(/.*)?'
sudo restorecon -Rv /srv/example.com/
The semanage rule is persistent, so a relabel or reboot will not silently remove it. Do not solve a web-access problem by disabling SELinux; correct the label and verify the denial in the audit log instead.
Allow Apache to write only when an application needs it
Static content should use the read-only httpd_sys_content_t type. An application that genuinely needs Apache to write uploads or cache data requires a more specific SELinux policy type and carefully limited directory permissions. Granting broad write access to the entire document root increases the impact of a compromised application.
Configure a name-based virtual host
One default instance can serve one site. For multiple domains, create a separate directory and a <VirtualHost> block for each name. Each block should declare its ServerName, DocumentRoot, CustomLog, and ErrorLog.
-
Create and label the site’s directory
sudo mkdir -p /srv/example.com sudo semanage fcontext -a -t httpd_sys_content_t '/srv/example.com(/.*)?' sudo restorecon -Rv /srv/example.com/ echo 'Example site' | sudo tee /srv/example.com/index.html -
Add the virtual-host configuration
Create a configuration file under
/etc/httpd/conf.d/, such as/etc/httpd/conf.d/example.com.conf:The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.<VirtualHost *:80> ServerName example.com ServerAlias www.example.com DocumentRoot /srv/example.com CustomLog /var/log/httpd/example.com_access.log combined ErrorLog /var/log/httpd/example.com_error.log <Directory /srv/example.com> Require all granted AllowOverride None </Directory> </VirtualHost>Point both DNS names at the server before testing from outside. The
<Directory>rule controls Apache’s authorization for that filesystem path; SELinux labeling and Unix permissions remain separate requirements. -
Validate before applying the change
sudo apachectl configtestThe expected result is
Syntax OK. Only then reload or restart:sudo systemctl reload httpdUse a full restart when a module or service-level change requires it. If the reload fails, inspect the service journal and correct the reported file and line rather than repeatedly restarting.
Add HTTPS on port 443
HTTP-only service sends credentials and page contents unencrypted. For TLS, install the Apache SSL module, provide a certificate and private key, configure the certificate directives, open TCP 443, and restart or reload Apache.
Recommended Free Tools
Rank #4
-
Install the SSL module
sudo dnf install mod_ssl -
Configure certificate files
In the TLS virtual-host configuration, set
SSLCertificateFileto the server certificate,SSLCertificateKeyFileto its private key, and, when your certificate chain requires it,SSLCACertificateFileto the issuing CA bundle. Keep the private key owned by root and set mode 600:sudo chown root:root /etc/pki/tls/private/example.com.key sudo chmod 600 /etc/pki/tls/private/example.com.keyUse certificate paths that match the files issued for your hostname; the names above are illustrative locations, not files created automatically by the package.
-
Open the HTTPS service and test
sudo firewall-cmd --permanent --add-service=https sudo firewall-cmd --reload sudo apachectl configtest sudo systemctl restart httpdBrowse to
https://server_IP_or_host_name/and check the certificate name and chain. Port 443 must be open both infirewalldand, if applicable, in the hosting provider’s security group.
Use a nonstandard HTTP port safely
Some internal services use a port other than 80 or 443. Opening that port in the firewall is not enough when SELinux is enforcing: Apache must also be allowed to bind it with the http_port_t type.
For TCP port 3131, assign the SELinux port type and open the same port in firewalld:
sudo semanage port -a -t http_port_t -p tcp 3131
sudo firewall-cmd --permanent --add-port=3131/tcp
sudo firewall-cmd --reload
Configure the matching <VirtualHost *:3131>, run sudo apachectl configtest, and restart or reload Apache. If the port already has an SELinux mapping, semanage port -a will report that it exists; inspect the current mapping and modify it rather than adding a duplicate.
Best Value
Verify the service and diagnose failures
Service will not start
- Check the unit state:
sudo systemctl status httpd. - Read startup messages:
sudo journalctl -u httpd. - Check syntax independently:
sudo apachectl configtestorsudo httpd -t. Fix every reported error until the result isSyntax OK. - After correcting the configuration, run
sudo systemctl restart httpd.
Local curl works but remote browsers cannot connect
A successful request to 127.0.0.1 proves that Apache is running locally, not that the server is reachable from the internet. Check DNS resolution, routing, the host’s firewalld rules, and any cloud security-group or network ACL rule. Confirm that the client is using the same port Apache is listening on.
The browser reports HTTP 403 Forbidden
- Check Unix ownership and read permissions on the file and every parent directory.
- For content outside
/var/www, verify the persistentsemanage fcontextrule and runrestorecon -Rv. - Review
/var/log/httpdand the journal for an SELinux denial or an authorization rule that rejects the request. - For a virtual host, confirm that its
DocumentRootpoints to the directory you actually populated.
A custom port is refused or Apache cannot bind it
Confirm that Apache’s virtual host uses the intended port, that firewalld permits it, and that SELinux maps it to http_port_t. A firewall rule without the SELinux port label can still produce a bind denial; the reverse is also true.
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 & 11The wrong site appears
Check the request’s hostname, DNS record, ServerName, and ServerAlias. Name-based virtual hosts select a site from the HTTP Host header. An unmatched name can fall through to the first/default virtual host, so verify each domain with a request that uses the intended hostname.
Maintain Apache after installation
Keep the RPM installation current through the normal CentOS Stream update process. Before changing configuration, copy the relevant file and use apachectl configtest. Prefer a reload for configuration-only changes so existing connections are disrupted as little as possible; use a restart when a module or service change requires it.
Monitor disk usage under /var/log/httpd, protect private keys, and restrict write permissions to directories that explicitly need them. When troubleshooting, preserve the exact error-log and journal message: it usually identifies whether the failure is syntax, permissions, SELinux, DNS, or network policy.
Choose the deployment pattern that fits
| Choice | Best fit | Important trade-off |
|---|---|---|
Repository RPM (dnf install httpd) |
Most CentOS Stream 9 servers. | Uses the distribution’s tested layout, service unit, updates, and SELinux integration. |
| Source build | A narrowly controlled environment that needs a feature or build option unavailable in the repository. | Requires you to manage compilation, upgrades, service integration, paths, and security policy yourself. |
| One shared document root | A single site or simple internal page. | All hostnames receive the same content unless you add virtual-host rules. |
| Name-based virtual hosts | Several domains on one Apache instance. | Each site needs its own configuration, logs, directory permissions, and SELinux labeling when outside /var/www. |
| HTTP on port 80 | Initial validation or deliberately private, non-sensitive traffic. | Traffic is unencrypted and should not carry credentials or confidential data. |
| HTTPS on port 443 | Public websites, authentication, and any sensitive content. | Requires correctly managed certificates, private-key protection, firewall access, and TLS configuration. |
Default /var/www paths |
Fastest setup with the default SELinux context. | Less separation between sites unless you create dedicated directories and virtual hosts. |
Custom paths such as /srv/example.com |
Organized multi-site or application layouts. | Requires persistent SELinux file-context rules and an explicit Apache <Directory> policy. |
What a successful installation looks like
The service is enabled and active, apachectl configtest returns Syntax OK, a local curl request returns your index page, and a remote request reaches the server through the permitted port. If any one of those checks fails, troubleshoot that layer—Apache configuration, filesystem and SELinux policy, host firewall, or external networking—before changing the others.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesQuick 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.

