Apache has its own memory cache module mod_mem_cache
which can be used to cache content similar to memcached
. The following directives configure Apache to use 1GB
of memory and will cache up to 1000
objects, each between 1
byte and 1
megabyte.
<IfModule mod_mem_cache.c> Cache Enable mem / MCacheSize 1074741824 MCacheMaxObjectCount 1000 MCacheMaxObjectSize 1048576 </IfModule>
authz_host_module log_config_module headers_module setenvif_module # Proxy needed by default on OSX proxy_module mime_module # DAV needed by default on OSX dav_module dav_fs_module # Status needed by default on OSX status_module negotiation_module dir_module userdir_module dir_module userdir_module apple_userdir_module alias_module rewrite_module php5_module
Find:
Options Indexes FollowSymLinks MultiViews
and remove Indexes
from the options list.
Every directory can be protected with Allow
and Deny
. The following example denies access to the root path /
to anybody except the local network 192.168.1.0/24
:
<Directory /> Order deny,allow Allow from 192.168.1.0/24 Deny from all </Directory>
The Order
is important - it says to first deny
, which resolves to Deny from all
and after that to allow
which resolves to Allow from 192.168.1.0/24
.
Apache can be configured as a reverse proxy in order to pass traffic to a backend. For example, the following directives:
<VirtualHost *:80> ProxyRequests Off ProxyPreserveHost On ProxyPass / http://192.168.0.1:80/ connectiontimeout=300 timeout=300 ProxyPassReverse / http://192.168.0.1:80/ ServerName website.com ServerAlias *.website.com ErrorLog ${APACHE_LOG_DIR}/error.log LogLevel warn CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
will redirect all traffic for website.com
and any sub-domain, such as site.website.com
to the host 192.168.0.1
. Additionally, it specifies that connections will timeout in 300s
. As long as:
<VirtualHost *:80>
is specified, then you can have any number of websites to be proxied to their respective backends.
On Debian-like systems, a global rule can be set to block bad bots. In order to do so create a file: /etc/apache2/conf.d/blockbots.conf
containing the bad_bots configuration.
You must also enable the setenvif
module with:
a2enmod setenvif
The following directive will share /var/www/webserver/share
through WebDAV
:
<Directory /var/www/webserver/share> DAV On AuthType Digest AuthName "share" AuthDigestDomain / AuthDigestProvider file AuthUserFile /etc/apache2/.htpasswd <LimitExcept PROPFIND> Require valid-user </LimitExcept> </Directory>
It seems that Directory
is prefered instead of Location
; the latter leading sometimes to System Error 67
meaning that the network path could not be found.
The authentication mechanism to use for maximum compatibility is Digest
and username and password pairs can be generated using the htdigest
command line utility. For this example:
htdigest -c /etc/apache2/.htpasswd share username
which will prompt for a password.
If you have been trying for a while to access the DAV
share from Windows and are prompted for the username and password over and over again even if you entered the correct information, you may want to run in Windows on a command prompt:
net stop WebClient net start WebClient
in order to restart the web-client thereby resetting WebDAV
caches and fixing the username and password prompt loop.
After enabling mod_expires
with:
a2enmod expires
after which an optimized configuration can be added as a file under /etc/apache/conf.d/
in order to set the expiration time for resources.
We use zcat
in combination with the -f
flag to read compressed and uncompressed files. The commands assume that your current working directory is in the apache log directory. The commands also assume that the files are named access.log*
which may be different on other systems (ie: access_log
).
zcat -f access.log* | awk '{print $1}' | sort -u | wc -l
zcat -f access.log* | awk '{print $1}' | sort | uniq -c -d | sort -n -k 1
The idea of preventing people from hot-linking images on your website is contradictory in itself: if you are serving content, then why prevent people from using the content you provide? You can instead shut your website down and keep the content to yourself.
Nevertheless, some people chose to do this, and one way to prevent hot-linking is to branch on the referrer (typo intentional in the example below) and deny any access to images when the referrer is not your website. In the example, we assume that www.example.com
and example.com
are the accepted domains used as referrer to your images and any other referrer, except a blank referrer (last rule) is denied the connection:
SetEnvIfNoCase Referer "^http://www.example.com/" locally_linked=1 SetEnvIfNoCase Referer "^http://www.example.com$" locally_linked=1 SetEnvIfNoCase Referer "^http://example.com/" locally_linked=1 SetEnvIfNoCase Referer "^http://example.com$" locally_linked=1 SetEnvIfNoCase Referer "^$" locally_linked=1 <FilesMatch "\.(gif|png|jpe?g)$"> Order Allow,Deny Allow from env=locally_linked </FilesMatch>
Note that branching on referrers is a very bad idea, given upstream caches that may manipulate headers as well as the possibility to circumvent this protection easily by sending a different referrer (your domain) along with the request. Bad, bad idea.
The best way to permanently redirect surfers to a different website is to RedirectMatch
with the permanent
option. This will ensure that the 301
(permanently moved) will be sent before redirecting.
Suppose you have a virtual host configuration for the domain servername.com
:
<VirtualHost *:80> ServerName servername.com DocumentRoot /var/www/servername.com <Directory /var/www/servername.com Order allow,deny Allow from all </Directory> </VirtualHost>
and that you want to redirect www.servername.com
to servername.com
. You would then add another virtual host that will perform the redirection:
<VirtualHost *:80> ServerName www.servername.com RedirectMatch permanent ^/(.*) http://servername.com/$1 </VirtualHost>
In this example, we want to move somesite.net
to newsite.org
. We already have a virtual host in-place to handle newsite.org
and we need to redirect every page from somesite.net
as well as any sub-domains to newsite.org
. In order to do that, we modify the old virtual-host for somesite.net
:
<VirtualHost *:80> ServerName somesite.net ServerAlias *.somesite.net RewriteEngine on RewriteCond %{HTTPS}s ^..(s?) RewriteRule ^ - [E=PROTO:http%1] RewriteCond %{HTTP_HOST} !^\w+\.newsite\.org$ [NC] RewriteCond %{HTTP_HOST} ^(\w+)\.\w+\..+ [NC] RewriteRule ^/?(.*) %{ENV:PROTO}://%1. newsite.org/$1 [R=301,L] RewriteCond %{HTTP_HOST} somesite\.net RewriteRule ^/?(.*) %{ENV:PROTO}://newsite.org/$1 [R=301,L] </VirtualHost>
this will match both protocols, HTTP and HTTPs (matching the last s
), it will also match any sub-domains and redirect everything to newsite.org
.
When using a web-server for live streams or software repositories (git, svn, etc…) it is sometimes useful to disable timeouts. This can be done in apache using the following directives:
<IfModule reqtimeout_module> RequestReadTimeout header=0 body=0 </IfModule> LimitRequestBody 0
When migrating documents from case-insensitive filesystems to a server with Apache and a case-sensitive system, some links may appear broken and inaccessible. In order to resolve this, enable the speling
(note the lack of double-l
) module with:
a2enmod speling
and then either in an .htaccess
, Directory
directive or globally add the setting:
CheckSpelling on
To increase the amount of memory alloted to the Zend OpCache found in newer PHP variants, edit the file /etc/php5/apache2/conf.d/05-opcache.ini
. It should contain something like the following:
; configuration for php ZendOpcache module ; priority=05 zend_extension=opcache.so
and then after that line add the following options:
opcache.memory_consumption=256 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=8000 opcache.revalidate_freq=60 opcache.fast_shutdown=1 opcache.enable_cli=1
Suppose you have a /support
alias where clients should be able to access some protected data by authenticating first using basic authentication. In this case, the password may travel over the wire unencrypted such that we need to first redirect through HTTPs and then provide authentication.
In the example below a /support
alias is created that is protected by basic authentication through PAM. By using the 403 error document we can redirect to the HTTPs version of the website site.tld
.
Alias /support /usr/share/support <Directory /opt/support> Options FollowSymLinks MultiViews AllowOverride All SSLOptions +StrictRequire SSLRequireSSL ErrorDocument 403 https://site.tld/support AuthType Basic AuthName "Restricted Area" AuthBasicProvider external AuthExternal pwauth GroupExternal unixgroup Require valid-user </Directory>
The reason for this hack is that authentication takes precedence such that using mod_rewrite
to create a redirect would not work. As such, the setup now generates a 403 error when the HTTP version of the website is requested, which in turn redirects to the HTTPs version where the authentication takes place over HTTPs.
If a website accepts a connection through HTTP and then redirects to HTTPS, there is a small window of opportunity where the client talks to the server without encryption that can be abused with a MITM attack.
First enable the headers module:
a2enmod headers
To enable HSTS, edit the SSL virtual host version of your website and add the following stanza:
Header always set Strict-Transport-Security "max-age=31556926; includeSubdomains;"
this will tell browsers to use the HTTPS version of the website without loading the HTTP version first.
The age in the example is set to one year and the includeSubdomains
option will enable HSTS for any subdomains as well.
When using Apache SSL, the following directives should be added in order to use strong cryptography:
SSLProtocol all -SSLv2 -SSLv3 SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS SSLHonorCipherOrder on SSLCompression off SSLSessionTickets off
the settings will disable SSLv2 and SSLv3 as well as enable most of the elliptic-curve cryptography.
Optionally, given a non self-signed certificate, SSL stapling can be used for apache above 2.3.3:
SSLUseStapling on SSLStaplingResponderTimeout 5 SSLStaplingReturnResponderErrors off SSLStaplingCache shmcb:/var/run/ocsp(128000)
Create a virtual host file or create a virtual host using the following configuration:
<VirtualHost *:80> Redirect 404 / </VirtualHost>
The effect is that if a visitor attempts to access the server IP directly, the default virtual host will return a 404 error.
To calculate the MaxClients
value for Apache, you first need to get the Resident Set Size (RSS) of an Apache process. In order to do this, under Linux, you can issue:
ps -ylC apache2 --sort:rss
otherwise, the top
utility may work as well by watching the SIZE
or RSS
value.
The formula to calculate the value that should be passed to MaxClients
in the Apache configuration is:
For instance, assuming a server with a total of 8GB of RAM, leaving 1GB over to other processes, and with an Apache RSS of 100MB the calculation would become:
The following setup implements a global and consistent directory index style that can be used for multiple virtual hosts just by adding an include to any Directory
stanza within a virtual host configuration.
where:
/etc/apache2/conf-available/fancyindex.conf
contains:Alias "/fancyindex.css" "/var/www/.fancyindex.css
/etc/apache2/includes/fancyindex.conf
contains:IndexOptions +Charset=UTF-8 IndexOptions +TrackModified IndexOptions +Charset=UTF-8 IndexOptions +FoldersFirst IndexOptions +NameWidth=* IndexOptions +FancyIndexing IndexOptions +HTMLTable IndexOptions +SuppressDescription IndexIgnore favicon.ico IndexIgnore auth* IndexIgnore include* IndexIgnore css* IndexIgnore share* IndexIgnore upload* IndexIgnore incoming* IndexStyleSheet "/fancyindex.css" Options +Indexes
/etc/apache2/sites-available/vhost.conf
is a virtual host configuration where the indexing can be turned on within any Directory
stanza just by including /etc/apache2/includes/fancyindex.conf
, ie enabling directory indexing for the directory named path
relative to the root of the virtual host:<Directory /path> include "includes/fancyindex.conf" </Directory>
/var/www/.fancyindex.css
contains the following:* { font-family: monospace; }
and is responsible for setting the CSS for the rendered index page.
IndexStyleSheet
takes an URL relative to the virtual host document root such that the aliasing performed within /etc/apache2/conf-available/fancyindex.conf
redirects the requests to the default virtual host where the /var/www/.fancyindex.css
file is placed. It ain't pretty, but it works; at least short of changing IndexStyleSheet
itself!
Perhaps a good reason for preferring this setup to using AllowOverride
and .htaccess
files is that the style of the directory index is generated by Apache itself rather than the website such that one can avoid mixing data with code. Furthermore, given multiple virtual hosts with the same owner, a consistent style may be preferred and with a centralized way of batch-changing all directory indexes.
On Debian, to enable brotli compression, the Apache module must first be installed by issuing the command:
apt-get install brotli
and then the Apache module must be enabled by issuing the command:
a2enmod brotli
Lastly, create the file /etc/apache2/conf-available/brotli.conf
with the following contents:
<IfModule mod_brotli.c> AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/xml text/css text/javascript application/javascript </IfModule>
The purpose of this file is to instruct the brotli Apache module to compress certain resources, namely textual content as well as javascript with the brotli compressor.
Finally, enable the configuration file by issuing the command:
a2enconf brotli
and reload the Apache configuration:
systemctl apache2 reload
The brotli compressor should now be enabled and will globally compress content as it is transferred from the Apache server.
Note that an alternative configuration is to add the contents of the file /etc/apache2/conf-available/brotli.conf
to a virtual host definition in order to only compress some websites.
The process of rate-limiting an IP network with Apache mod_qos involves matching an IP address block using the Apache2 SetEnvIfExpr
expression:
SetEnvIfExpr "-R '47.128.0.0/16'" Amazon=yes
where:
"-R '47.128.0.0/16'"
is a network block match and,Amazon=yes
is a variable Amazon
being set to yes
followed by using mod_qos to rate-limit:
QS_EventLimitCount Amazon 10 60
where:
10
represents the number of connections allowed per 60
seconds.