Low Orbit Flux Logo 2 F

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
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 192.168.0.25 ). You should see the default Apache page.

http://192.168.0.25

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

/var/www/html

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:

/var/www/html

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
</VirtualHost>

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

<html>
    <head>
        <title>Welcome to example.org</title>
    </head>
    <body>
        <h1>Welcome to example.org</h1>
    </body>
</html>

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

Logs!

/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

<IfModule mod_dir.c>
    DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm
</IfModule>

<IfModule mod_dir.c>
    DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
</IfModule>

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


http://your_domain/info.php

PHP security stuff


vi /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://your_domain/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>
    <limitExcept GET POST>
        Order allow,deny
    </limitExcept>
## Add rest of the config goes here... ##
</directory>

Apache SSL with Lets Encrypt and Certbot

https://certbot.eff.org/lets-encrypt/ubuntubionic-apache.html

– 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 vi /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 vi /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 at some point.


sudo certbot renew      

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

Renew command should go in one of these


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

Renewal script:


#!/bin/sh
if certbot renew > /var/log/letsencrypt/renew.log 2>&1 ; then
   /etc/init.d/apache2 reload >> /var/log/letsencrypt/renew.log
fi
exit

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

Test it:

https://yourwebsite.com/

Hardening / Securing Apache Web Server

Get more background from these guys: Tecmint Apache Security Tips

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
</Directory>

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.

User and Permissions

You are going to want to run Apache as a 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

Directory Permissions: Allow/Deny/Options

Restrict dir access:


<Directory>
   Options None
   Order deny,allow
   Deny from all
</Directory>
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.

mod_security


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

mod_evasive

Disable Apache’s following of Symbolic Links

main config file:


Options -FollowSymLinks

In case some app needs links:


.htaccess

# Enable symbolic links
Options +FollowSymLinks

Turn off Server Side Includes and CGI Execution

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

globally:


Options -Includes
Options -ExecCGI

Per directory:


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

Limit Request Size

500k limit example:


<Directory "/var/www/myweb1/user_uploads">
   LimitRequestBody 512000
</Directory>

Protect DDOS attacks and Hardening

TimeOut : This defaults to 300 seconds. It sets the timeout value for different events. Keeping this low can help to mitigate DDOS attacks.
MaxClients : This defaults to 256. This is the maximum number of connections that can be served at the same time. Connections will start to queue after this threshold. It works with Worker and Prefork MPM.
KeepAliveTimeout : This defaults to 5 seconds. It is the time that the server will wait for another connection before it closes the connection.
LimitRequestFields : This defaults to 100. This limits the number of fields in the HTTP request header. Lowering this can help to mitigate DDOS attacks.
LimitRequestFieldSize : This will limit the size of 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:


<VirtualHost 172.16.25.132:443>
        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
</VirtualHost>

Disable Null and Weak Ciphers:


SSLCipherSuite ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM