How to Install and Configure Apache (httpd) as a Web Server on Fedora

Install and start Apache on Fedora using dnf and systemctl to serve web pages from /var/www/html.

You installed httpd, but the browser shows Connection refused

You ran dnf install httpd, enabled the service, and pointed your browser to http://localhost. The browser displays "Connection refused" or hangs until it times out. You checked systemctl status httpd and it reports active (running). The service is up, the process exists, but no data reaches the port. This is the standard first encounter with Apache on Fedora. The package manager placed the binaries, systemd launched the daemon, but the operating system's security layers are intercepting the traffic before it can be processed.

What is blocking the request

Apache listens on port 80 for HTTP traffic. Fedora ships with a host-based firewall enabled by default that blocks incoming connections to almost every port except SSH and a few essential services. Even if the firewall allows the packet through, SELinux enforces mandatory access controls. SELinux checks whether the httpd process has permission to read the specific files it is trying to serve and whether it is allowed to bind to the network port.

Think of Apache as a receptionist sitting at a desk. The firewall is the security guard at the building entrance. SELinux is the badge scanner that checks if the receptionist is allowed to open specific drawers. If the guard stops the visitor, the receptionist never sees them. If the guard lets the visitor in but the badge scanner denies access to the drawer, the receptionist cannot hand over the file. The service can be active and healthy while still failing to serve content because the network path is blocked or the file labels are incorrect.

Install and enable the service

Here's how to install the package and ensure the service starts on boot and runs right now. Fedora uses the package name httpd for the Apache HTTP Server. The systemctl command manages the service lifecycle.

sudo dnf install httpd -y
# httpd is the Fedora package name for the Apache HTTP Server
# -y skips the confirmation prompt to streamline the installation

sudo systemctl enable --now httpd
# enable adds the unit to the default target so it starts automatically on boot
# --now starts the service immediately without requiring a separate start command

Enable before you start. If the system reboots during a crash or maintenance window, the service comes back up automatically without manual intervention.

Open the firewall

The firewall must allow traffic to port 80. Fedora distinguishes between runtime rules that apply immediately but vanish on reboot, and persistent rules that are written to disk and survive reboots. You must apply changes to the persistent configuration and then reload the runtime state. Skipping the reload leaves the firewall in an inconsistent state where the disk config says "allow" but the running kernel says "block".

sudo firewall-cmd --permanent --add-service=http
# --permanent writes the rule to the configuration file on disk
# --add-service=http opens port 80 using the predefined service definition

sudo firewall-cmd --reload
# reload applies the persistent configuration to the running firewall engine
# skipping this step leaves the runtime state unchanged and the port blocked

Reload the firewall after every rule change. The runtime config and persistent config diverge instantly if you forget, and debugging a mismatch between --permanent and runtime output wastes time.

Handle SELinux contexts

SELinux prevents Apache from reading files unless they carry the correct security label. The default document root /var/www/html is labeled correctly out of the box. Creating new directories, moving files from your home directory, or downloading content via wget often strips or mislabels the SELinux context. If the label is wrong, httpd gets a Permission denied error even if standard Linux permissions (chmod) are open.

Here's how to fix the context for a custom directory. The semanage tool manages file contexts, and restorecon applies them.

sudo mkdir -p /var/www/html/myapp
# create a directory for your application files

sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/html/myapp(/.*)?"
# semanage defines the expected SELinux type for the path pattern
# httpd_sys_content_t allows httpd to read files but not write to them

sudo restorecon -Rv /var/www/html/myapp
# restorecon applies the defined context to existing files recursively
# -v prints verbose output so you can see which files changed their label

Check the context before you blame permissions. Run ls -Z /var/www/html/myapp to see the label. If the label shows user_home_t or default_t, chmod 777 will not fix the issue. SELinux denies access based on the label, not the mode bits.

Verify the configuration

Verify the service is listening and serving the default page. Use curl to test locally without a browser, and check the logs for warnings. Fedora splits Apache configuration into a main file and a drop-in directory. The main config is /etc/httpd/conf/httpd.conf. Additional files in /etc/httpd/conf.d/ are loaded automatically. Never edit files in /usr/lib/httpd/. Those files ship with the package and get overwritten on updates. User modifications belong in /etc/.

curl -I http://localhost
# -I fetches only the HTTP headers
# a 200 OK response confirms Apache is processing requests successfully

sudo httpd -t
# -t runs a syntax check without starting or restarting the server
# always run this before restarting to catch typos in configuration files

sudo journalctl -xeu httpd
# -x adds explanatory text to journal entries for easier reading
# -e jumps to the end of the log to show recent events
# -u filters the output for the httpd unit specifically

Test syntax before you restart. A typo in a configuration file kills the service and leaves you debugging a black box. The syntax check fails fast and points to the exact line number.

Common errors and fixes

Errors fall into three categories: network blocks, configuration syntax, and access denials. Identifying the category saves hours of guessing.

If curl returns Connection refused, the firewall is blocking the port or Apache is not listening. Check the listening sockets with ss -tlnp | grep :80. If the output is empty, Apache failed to bind. Check journalctl -u httpd for binding errors. If the output shows LISTEN, the firewall is dropping the packet. Verify the firewall rule with sudo firewall-cmd --list-all.

If you see AH00558: httpd: Could not reliably determine the server's fully qualified domain name, this is a warning, not a fatal error. Apache still starts and serves content. The warning appears because the ServerName directive is missing. Add ServerName localhost to /etc/httpd/conf/httpd.conf to silence it.

If you get 403 Forbidden, SELinux is likely denying access to the files. Check the SELinux troubleshoot logs. Fedora provides a helper service that translates raw AVC denials into human-readable messages.

sudo journalctl -t setroubleshoot
# setroubleshoot logs contain one-line summaries of SELinux denials
# the output suggests commands to fix the policy or restore context

Silence warnings by setting ServerName. A clean log makes real errors stand out immediately.

Choose the right web server

Fedora supports multiple web servers. The choice depends on the workload, not personal preference. Each tool has strengths that align with specific use cases.

Use httpd when you need a mature, widely documented server with extensive module support for legacy applications and complex .htaccess configurations. Use nginx when you are serving static assets or acting as a reverse proxy for high-concurrency workloads where event-driven architecture reduces memory overhead. Use caddy when you want automatic HTTPS certificates and minimal configuration for simple sites. Use podman with a container image when you want to isolate dependencies and avoid polluting the host system packages.

Pick the tool that matches the workload. Do not install httpd just because it is the default. The default exists for compatibility, not because it is the best choice for every scenario.

Where to go next