Low Orbit Flux Logo 2 D

Apache Web Server Install / Setup on Linux

Apache Web Server logo

Red Hat / Centos Differences

By default the instructions on this page assume that you are running Ubuntu 18.04. Debian should be almost the same. Red Hat will have a few minor differences. Instead of calling the service ‘apache2’, the Red Hat / Centos package has named it ‘httpd’. Just replace ‘apache2’ with ‘httpd’ and you will be all set for the world of Red Hat / Centos.

Installation on Red Hat and Centos is a tiny bit different. Just use the ‘yum’ command and replace the package ‘apache2’ with ‘httpd’.

sudo yum install httpd
sudo systemctl enable httpd
sudo systemctl start httpd

Build From Source

gzip -d httpd-NN.tar.gz
tar xvf httpd-NN.tar
cd httpd-NN
./configure --prefix=/opt/apache
make install

vi /opt/apache/conf/httpd.conf
/opt/apache/bin/apachectl -k start
/opt/apache/bin/apachectl -k stop

Install Apache on Ubuntu / Debian

sudo apt update
sudo apt install apache2
apache2 -version  # verify 

sudo ufw status
sudo ufw app list

Many people will tell you that you should only open the firewall for the ports that you are listening on. If you are only using either port 80 or port 443, then only open the profile for that port. This makes sense if you only want to serve one port. It is almost always a good idea to use SSL. If you aren’t using it, you should get it set-up. When you are using SSL, it is a good idea to also serve port 80 and just redirect that to 443. This way, if someone accidentally tries to access the insecure version of your site, they will be redirected to the secure version instead of just getting an error.

I would select “Apache Full” because you will normally want to use SSL on port 443 and redirect regular HTTP requests from port 80 to this port.

Enable ‘Apache Full’ and verify the status.

sudo ufw allow 'Apache Full'
sudo ufw status

Check that the Apache HTTP Server is running. It should be but start it if it isn’t. It should also be enabled but if not you can go ahead and enable it.

sudo systemctl status apache2
sudo systemctl enable apache2
sudo systemctl start apache2

If you don’t know it, you can find your IP with either of these commands.

hostname -I
curl -4 icanhazip.com

You can verify that your server is up and serving pages by pasting your URL in a web browser ( assuming your IP is ). You should see the default Apache page.

By default, your site will be served from here. This is where all of your HTML goes.


Manage the server with these commands:

sudo systemctl stop apache2       # stop it
sudo systemctl start apache2      # start it
sudo systemctl restart apache2    # restart it 
sudo systemctl reload apache2     # reload config, stay connected
sudo systemctl disable apache2    # disable starting at boot
sudo systemctl enable apache2     # enable starting at boot

Virtual Hosts

By default, you will basically be serving a single site from this directory:


If you want to be able to serve multiple sites from your web server, you will want to set-up virtual hosts. These are like server blocks from NGINX.

Create a New Virtual Host

For this example we will creat a new virtual host for the domain example.org.

Virtual Host File

sudo vi /etc/apache2/sites-available/example.org.conf

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName example.org
    DocumentRoot /var/www/example.org/html
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

Setup Your Web Data Directory

sudo mkdir -p /var/www/example.org/html sudo chown -R $USER:$USER /var/www/example.org/html sudo chmod -R 755 /var/www/example.org

Create your own test page:

vi /var/www/example.org/html/index.html

        Welcome to example.org

Welcome to example.org

Enable the new config for your domain and disable the default configuration.

sudo a2ensite example.org.conf sudo a2dissite 000-default.conf

Test the configuration to make sure that it is valid before actually restarting Apache. If it is OK, restart.

sudo apache2ctl configtest # test sudo systemctl restart apache2 # Restart Apache.

You should now be able to reach your site by pasting your URL into a browser: http://example.org.

/var/www/html default web content directory /etc/apache2 Apache configuration directory /etc/apache2/apache2.conf main Apache config file, has global configs and loads other config files /etc/apache2/ports.conf configure what ports Apache will listen on here /etc/apache2/sites-available/ virtual host configs go here /etc/apache2/sites-enabled/ enabled virtual hosts configs go here, these are just links to files in the ‘sites-available’ dir /etc/apache2/conf-available/ configuration fragments /etc/apache2/conf-enabled/ enabled configuration fragments, links to files in the ‘conf-available’ dir /etc/apache2/mods-available/ mods (.load and .conf files) /etc/apache2/mods-enabled/ enabled mods ( again, just links )

a2enmod # enable mod a2dismod # disable mod


/var/log/apache2/access.log # all requests are recorded here /var/log/apache2/error.log # all errors go here

Apache PHP Setup

sudo apt install php libapache2-mod-php php-mysql

sudo nano /etc/apache2/mods-enabled/dir.conf

DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm

sudo systemctl restart apache2 sudo systemctl status apache2

sudo nano /var/www/your_domain/info.php sudo nano /var/www/your_domain/html/info.php


PHP security stuff

/etc/php.d/secutity.ini expose_php=Off display_errors=Off log_errors=On error_log=/var/log/httpd/php_scripts_error.log open_basedir=”/var/www/html/” # limit FS access to here file_uploads=Off upload_max_filesize=1M ## only if uploads are needed and on allow_url_fopen=Off allow_url_include=Off sql.safe_mode=On ## might break things post_max_size=1K ## might break things

disable_functions =exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source

set in seconds

max_execution_time = 30 max_input_time = 30 memory_limit = 40M

curl -I https://www.cyberciti.biz/index.php

View modules:

php -m

Disable modules: mv /etc/php.d/sqlite3.ini /etc/php.d/sqlite3.disable

Watch your logs:

tail -f /var/log/httpd/error_log

grep ‘login.php’ /var/log/httpd/error_log

egrep -i “denied|error|warn” /var/log/httpd/error_log

tail -f /var/log/httpd/php_scripts_error.log

grep “…etc/passwd” /var/log/httpd/php_scripts_error.log

Extra Apache stuff:

<directory /var/www/html> Order allow,deny

Add rest of the config goes here…


Apache SSL with Lets Encrypt and Certbot


– certbot logo – lets encrypt logo

background image from bottom from: https://upcloud.com/community/tutorials/install-lets-encrypt-apache/

-tested on ubuntu 18.04

Add Certbot Repository

sudo apt-get update sudo apt-get install software-properties-common # needed? sudo add-apt-repository universe # needed? sudo add-apt-repository ppa:certbot/certbot sudo apt-get update

NOTE - this is standard now …..

Install Certbot

sudo apt-get install certbot python-certbot-apache

Make sure HTTPS is open and not just HTTP sudo ufw status sudo ufw allow ‘Apache Full’ sudo ufw delete allow ‘Apache’ sudo ufw status

Get the cert, edit Apache configs, and turn on HTTPS.

sudo certbot –apache # all domains / server wide sudo certbot –apache -d your_domain -d www.your_domain # just one domain

It will give you the option to redirect HTTP to HTTPS or not. I choose to redirect. This is probably usually a good idea.

/etc/letsencrypt/live/your_domain/fullchain.pem /etc/letsencrypt/live/your_domain/privkey.pem

Just get the cert, change Apache by hand

sudo certbot certonly –apache ….. install manually yourself …..

Optionally, disable insecure protocols:

sudo nano /etc/letsencrypt/options-ssl-apache.conf SSLProtocol all -SSLv2 -SSLv3 -TLSv1

disable for security: SSLCompression off

Users can’t bypass warnings about the cert in case of MITM attacks: SSLOptions +StrictRequire

More optional security settings: sudo nano /etc/apache2/sites-available/000-default-le-ssl.conf Header always set Strict-Transport-Security “max-age=31536000; includeSubDomains; preload”

sudo systemctl reload apache2    # check if this is really needed

Test Automatic Renewals

sudo certbot renew --dry-run
sudo certbot renew --dry-run --agree-tos  ## ??????

Actually renew for real. You will need this someday (soon these certs only last ……. ).

sudo certbot renew      

Schedual renewals like this so that you don’t need to remember.

Renew command should go in one of htese

/etc/crontab/ /etc/cron./ systemctl list-timers

sudo crontab -e
01 02,14 * * * /etc/cron.daily/certbot-renew

Renewal script:

if certbot renew > /var/log/letsencrypt/renew.log 2>&1 ; then
   /etc/init.d/apache2 reload >> /var/log/letsencrypt/renew.log

sudo chmod +x /etc/cron.daily/certbot-renew

Test it:


Make sure there are no errors and that your site shows as secure.

Also, make sure that http://yourwebsite.com/ redirects to https://yourwebsite.com/

Also, test your site with this tool:


Hardening / Securing Apache Web Server


hide Apache Version and OS Identity from Errors

vim /etc/httpd/conf/httpd.conf (RHEL/CentOS/Fedora)
vim /etc/apache2/apache2.conf (Debian/Ubuntu)

ServerSignature Off
ServerTokens Prod

service httpd restart (RHEL/CentOS/Fedora)
service apache2 restart (Debian/Ubuntu)

Disable Directory Listing

<Directory /var/www/html>
    Options -Indexes

Regular Updates

need the ubuntu command too

httpd -v

Server version: Apache/2.2.15 (Unix) Server built: Aug 13 2013 17:29:28

yum update httpd
apt-get install apache2

Disable Modules

grep LoadModule /etc/httpd/conf/httpd.conf

disable these: mod_imap, mod_include, mod_info, mod_userdir, mod_autoindex

You can probably find a whole lot more modules that could be removed depending on your specific needs. In terms of security, the fewer you have the better.

Run Apache as separate User and Group

Create Apache User and Group

groupadd http-web
useradd -d /var/www/ -g http-web -s /bin/nologin http-web

vi /etc/httpd/conf/httpd.conf 

User http-web
Group http-web

——> apache users and dir permissions

Directory Permissions: Allow/Deny/Options

Restrict dir access:

   Options None
   Order deny,allow
   Deny from all

””” Options “None” – This option will not allow users to enable any optional features. Order deny, allow – This is the order in which the “Deny” and “Allow” directives will be processed. Here it will “deny” first and “allow” next. Deny from all – This will deny request from everybody to the root directory, nobody will be able to access root directory. “””

Secure Apache: mod_security and mod_evasive

Use mod_security and mod_evasive Modules to Secure Apache


sudo apt-get install libapache2-modsecurity sudo a2enmod mod-security sudo /etc/init.d/apache2 force-reload

yum install mod_security /etc/init.d/httpd restart


Disable Apache’s following of Symbolic Links

main config file: Options -FollowSymLinks

In case some app needs links:


Enable symbolic links

Options +FollowSymLinks

Turn off Server Side Includes and CGI Execution

Just make sure you don’t disable something you need …..


Options -Includes
Options -ExecCGI

Per directory:

<Directory "/var/www/html/web1">
Options -Includes -ExecCGI

Limit Request Size

0 (unlimited) to 2147483647 (2GB)

“that are allowed in a request body” “limit the upload size for a particular directory.”

500k limit

<Directory “/var/www/myweb1/user_uploads”> LimitRequestBody 512000 </Directory>

Protect DDOS attacks and Hardening

””” TimeOut : This directive allows you to set the amount of time the server will wait for certain events to complete before it fails. Its default value is 300 secs. It’s good to keep this value low on those sites which are subject to DDOS attacks. This value totally depends on kind of request you are getting on your website. Note: It could pose problems with come CGI scripts.

MaxClients : This directive allows you to set the limit on connections that will be served simultaneously. Every new connection will be queued up after this limit. It is available with Prefork and Worker both MPM. The default value of it is 256.

KeepAliveTimeout : Its the amount of time the server will wait for a subsequent request before closing the connection. Default value is 5 secs.

LimitRequestFields : It helps us to set a limit on the number of HTTP request’s header fields that will be accepted from the clients. Its default value is 100. It is recommended to lower this value if DDos attacks are occurring as a result of so many http request headers.

LimitRequestFieldSize : It helps us to set a size limit on the HTTP Request header. “””

Disable Trace HTTP Request

TraceEnable off

Manually Configure SSL

You may decide that you want to generate your own certificates, by hand, without using Lets Encrypt. If you are generating your own cert without it being signed by a known autority it won’t be much use for a site that is exposed on the internet. It will show up as insecure and will not be trusted by anyone. It may work just fine though if you are running a webserver on a private network and you just need to have the connection encrypted.

You can generate SSL certificates like this.

openssl genrsa -des3 -out example.com.key 1024
openssl req -new -key example.com.key -out exmaple.csr
openssl x509 -req -days 365 -in example.com.com.csr -signkey example.com.com.key -out example.com.com.crt

Your virtual host configuration will look something like this:

        SSLEngine on
        SSLCertificateFile /etc/pki/tls/certs/example.com.crt
        SSLCertificateKeyFile /etc/pki/tls/certs/example.com.key
        SSLCertificateChainFile /etc/pki/tls/certs/sf_bundle.crt
        ServerAdmin ravi.saive@example.com
        ServerName example.com
        DocumentRoot /var/www/html/example/
        ErrorLog /var/log/httpd/example.com-error_log
        CustomLog /var/log/httpd/example.com-access_log common

Disable Null and Weak Ciphers: