{"id":680,"date":"2026-02-10T15:32:20","date_gmt":"2026-02-10T23:32:20","guid":{"rendered":"https:\/\/blog.iabsolute.com\/?p=680"},"modified":"2026-02-10T15:32:20","modified_gmt":"2026-02-10T23:32:20","slug":"how-to-install-apache-on-centos","status":"publish","type":"post","link":"https:\/\/blog.iabsolute.com\/?p=680","title":{"rendered":"How to Install Apache on CentOS"},"content":{"rendered":"\n<p>The Apache web server is the most widely used platform for deploying HTTP-based services. Its popularity is due to its support for dynamically loadable modules, compatibility with various file formats, and integration with other software tools.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"prerequisites\">Prerequisites<a><\/a><\/h2>\n\n\n\n<p>To install the Apache HTTP server following this guide, you will need:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A local computer or a cloud server with CentOS 9 installed<\/li>\n\n\n\n<li>A user with&nbsp;<code>sudo<\/code>&nbsp;privileges or&nbsp;<code>root<\/code><\/li>\n\n\n\n<li>Enabled&nbsp;<code>firewalld<\/code><\/li>\n<\/ul>\n\n\n\n<p>If you\u2019re looking for a reliable, high-performance, and budget-friendly solution for your workflows, Hostman has you covered with&nbsp;<a href=\"https:\/\/hostman.com\/products\/linux-vps\/\">Linux VPS Hosting<\/a>&nbsp;options, including&nbsp;<a href=\"https:\/\/hostman.com\/products\/vps-debian\/\">Debian VPS<\/a>,&nbsp;<a href=\"https:\/\/hostman.com\/products\/vps-ubuntu\/\">Ubuntu VPS<\/a>, and&nbsp;<a href=\"https:\/\/hostman.com\/products\/vps-centos\/\">VPS CentOS<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-1--install-apache\">Step 1: Install Apache<a><\/a><\/h2>\n\n\n\n<p>The Apache package is available in the official CentOS repository, so you can install it using&nbsp;<code>dnf<\/code>.<\/p>\n\n\n\n<p>First, update the package list:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo dnf update -y<\/code><\/pre>\n\n\n\n<p>Run the following command to install Apache:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo dnf install httpd -y<\/code><\/pre>\n\n\n\n<p>The package manager will install the Apache web server and all necessary dependencies on CentOS.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-2--configuring-the-firewall\">Step 2: Configuring the Firewall<a><\/a><\/h2>\n\n\n\n<p>To operate the web server, you\u2019ll need to configure the firewall to allow HTTP and HTTPS traffic:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo firewall-cmd --permanent --add-service=http\nsudo firewall-cmd --permanent --add-service=https<\/code><\/pre>\n\n\n\n<p>After running these commands, restart the firewall to apply the new rules:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo firewall-cmd --reload<\/code><\/pre>\n\n\n\n<p>The Apache installation is now complete, and you can start the web server and check its functionality.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-3--checking-the-http-server\">Step 3: Checking the HTTP Server<a><\/a><\/h2>\n\n\n\n<p>Once installed, Apache isn\u2019t running yet, so you need to enable and start it using these commands:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl enable httpd\nsudo systemctl start httpd<\/code><\/pre>\n\n\n\n<p>To verify if the Apache service has started, use this command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl status httpd<\/code><\/pre>\n\n\n\n<p>If the web server is running correctly, you should see a message showing the status as&nbsp;<code>active (running)<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\u25cf httpd.service - The Apache HTTP Server\n &nbsp;&nbsp;&nbsp;&nbsp;Loaded: loaded (\/usr\/lib\/systemd\/system\/httpd.service; enabled; preset: disabled)\n &nbsp;&nbsp;&nbsp;&nbsp;Active: active (running) since Thu 2024-11-07 07:34:27 GMT; 6s ago<\/code><\/pre>\n\n\n\n<p>Another way to check is to open the server\u2019s IP address in a browser:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>http:&#47;&#47;your_server_ip<\/code><\/pre>\n\n\n\n<p>You can find your server\u2019s IP on the server&#8217;s Dashboard or in an email received after setting up the server.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-4--managing-the-apache-service\">Step 4: Managing the Apache Service<a><\/a><\/h2>\n\n\n\n<p>Now, you can try some systemctl commands for interacting with the Apache service.&nbsp;<\/p>\n\n\n\n<p>For example, to stop the HTTP server, use:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl stop httpd<\/code><\/pre>\n\n\n\n<p>To start it again, use:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl start httpd<\/code><\/pre>\n\n\n\n<p>For a complete restart, such as when applying configuration changes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl restart httpd<\/code><\/pre>\n\n\n\n<p>To reload Apache without interrupting active connections, use:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl reload httpd<\/code><\/pre>\n\n\n\n<p>We enabled Apache to start automatically when the server boots. If you prefer to disable this option, run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl disable httpd<\/code><\/pre>\n\n\n\n<p>These commands allow you to manage the Apache process easily.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-5--setting-up-virtual-hosts\">Step 5: Setting Up Virtual Hosts<a><\/a><\/h2>\n\n\n\n<p>The default Apache HTTP server configuration allows for&nbsp;<a href=\"https:\/\/hostman.com\/products\/wordpress-hosting\/\">hosting only one site<\/a>. However, you can set up virtual hosts to host multiple sites with separate resources.<\/p>\n\n\n\n<p>Virtual hosts in Apache work similarly to those in Nginx. They allow you to separate configurations and host multiple domains on a single virtual or physical server. In this guide, we\u2019ll use a placeholder site called example.com. When configuring, replace it with your actual domain.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create the&nbsp;<code>html<\/code>&nbsp;directory for example.com:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mkdir -p \/var\/www\/example.com\/html<\/code><\/pre>\n\n\n\n<ol class=\"wp-block-list\" start=\"2\">\n<li>Create a directory for log files:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mkdir -p \/var\/www\/example.com\/log<\/code><\/pre>\n\n\n\n<ol class=\"wp-block-list\" start=\"3\">\n<li>Set permissions for the&nbsp;<code>html<\/code>&nbsp;directory. Assign ownership to the&nbsp;<code>$USER<\/code>&nbsp;environment variable.<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo chown -R $USER:$USER \/var\/www\/example.com\/html<\/code><\/pre>\n\n\n\n<ol class=\"wp-block-list\" start=\"4\">\n<li>Verify standard permissions for the root directory:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo chmod -R 755 \/var\/www<\/code><\/pre>\n\n\n\n<ol class=\"wp-block-list\" start=\"5\">\n<li>Create an&nbsp;<code>index.html<\/code>&nbsp;file.&nbsp;You can use any code editor to create this file. For example, with&nbsp;<code>vi<\/code>:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo vi \/var\/www\/example.com\/html\/index.html<\/code><\/pre>\n\n\n\n<p>Add simple content to the file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;html&gt;\n  &lt;head&gt;\n    &lt;title&gt;Welcome to Example.com!&lt;\/title&gt;\n  &lt;\/head&gt;\n  &lt;body&gt;\n    &lt;h1&gt;Success! The example.com virtual host is working!&lt;\/h1&gt;\n  &lt;\/body&gt;\n&lt;\/html&gt;\n<\/code><\/pre>\n\n\n\n<p>After saving&nbsp;<code>index.html<\/code>, you\u2019re nearly ready to set up the configuration files for each domain. These files will tell Apache how to handle requests for each virtual host.<\/p>\n\n\n\n<ol class=\"wp-block-list\" start=\"6\">\n<li>Create directories for virtual host configurations.&nbsp;The configuration files for individual domains are stored in a&nbsp;<code>sites-available<\/code>&nbsp;directory, while the&nbsp;<code>sites-enabled<\/code>&nbsp;directory will contain symbolic links to sites that are ready to receive traffic:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mkdir \/etc\/httpd\/sites-available \/etc\/httpd\/sites-enabled<\/code><\/pre>\n\n\n\n<p>Now, you need to instruct the HTTP server to find virtual hosts in the&nbsp;<code>sites-enabled<\/code>&nbsp;directory. To do this, modify the main Apache configuration file by running the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo vi \/etc\/httpd\/conf\/httpd.conf<\/code><\/pre>\n\n\n\n<p>Then, move the cursor to the very end of the file and add the following lines:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Supplemental configuration\n#\n# Load config files in the \"\/etc\/httpd\/conf.d\" directory, if any.\nIncludeOptional conf.d\/*.conf\nIncludeOptional sites-enabled\/*.conf\n<\/code><\/pre>\n\n\n\n<p>Now, it\u2019s time to create the virtual host configuration file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo vi \/etc\/httpd\/sites-available\/example.com.conf<\/code><\/pre>\n\n\n\n<p>In this file, add the following configuration:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;VirtualHost *:80&gt;\n    ServerName www.example.com\n    ServerAlias example.com\n    DocumentRoot \/var\/www\/example.com\/html\n    ErrorLog \/var\/www\/example.com\/log\/error.log\n    CustomLog \/var\/www\/example.com\/log\/requests.log combined\n&lt;\/VirtualHost&gt;\n<\/code><\/pre>\n\n\n\n<p>Make sure to replace example.com with your actual domain name. This configuration tells the web server where to find the site\u2019s root directory and where to store the error and access logs.<\/p>\n\n\n\n<p>After saving and closing the file, you need to activate the virtual host by creating a symbolic link for the domain in the&nbsp;<code>sites-enabled<\/code>&nbsp;directory:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ln -s \/etc\/httpd\/sites-available\/example.com.conf \/etc\/httpd\/sites-enabled\/example.com.conf<\/code><\/pre>\n\n\n\n<p>At this point, the configuration is complete, and the host is ready to function. However, before restarting the web server, it\u2019s a good idea to check if the SELinux module is correctly handling requests.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-6--configuring-permissions-in-selinux\">Step 6: Configuring Permissions in SELinux<a><\/a><\/h2>\n\n\n\n<p>The SELinux (Security-Enhanced Linux) module enhances the operating system&#8217;s security. CentOS comes with a preconfigured SELinux package that works with Apache. However, since we&#8217;ve made changes, starting the web server services might result in an error. To resolve this, you need to adjust SELinux policies for Apache. There are two ways to adjust these policies: a universal approach and a folder-specific approach.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"option-1--universal-approach\">Option 1: Universal Approach<a><\/a><\/h3>\n\n\n\n<p>This method allows the SELinux security module to use any Apache processes via the httpd_unified boolean variable. It\u2019s convenient but doesn\u2019t allow separate policies for individual directories and files. To enable the universal policy, run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo setsebool -P httpd_unified 1<\/code><\/pre>\n\n\n\n<p>The setsebool command is used to modify boolean values, and the -P flag ensures that the change is persistent across reboots. In this case, the httpd_unified boolean is activated with the value 1.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"option-2--adjusting-selinux-policies-for-specific-directories\">Option 2: Adjusting SELinux Policies for Specific Directories<a><\/a><\/h3>\n\n\n\n<p>This approach requires more steps but allows for more granular control over permissions for each directory or file. You\u2019ll need to specify the context type for each new folder manually. For example, to check the parameters of the&nbsp;<code>\/var\/www\/example.com\/log<\/code>&nbsp;directory, run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ls -dlZ \/var\/www\/example.com\/log\/<\/code><\/pre>\n\n\n\n<p>You\u2019ll see something like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>drwxr-xr-x. 2 root root unconfined_u:object_r:httpd_sys_content_t:s0 6 Nov 07 09:01 \/var\/www\/example.com\/log\/<\/code><\/pre>\n\n\n\n<p>You can see that the context used is&nbsp;<code>httpd_sys_content_t<\/code>, meaning Apache can only read files placed in this folder. To change the context to&nbsp;<code>httpd_log_t<\/code>&nbsp;so that the web server can write to log files, run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo semanage fcontext -a -t httpd_log_t \"\/var\/www\/example.com\/log(\/.*)?\"<\/code><\/pre>\n\n\n\n<p>This command will set the correct context for the log directory and its contents, allowing Apache to write log entries.<\/p>\n\n\n\n<p>Apply the changes using the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo restorecon -R -v \/var\/www\/example.com\/log<\/code><\/pre>\n\n\n\n<p>The&nbsp;<code>-R<\/code>&nbsp;flag allows the command to run recursively, updating existing files, and the&nbsp;<code>-v<\/code>&nbsp;flag will display the changes being made. You should see an output like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Relabeled \/var\/www\/example.com\/log from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:httpd_log_t:s0<\/code><\/pre>\n\n\n\n<p>If you want to verify that the context type has been updated, check the current status again:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ls -dlZ \/var\/www\/example.com\/log\/<\/code><\/pre>\n\n\n\n<p>The output should look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>drwxr-xr-x. 2 root root unconfined_u:object_r:httpd_log_t:s0 6 Nov 07 09:01 \/var\/www\/example.com\/log\/<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-7--testing-the-virtual-host\">Step 7: Testing the Virtual Host<a><\/a><\/h2>\n\n\n\n<p>After adjusting the SELinux permissions, the Apache server should now be able to write data to the&nbsp;<code>\/var\/www\/example.com\/log<\/code>&nbsp;directory. Let\u2019s restart the Apache service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl restart httpd<\/code><\/pre>\n\n\n\n<p>Next, list the contents of the&nbsp;<code>\/var\/www\/example.com\/log<\/code>&nbsp;directory to verify that the system has created the log files:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ls -lZ \/var\/www\/example.com\/log<\/code><\/pre>\n\n\n\n<p>You should see output similar to this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>-rw-r--r--. 1 root root system_u:object_r:httpd_log_t:s0 0 Nov 07 09:06 error.log\n-rw-r--r--. 1 root root system_u:object_r:httpd_log_t:s0 0 Nov 07 09:06 requests.log<\/code><\/pre>\n\n\n\n<p>The first line confirms the existence of the&nbsp;<code>error.log<\/code>&nbsp;file, and the second confirms the presence of the&nbsp;<code>requests.log<\/code>&nbsp;file.<\/p>\n\n\n\n<p>Now, you can check the functionality of the domain through a browser. You should see a message like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Success! The example.com virtual host is working<\/code><\/pre>\n\n\n\n<p>This confirms that the virtual host has been successfully set up and is serving content. Repeat steps 5 and 6 for each new site, replacing the domain with the appropriate one.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusion\">Conclusion<a><\/a><\/h2>\n\n\n\n<p>In this tutorial, we&#8217;ve walked through installing and configuring Apache on CentOS 9, including setting up virtual hosts for multiple domains. We covered installation with dnf, configuring firewall rules, enabling Apache to start on boot, and managing its service using systemctl. We also explored SELinux configuration for proper permissions, ensuring Apache can read and write log files. With these steps, you&#8217;ll have a&nbsp;<a href=\"https:\/\/hostman.com\/products\/vps-server-hosting\/\">functional web server<\/a>&nbsp;ready to host sites and deploy content<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Apache web server is the most widely used platform for deploying HTTP-based services. Its popularity is due to its support for dynamically loadable modules, compatibility with various file formats, and integration with other software tools. Prerequisites To install the &hellip; <a href=\"https:\/\/blog.iabsolute.com\/?p=680\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[25,10,38],"tags":[],"class_list":["post-680","post","type-post","status-publish","format-standard","hentry","category-apache","category-centos","category-iis"],"_links":{"self":[{"href":"https:\/\/blog.iabsolute.com\/index.php?rest_route=\/wp\/v2\/posts\/680","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.iabsolute.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.iabsolute.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.iabsolute.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.iabsolute.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=680"}],"version-history":[{"count":1,"href":"https:\/\/blog.iabsolute.com\/index.php?rest_route=\/wp\/v2\/posts\/680\/revisions"}],"predecessor-version":[{"id":681,"href":"https:\/\/blog.iabsolute.com\/index.php?rest_route=\/wp\/v2\/posts\/680\/revisions\/681"}],"wp:attachment":[{"href":"https:\/\/blog.iabsolute.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=680"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.iabsolute.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=680"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.iabsolute.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=680"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}