Apache Web Server Install / Setup on Linux
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
- note about the prefix
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
- Apache - gives you port 80 ( HTTP ), good if you are running Apache without SSL
- Apache Secure - gives you port 443 ( TLS/SSL ), good if you are using SSL
- Apache Full - This gives you both port 80 and 443.
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/
- Apache already install
- This is for if you have an actual domain name
- you can get hosting tools to install SSL for you …..
-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
- /etc/crontab/
- /etc/cron./
- systemctl list-timers
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/ |
- 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:
- https://www.ssllabs.com/ssltest/analyze.html
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
- works like a firewall
- provides traffic monitoring
- defends against brute force attacks
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
- minimizes damage from DOS/DDOS and HTTP brute Force attacks
- it detects
- too many requests to a single page per second
- any child process making more than 50 concurrent requests
- IPs that keep making requests after they are temporarily blacklisted
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
-
0 (unlimited) to 2147483647 (2GB)
- “that are allowed in a request body”
- “limit the upload size for a particular directory.”
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