Installing and setting up Apache in Ubuntu
published on
This post aims to cover how I will install typically install Apache. There will be things that you may decide to learn more about, change, update or even leave out.
My main reason for using Apache these days is that mod_security, mod_evasive and modpagespeed are all so easy to get set up. Other web servers either don't support this functionality or it is more difficult to install.
Install Apache
We will start by install Apache, mod_security and mod_evasive.
sudo add-apt-repository ppa:ondrej/apache2sudo apt-get updatesudo apt-get install apache2 apache2-utilssudo apt-get install libapache2-mod-security2 libapache2-mod-evasivesudo a2enmod mime http2 rewrite deflate expires headers ssl
Install the firewall
sudo apt install ufwsudo ufw default deny incomingsudo ufw default allow outgoingsudo ufw logging lowsudo ufw allow 80sudo ufw allow 443sudo ufw enable
Install PHP (if you need it)
This will install PHP 7.4 using the mpm_event module in Apache. If you want a different version of PHP change the version numbers in the following commands.
sudo apt-get install libapache2-mod-php7.4 libapache2-mod-fcgidsudo a2enmod mpm_eventsudo a2enmod proxy_fcgi setenvifsudo a2enconf php7.4-fpmsudo systemctl restart php7.4-fpm
Modpagespeed
Modpagespeed is a module developed by Google for Apache and Nginx. It is quite old now but it still works well at helping to speed up your site as will be evidenced in Google Pagespeed.
It isn't perfect and only works with certain content but can be quite useful. If you want to include it in your Apache installation then do the following.
wget https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_amd64.debsudo dpkg -i mod-pagespeed-stable_current_amd64.debsudo apt-get -f install
Modpagespeed comes with a useful default configuration but if you do wish to change yours the configuration file can be found at /etc/apache2/mods-available/pagespeed.conf.
Setting up mod_security
This is a web application firewall (or WAF). It can help to protect your site from online threats. Tuning mod_security for your unique site is beyond the scope of this simple post and will be covered in Working with ModSecurity in the Apache web server.
Start by editing the configuration file
sudo mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.confsudo nano /etc/modsecurity/modsecurity.conf
I like to leave it set to 'DetectionOnly' at first for a short time. I will then look through the logs to find which rules my site is tripping. I can then choose to make changes to my site to avoid these rules or disable these rules when I turn detection to 'on'. Before disabling any rules I will make sure I understand why the rule was being tripped and what the consequences of disabling it are.
Change the SecAuditLogParts ABDEFHIJZ line to read SecAuditLogParts ABCEFHJKZ. If you would prefer to have mod_security blocking immediately change the SecRuleEngine line to read SecRuleEngine On.
Install the rulesets
These are the rules that mod_security will use to decide whether to allow or block certain traffic.
wget https://github.com/coreruleset/coreruleset/archive/refs/tags/v3.3.2.tar.gztar xvf v3.3.2.tar.gzsudo mkdir /etc/apache2/modsecurity-crs/sudo mv coreruleset-3.3.2/ /etc/apache2/modsecurity-crs/cd /etc/apache2/modsecurity-crs/coreruleset-3.3.2/sudo mv crs-setup.conf.example crs-setup.confsudo nano /etc/apache2/mods-enabled/security2.conf
Find the IncludeOptional /usr/share/modsecurity-crs/*.load line, and replace it with the following two lines
IncludeOptional /etc/apache2/modsecurity-crs/coreruleset-3.3.2/crs-setup.confIncludeOptional /etc/apache2/modsecurity-crs/coreruleset-3.3.2/rules/*.conf
Set up logrotate
Create the /etc/logrotate.d/modsecurity file and add the following lines
{ rotate 14 daily missingok compress delaycompress notifempty}
Now enable it
sudo a2enmod security2
Setting up mod_evasive
Edit the configuration file at /etc/apache2/mods-enabled/evasive.conf and uncomment all the lines. Make sure to add your email address to the DOSEmailNotify line.
Now set up the directory necessary for the logs and enable the module
sudo mkdir /var/log/mod_evasive sudo chown -R www-data:www-data /var/log/mod_evasivesudo a2enmod evasive
Restart the server
After making changes the server must be restarted
sudo systemctl restart apache2
Apache should be set up to automatically start on reboot and run once installed. If it isn't run the following commands
sudo systemctl enable apache2sudo systemctl start apache2
Update some configuration files
There are now a few files that we need to make changes to in order to secure your server and get your site online.
security.conf
Open the file at /etc/apache2/conf-enabled/security.conf and add, or modify, the following lines
ServerTokens ProdServerSignature OffSecServerSignature " "TraceEnable OffHeader unset ServerHeader unset X-Powered-ByHeader unset X-CF-Powered-ByHeader unset X-Mod-PagespeedHeader unset X-Pingback
Some of these may not be relevant to you so it is a good idea to research what each of these do before adding them.
php.ini
Edit your php.ini file which, for this tutorial, will be found at /etc/php/7.4/fpm/php.ini. Find the line expose_php = on and change it to expose_php = off.
apache2.conf
The apache2.conf file can be found at /etc/apache2/apache2.conf and I tend to use the one below initially
# This is the main Apache server configuration file. It contains the# configuration directives that give the server its instructions.# See http://httpd.apache.org/docs/2.4/ for detailed information about# the directives and /usr/share/doc/apache2/README.Debian about Debian specific# hints.## * apache2.conf is the main configuration file (this file). It puts the pieces# together by including all remaining configuration files when starting up the# web server.## * ports.conf is always included from the main configuration file. It is# supposed to determine listening ports for incoming connections which can be# customized anytime.## * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/# directories contain particular configuration snippets which manage modules,# global configuration fragments, or virtual host configurations,# respectively.## They are activated by symlinking available configuration files from their# respective *-available/ counterparts. These should be managed by using our# helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See# their respective man pages for detailed information.## * The binary is called apache2. Due to the use of environment variables, in# the default configuration, apache2 needs to be started/stopped with# /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not# work with the default configuration.# Global configuration## ServerRoot: The top of the directory tree under which the server's# configuration, error, and log files are kept.## Do NOT add a slash at the end of the directory path.##ServerRoot "/etc/apache2"Mutex file:${APACHE_LOCK_DIR} defaultPidFile ${APACHE_PID_FILE}Timeout 120KeepAlive OnMaxKeepAliveRequests 100KeepAliveTimeout 10# These need to be set in /etc/apache2/envvarsUser ${APACHE_RUN_USER}Group ${APACHE_RUN_GROUP}HostnameLookups OffErrorLog ${APACHE_LOG_DIR}/error.logLogLevel warn# Include module configuration:IncludeOptional mods-enabled/*.loadIncludeOptional mods-enabled/*.conf# Include list of ports to listen onInclude ports.conf<Directory /> Options None AllowOverride None Require all denied</Directory><Directory /usr/share> AllowOverride None Require all granted</Directory><Directory /var/www/> Options -Indexes +FollowSymLinks AllowOverride None Require all granted</Directory>#<Directory /srv/># Options Indexes FollowSymLinks# AllowOverride None# Require all granted#</Directory>AccessFileName .htaccess<FilesMatch "^\.ht"> Require all denied</FilesMatch>Header unset ETagFileETag NoneLogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combinedLogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combinedLogFormat "%h %l %u %t \"%r\" %>s %O" commonLogFormat "%{Referer}i -> %U" refererLogFormat "%{User-agent}i" agent# Include generic snippets of statementsIncludeOptional conf-enabled/*.conf# Include the virtual host configurations:IncludeOptional sites-enabled/*.confServerName 127.0.0.1
Apache virtual host configuration
Before a site can appear online it needs a virtual host configuartion file. Initially I will disable the default one (which only needs doing once and then set up the necessary directories before adding the actual configuration settings.
Remember that were you see [domain] you should replace it with your own domain name (e.g. example.com).
sudo a2dissite 000-default.confsudo mkdir /var/www/[domain]sudo chown -R www-data:www-data /var/www/[domain]sudo chmod -R 755 /var/www/[domain]
Now create the virtual host file and add the following lines
sudo nano /etc/apache2/sites-available/[domain].conf<VirtualHost *:80> ServerAdmin [email address] ServerName www.[domain] ServerAlias [domain] DocumentRoot /var/www/[domain] # enable HTTP/2, if available Protocols h2 http/1.1 SetEnv TZ Europe/London AddDefaultCharset UTF-8 DefaultLanguage en FileETag none # if site uses PHP then put index.php first; if site is static only don't include index.php at all DirectoryIndex index.html index.php ErrorLog ${APACHE_LOG_DIR}/[domain]-error.log CustomLog ${APACHE_LOG_DIR}/[domain]-access.log combined # Set values to match what you need <Directory /var/www/[domain]> Options +SymLinksIfOwnerMatch -MultiViews -Indexes -Includes -ExecCGI AllowOverride All Require all granted </Directory> # if custom error pages are needed add a new line per error code # using the example as a guide # e.g. ErrorDocument [error code] [filename] #if using Cloudflare or other proxy then uncomment the following line #RemoteIPHeader CF-Connecting-IP # if using PHP then uncomment the following three lines and update to relevant version #<FilesMatch \.php$> # SetHandler "proxy:unix:/var/run/php/php7.4-fpm.sock|fcgi://localhost" #</FilesMatch> # set up cache times - HTML and CSS not cached by these settings # add them below if they won't be updated often <FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|swf)$"> # 2592000 = one month Header set Cache-Control "max-age=2592000, public" </FilesMatch> # some of these will need there own unique settings depending on what the site needs Header set X-XSS-Protection "1; mode=block" Header set X-Content-Type-Options nosniff Header set X-Frame-Options DENY Header set Referrer-Policy: no-referrer Header set X-Permitted-Cross-Domain-Policies "none" Header set Content-Security-Policy "default-src 'self';" Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure Header set X-Download-Options "noopen" Header set Permissions-Policy "fullscreen=(self)" Header set Access-Control-Allow-Origin * # The following line is an example only # and allows the use of Google Fonts #Content-Security-Policy default-src 'self'; style-src 'self' fonts.googleapis.com; font-src fonts.gstatic.com # or use the below if your site doesn't connect to anything else ###Header set Content-Security-Policy "default-src 'self';"</VirtualHost>
Some things to note:
[email address]and[domain]should be replaced by your site email address and domain name.- The default language and timezone may need changing depending on where you live.
- Some of the cache settings may not work for you. Make sure to change them to something more suitable.
- The headers may not be suitable for your site either. You should make sure to read up about them before using them.
Make sure to enable your site with sudo a2ensite [domain].conf and restart Apache using sudo systemctl restart apache2. If you need to test your configuration to see if it works try sudo apache2ctl configtest.
Finishing off the virtual host configuration
Now that the initial virtual host has been created we want to create a version that is secured with a SSL certificate.
Start by installing certbot
sudo apt-get install snapdsudo snap install core; sudo snap refresh coresudo snap install --classic certbotsudo ln -s /snap/bin/certbot /usr/bin/certbot
Now install a certificate for your site
sudo certbot -d [domain] -d www.[domain] --apache
Once you have answered a few questins your certificate should be installed. Certbot will craete a new configuration file and add a few lines to the one you created above to redirect visitors to the secure version of your site.
Open the new configuration file called [domain]-le-ssl.conf and add the following lines
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384SSLHonorCipherOrder offSSLSessionTickets offSSLUseStapling OnSSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
Finally make sure to restart Apache using sudo systemctl restart apache2.
Final notes
There are quite a few things that can be changed or left out of this configuration. Doing it this way I can make sure that the site is pretty secure when I get it online. However, it will be useful for you to research what different parts do and whether you need them or not.
All that should be left for you to do now is upload your site to /var/www/[domain] and begin sharing it with the world.
