How to Setup Cache on Apache Server Correctly - apache

I have followed the tutorial to setup Browser Caching on My Droplet:
https://www.digitalocean.com/community/tutorials/how-to-configure-apache-content-caching-on-ubuntu-14-04
What I want to accomplish for now is set up a year-long cache on all files but later on will fine-tune files like HTML for a much shorter expiry.
I have checked my cache folder with below and it is growing:
ls -la /var/cache/apache2/mod_cache_disk/
But the problem is Google Page Insight and other page speed tests are still reporting that there is not cache policy applied to my files even after 2 days of caching applied to the server.
I have also check edge dev tools and most files don't show Cache-Control in response and for some a small subset of files that it is shown, it is set to no-cache.
I included the following lines in my domain's virtual host file and enabled caching on my server:
CacheQuickHandler off
CacheLock on
CacheLockPath /tmp/mod_cache-lock
CacheLockMaxAge 5
CacheIgnoreHeaders Set-Cookie
<Location />
CacheEnable disk
CacheHeader on
CacheDefaultExpire 600
CacheMaxExpire 86400
CacheLastModifiedFactor 0.5
ExpiresActive on
ExpiresDefault A31536000
Header set Cache-Control public
Header merge Cache-Control max-age=31536000
FileETag All
</Location>
Any idea what's wrong?

After days of headache I finally solved it. I was editing the Virtual Host for HTTP and not the one for HTTPs/SLL. If any body faces this problem just search for active virtual host files on your server like below:
$ apachectl -S
VirtualHost configuration:
:443 de***.com (/etc/apache2/sites-enabled/000-default-le-ssl.conf:2)
:80 de***.com (/etc/apache2/sites-enabled/000-default.conf:1)

Related

Apache2 no cache specific file only

I'm running and Amazon EC2 with Ubuntu 14.4 and Apache2 with no PHP or other server-side script--just a static content site. I used this tutorial to get to the point I am at now with the apache file (see screenshot at link below):
https://www.digitalocean.com/community/tutorials/how-to-configure-apache-content-caching-on-ubuntu-14-04
I want to have a directive (if that is the nomenclature) that tells Apache to not cache a single, specific file only, but still handle everything else as it is already configured. I'm no computer whizz here--just learning. Is there a way to do this? Currently I have made a new directory inside my images folder called "no-cache" where the image I do not want cached lives.
I tried adding a second location tag below the first one with "CacheDisable on" inside it, however this is not supported. Also tried using a Directory tag, but this also does not work with the current configuration.
Thanks in advance!
/etc/apache2/sites-enabled/000.default.conf
The link you provided is a bit confusing since it mentions so many different types of caching.
When dealing with Webservers and caching, what you usually mean is sending cache messages (using http headers) to define how the browser should handle caching, to improve visitors performance. This is the last item discussed in that link of yours, despite being the most common. The first section talks about Apache caching files itself to improve its own performance and is much less common.
If client side caching using mod_expiries is what you mean, then you can control this with location headings:
#Allow long term assets to be cached for 6 months as they are versioned and should never change
<Location /assets/libraries/ >
ExpiresDefault A15724800
Header set Cache-Control "public"
</Location>
#Do not cache these files
<Location /login >
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
</Location>
I've a more detailed blog on this here: https://www.tunetheweb.com/performance/http-performance-headers/caching/.

The files served by my Apache Server are not being saved on browser cache

I have installed and configured an Apache server with a virtualhost which serves images.
When I load my page with images on the browser the second time (the images should be on cache after the first time the page is loaded), the browser doesnt get the images (or files) from cache, and think that it should.
What is wrong? I am using Google Chrome, and when I load some other web from other server the cache works, so I think that I have some problem with the Apache, but I am not sure.
Thank you very much.
The response is a video-segment which is played by Dash player.
Response headers:
accept-ranges:bytes
content-length:194431
date:Wed, 09 Mar 2016 07:42:07 GMT
etag:"2f77f-52acd33f8b167"
last-modified:Tue, 02 Feb 2016 17:55:12 GMT
server:Apache/2.4.18 (Unix) OpenSSL/1.0.2e PHP/7.0.2
status:200
After doing that:
ExpiresActive On
# Set up caching on media files for 1 year (forever?)
<FilesMatch "\.(mp4|m4s)$">
ExpiresDefault "access plus 3600 seconds"
Header set Cache-Control "public"
Header set Content-Type "video/mp4"
Header set Vary "Host"
Header set Access-Control-Allow-Origin "*"
</FilesMatch>
The headers are:
accept-ranges:bytes
access-control-allow-origin:*
cache-control:public
content-length:194431
content-type:video/mp4
But it doesnt save on the cache, I mean, when I reload the web or the video, it does not get it from the cache as it should.
You are not including any cache-control headers telling the browser to cache the resources. The spec is unclear how to handle this but most browsers choose not to cache unless explicitly told to.
You need to include Apache config like this (assuming you are already including the mod_expiries module):
ExpiresActive On
# Set up caching on media files for 1 week
<filesMatch ".([iI][cC][oO]|[gG][iI][fF]|[jJ][pP][gG]|[jJ][pP][eE][gG]|[pP][nN][gG]|[fF][lL][vV]|[pP][dD][fF]|[sS][wW][fF]|[mM][oO][vV]|[mM][pP]3|[wW][mM][vV]|[pP][pP][tT])$">
ExpiresDefault A604800
Header append Cache-Control "public"
</filesMatch>
# Set up caching on font files for 6 months
<filesMatch ".([eE][oO][tT]|[tT][tT][fF]|[sS][vV][gG]|[Ww][Oo][Ff][Ff]|[Ww][Oo][Ff][Ff]2)$">
ExpiresDefault 15552000
Header append Cache-Control "public"
</filesMatch>
Which will then produce a header like this:
cache-control:max-age=10800, public
I've written a blog post on this if you want more details: https://www.tunetheweb.com/performance/http-performance-headers/caching/
OK, I have solved the problem.
I was using an https connection and the certificate I was using didnt have the correct parameters (common name must be the name of the url programmed on the server) and the certificate of the server must be authenticate by some CA, so I have made CA certificates to authenticate the server certificates. This means that if you have an unsecure https connection, Chrome does not save files on cache.
After having all the certificates corrected, I have upload to google chrome the certificates to trust my web (configuration of google Chrome, advanced options, Manage https/ssl certificates). After that, I can save files on cache because of the certificates which makes the https connection secure (green lock on the chrome url bar).
That was my problem and this is how I solved it.
Thanks for your answers and your time!! ;)

Enabling CORS .htaccess restrictions

I am encountering some behaviour from a produciton server and I was wondering if someone could confirm if something is possible and how it might have been done.
I have a website www.example.com with SSL enabled and all traffic forwarding to https
On that site I have a font file https://www.example.com/wp-content/assets/fonts/icons.ttf
I have additional campaign sites (e.g www.examplecampaign.com) that use the css file from example.com which loads in a font face using that font file. I am actually adding all the relevant file types woff, etc but will refer to ttf for simplicity. The icon font displays fine on www.example.com but on www.examplecampaign.com because in Firefox I get the error
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://www.example.com/wp-content/assets/fonts/icons.ttf. This can be fixed by moving the resource to the same domain or enabling CORS.
So here begins my problem. On our stage server which we have full access to I can add
# BEGIN REQUIRED FOR WEBFONTS
AddType font/ttf .ttf
AddType font/eot .eot
AddType font/otf .otf
AddType font/woff .woff
<FilesMatch "\.(ttf|otf|eot|woff)$">
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
# END REQUIRED FOR WEBFONTS
to the .htaccess file and that solves the problem. However on our produciton server which is owned and managed by the client this header modification is ignored. I am using http://web-sniffer.net/ to test this.
To further complicate things I hvae found that if I just added
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
on my stage site the header would appear when requesting any page or resource BUT on the production server if I added that the Access-Control-Allow-Origin would appear on all pages apart from the font files (and possible other resources).
So my question is, is it possible in Apache to disable / ignore header modification for a certain file type(s) and how would that be done. It's weird that it's so specific. We no longer have sudo access and have to request changes to conf files which is one of the reasons im making this change in .htaccess not that I think that would matter where this is set? Also example.com is a wordpress site but I don't think that would affect anything? As it's working on stage but not produciton.
Does anyone know of the Apache configuration that would restrict the use of mod_header in that way?

Apache configuration settings for specific port (PCI Compliance)

I am trying to make my server PCI Compliant. One of the last issues that I need to fix is to remove the INode from Apache ETag header. So I defined in httpd.conf this line: "FileETag MTime Size" to only return MTime and Size.
<Directory "/var/www/html">
Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
FileETag MTime Size
</Directory>
This fix solved issue for standard port 80.
Now, I also have hosting control panel (ISPConfig3) running on port 8000. After running PCI compliance test I got this error:
Apache ETag header discloses inode numbers Severity: Potential Problem
CVE: CVE-2003-1418 Impact: A remote attacker could determine inode
numbers on the server. Resolution Use the
http://httpd.apache.org/docs/2.2/mod/core.html#FileETag FileETag
directive to remove the INode component from the calculation of the
ETag. For example, place the following line in the Apache
configuration file to calculate the ETag based only on the file's
modification time and size: FileETag MTime Size Vulnerability Details:
Service: 8000:TCP
I assume I have to add something in httpd.conf to also apply FileETag to all applications running on port 8000.
Please advice what should be done.
Thank you!
Kelvin
It sounds like your PCI Compliance test is out of date. Have you read CVE-2003-1418?
Apache HTTP Server 1.3.22 through 1.3.27 on OpenBSD allows remote attackers to obtain sensitive information via (1) the ETag header, which reveals the inode number, or (2) multipart MIME boundary, which reveals child proccess IDs (PID).
[My Ital] This isn't an issue for Apache 2.2 which uses a different Etag algo. And if you are still running Apache 1.3 then you've got bigger problems since it is no longer supported.
You are trying to solve a non-problem. Get yourself a current PCI Compliance test suite.
Add this to the beginning of your /etc/apache2/http.conf:
#PCI Compliance fix for "Apache ETag header discloses inode numbers"
Header unset ETag
FileETag MTime Size
This worked for my PCI compliance scan and I don't see why it wouldn't work on all ports that apache listens on.
Per Apache 2.4 FileETag directive documentation the default used for calculating the ETag is MTime Size.
For Apache versions 2.3.14 and earlier the default was set to INode MTime Size.
ETag settings for all ports and checking Apache ETag output
You can check for yourself by using curl and comparing the ETag value returned in the headers versus the inode value returned by ls.
For example:
curl -I https://example.com/file
where file is a file that is on your filesystem served by your Apache web server.
With ETag set to MTime Size you might see something like this:
ETag: "3-24f10051b181e"
You can change the values returned by ETag by using the FileETag directive. Add to the bottom of your Apache server conf (e.g. /etc/httpd/conf/httpd.conf) file the following:
FileETag INode
Reload or restart Apache and then repeat the curl test.
In my tests, inclusion of FileETag INode in the server config file affected output on ALL ports being served by my Apache web server: 80 and 443.
With ETag set to INode you should receive a single hex number, something like this:
ETag: "200f8fa"
Convert the numbers returned by ETag from hex to decimal and compare to the inode number.
If you run ls -i /path/to/webroot/example.com/file the inode returned should be the decimal equivalent of the hex number returned via ETag (in this example 33618170).
If you added FileETag Inode don't forget to remove it and restart/reload Apache.
ETag settings for a specific port
The contexts where you can use FileETag are:
server config
virtual host
directory
.htaccess
If FileETag is present in the server config with the component keywords you desire and you are still seeing incorrect ETag output for a specific port that Apache is serving, you should search vhost config files and web root directories for FileETag - as any settings there will override the server config.
If you actually want to have a specific ETag output on a specific port, you should add FileETag to the appropriate VirtualHost block for the port you want to affect. If you are serving more than one site on this port, you'll need to add FileETag to each VirtualHost block that specifies that port.

Using keep-alive feature in .htaccess

I want to use the keep-alive feature in Apache. How can I do this with my host (.htaccess file), and what are the best values for the parameters like KeepAliveTimeout?
If Keep-alive is turned on in the Apache configuration, all you need is just set an HTTP header Connection: keep-alive. E.g. add following lines to your .htaccess file:
<ifModule mod_headers.c>
Header set Connection keep-alive
</ifModule>
You can't control keepalive behaviour in an .htaccess. Keepalives are a host-level feature, not one where different directories can behave differently depending on the per-directory htaccess info.
If you are on the kind of basic shared hosting that only gives you .htaccess to configure your sites, you can't change the keepalive settings. Presumably the hosting company will have set them appropriately, or just left them on the default settings, which are usually fine.
Yes Keep-alive behavior can be controlled in .htaccess file.
First check the server setting by printing $_SERVER and if
[HTTP_CONNECTION] => keep-alive
is there then you just have to include the setting in your .htaccess file.
Add the following line at the end of .htaccess file in your project's root directory.
<ifModule mod_headers.c>
Header set Connection keep-alive
</ifModule>
If you have SSH access to your server you should edit the Apache config file. Use these settings as a starter:
KeepAlive: on
KeepAliveTimeout: 3 seconds
MaxKeepAliveRequests: 60
This should work for most basic server setups with average traffic. You can always tweak the settings to suit your own needs. See here for more detailed info about this: http://www.giftofspeed.com/enable-keep-alive/
If you don't have access to your server you should contact your host. Changing the keepalive settings on your own by editing the .htaccess file will probably don't work.
It very much depends on your site and the amount of traffic it receives. If a user comes to your site, then clicks through to another page within the KeepAliveTimeout setting (default is 15), a new TCP does not have to be created. This can really help with overhead.
On the other hand, any Apache processes that are currently tied up w/ existing visitors will not be able to talk to the new ones. So you may have to increase the total number of Apache processes that are available.
In short... it requires tweaking.
you can't control keep-alive behavior in .htaccess
Paste the following code in your .htaccess file:
<ifModule mod_headers.c>
Header set Connection keep-alive
</ifModule>
Then use this website: https://varvy.com/pagespeed/ to check if it's enabled.