Apache¶
Description
Tips and guides for hosting Plone with Apache web server.
- Introduction
- Installing Apache front-end for Plone
- Procedure to restart Apache in production environment
- www-redirects
- Migration redirects
- Proxying other site under Plone URI space
- Redirecting certain URIs to old site
- Virtual hosting Apache configuration generator
- Caching images
- Testing cache headers
- Flushing cache
- Custom 500 internal error page
- Load balanced Apache virtual host configuration
Introduction¶
Here are useful information and snippets when hosting Plone behind Apache.
Installing Apache front-end for Plone¶
Apache runs on port 80. Plone runs on port 8080. Apache accepts all HTTP traffic to your internet domain.
Here are quick instructions for Ubuntu / Debian.
Install required software:
sudo apt-get install apache2
sudo a2enmod rewrite
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod headers
sudo /etc/init.d/apache2 restart
Add virtual host config file
/etc/apache2/sites-enabled/yoursite.conf
. Assuming Plone is your site id in Zope
Management Interface (capital lettering do matter) and
your domain name is
yoursite.com
(note with or without www matters, see below):
UseCanonicalName On
NameVirtualHost *
<VirtualHost *>
ServerAlias yoursite.com
ServerSignature On
Header set X-Frame-Options "SAMEORIGIN"
Header set Strict-Transport-Security "max-age=15768000; includeSubDomains"
Header set X-XSS-Protection "1; mode=block"
Header set X-Content-Type-Options "nosniff"
Header set Content-Security-Policy-Report-Only "default-src 'self'; img-src *; style-src 'unsafe-inline'; script-src 'unsafe-inline' 'unsafe-eval'"
ProxyVia On
# prevent your web server from being used as global HTTP proxy
<LocationMatch "^[^/]">
Deny from all
</LocationMatch>
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
RewriteEngine on
RewriteRule ^/(.*) http://localhost:8080/VirtualHostBase/http/yoursite.com:80/Plone/VirtualHostRoot/$1 [P,L]
</VirtualHost>
<VirtualHost *>
ServerAlias *
ServerRoot /var/www
ServerSignature On
</VirtualHost>
Eventually you have one virtual host configuration file per one domain on your server.
Restart apache:
sudo apache2ctl configtest
sudo apache2ctl restart
Check that Plone responds:
http://yoursite.com:8080/Plone
Check that Apache responds:
http://yoursite.com
If everything is good then your Plone site properly configured using Apache front-end.
Content Security Policy (CSP) prevents a wide range of attacks, including cross-site scripting and other cross-site injections, but the CSP header setting may require careful tuning. To enable it, replace the Content-Security-Policy-Report-Only by Content-Security-Policy. The example above works with Plone 4.x (including TinyMCE) but it very wide. You may need to adjust it if you want to make CSP more restrictive or use additional Plone Products. For more information, see
For an SSL configuration, just modify the rewrite rule from:
RewriteRule ^/(.*) http://localhost:8080/VirtualHostBase/http/yoursite.com:80/Plone/VirtualHostRoot/$1 [P,L]
to:
RewriteRule ^/(.*) http://localhost:8080/VirtualHostBase/https/yoursite.com:443/Plone/VirtualHostRoot/$1 [P,L]
Inside an SSL-enabled Apache virtual host definition.
Procedure to restart Apache in production environment¶
You might share the same Apache web server across several production sites. You don't want to hinder the performance of the other sites when doing Apache configuration changes to one site.
The correct procedure to restart Apache is (on Ubuntu/Debian Linux)
# Check that config files are working after editing them
apache2ctl configtest
# Let Apache finish serving all the on-going requests before
# restarting worker processes
apache2ctl graceful
www-redirects¶
If you wish to force people to use your site with or without www prefix you can use the rules below. Note that setting this kind of rule is very useful from the search engine optimization point of view also.
Example in <VirtualHost> section to redirect www.site.com -> site.com:
<VirtualHost 127.0.0.1:80>
ServerName site.com
ServerAlias www.site.com
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.site\.com [NC]
RewriteRule (.*) http://site.com$1 [L,R=302]
</IfModule>
Example in <VirtualHost> section to redirect site.com -> www.site.com:
<VirtualHost 127.0.0.1:80>
ServerName site.com
ServerAlias www.site.com
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^site\.com [NC]
RewriteRule (.*) http://www.site.com$1 [L,R=302]
</IfModule>
Redirecting all the pages to the root of a new site:
RewriteEngine On RewriteRule (.*) http://www.newsite.com [L,R=302]
Migration redirects¶
To redirect traffic from all pages permanently (301) to the landing page of a new site:
RewriteEngine On
RewriteRule (.*) http://collective-docs.readthedocs.org/ [L,R=301]
Proxying other site under Plone URI space¶
The following rule can be used to put a static web site to sit in the same URI space with Plone. Put these rules before VirtualHost ProxyPass.
Examples:
ProxyPass /othersite/ http://www.some.other.domain.com/othersite/
ProxyPassReverse /othersite/ http://www.some.other.domain.com/othersite/
Reverse proxy host¶
By default, host name is correctly delivered from Apache to Plone. Otherwise you might see all your HTTP requests coming from localhost, Apache.
You need:
ProxyPreserveHost On
For more information, see
Redirecting certain URIs to old site¶
This is useful if you migrate to a Plone from some legacy technology and you still need to have some part of the URI space to point to the old server.
- Create alternative domain name for the existing old site (e.g. www2)
- Modify Apache configuration so that URLs still being used are redirected to the old server with alternative name, Put in this rewrite
<location /media>
RedirectMatch /media/(.*)$ http://www2.site.fi/media/$1
</location>
Caching images¶
You can force caching of content types on apache
First you need to enable Apache modules:
* mod_cache, mod_diskcache
On Debian this is:
sudo a2enmod
Then you can add to your virtual host configuration:
# Disk cache configuration
CacheEnable disk /
CacheRoot "/var/cache/yourorganization-production"
CacheLastModifiedFactor 0.1
#CacheDefaultExpire 1
#CacheMaxExpire 7200
CacheDirLength 2
Then install go to Cache Configration (Plone 4.1+) and configure the caching options.
Unsetting language cookie for media content¶
Media like content can confuse and break language selector on multilingual sites.
By default, Plone sets I18N_LANGUAGE cookie on
- All page requests
- All ATImage requests
Even if images are often language neutral, they still set I18N_LANGUAGE cookie on HTTP response. This is problematic if image gets cached and the user switches the language using the language selector. This happens when you enforce caching using Apache level rules (instead of using Products.CacheSetup or similar product). The user browsers received cached HTTP response image for the image and it contains Set-Cookie: I18N_LANGUAGE header for the wrong language -> browser language choice by cookie is reset.
A workaround is to force language cookie off from media like content:
SetEnvIfNoCase Request_URI "\.(?:gif|jpe?g|png|css|js)$" language-neutral
SetEnvIfNoCase Request_URI "image_preview(/)$" language-neutral
SetEnvIfNoCase Request_URI "image_large(/)$" language-neutral
SetEnvIfNoCase Request_URI "image_small(/)$" language-neutral
SetEnvIfNoCase Request_URI "image_thumb(/)$" language-neutral
SetEnvIfNoCase Request_URI "image_mini(/)$" language-neutral
SetEnvIfNoCase Request_URI "image*$" language-neutral
SetEnvIfNoCase Request_URI "navImage_small(/)$" language-neutral
# Any URL having image in it
SetEnvIfNoCase Request_URI "^.*image*" language-neutral
Header unset Set-Cookie env=language-neutral
Testing cache headers¶
Use UNIX wget command. -S flag will display request headers.
Remember to do different request for HTML, CSS, JS and image payloads - the cache rules might not be the same.
HTTP example:
cd /tmp
wget --cache=off -S http://production.yourorganizationinternational.org/yourorganizationlogotemplate.gif
HTTP request sent, awaiting response...
HTTP/1.1 200 OK
Date: Tue, 09 Mar 2010 12:33:26 GMT
Server: Apache/2.2.8 (Ubuntu) DAV/2 SVN/1.4.6 mod_python/3.3.1 Python/2.5.2 PHP/5.2.4-2ubuntu5.4 with Suhosin-Patch mod_ssl/2.2.8 OpenSSL/0.9.8g
Last-Modified: Wed, 25 Nov 2009 06:51:41 GMT
Content-Length: 4837
Via: 1.0 production.yourorganizationinternational.org
Cache-Control: max-age=3600, public
Expires: Tue, 09 Mar 2010 13:02:29 GMT
Age: 1857
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: image/gif
Length: 4837 (4.7K) [image/gif]
Saving to: `yourorganizationlogotemplate.gif.14'
HTTPS example:
cd /tmp
wget --cache=off --no-check-certificate -S https://production.yourorganizationinternational.org/
Custom 500 internal error page¶
To make you look more pro when you update the server or Plone goes down
Load balanced Apache virtual host configuration¶
This complex config example includes
- HTTPS and SSL certificate set-up
- Load balancing using ZEO front-ends and Apache load balancer module
- Apache disk cache. This should provide static resource caching w/HTTPS support if you are using plone.app.caching.
- https://httpd.apache.org/docs/2.2/caching.html
See
More information about how to set a sticky session cookie if you need to support Zope sessions in your code
Example:
<VirtualHost 123.123.123:443>
ServerName production.yourorganization.org
ServerAdmin rocks@mfabrik.com
SSLEngine On
SSLCertificateFile /etc/apache2/ssl-keys/yourorganization.org.cer
SSLCertificateKeyFile /etc/apache2/ssl-keys/yourorganization.org.key
SSLCertificateChainFile /etc/apache2/ssl-keys/InstantValidationCertChain.crt
LogFormat combined
TransferLog /var/log/apache2/production.yourorganization.org.log
<IfModule mod_proxy.c>
ProxyVia On
# prevent the webserver from being used as proxy
<LocationMatch "^[^/]">
Deny from all
</LocationMatch>
</IfModule>
# Balance load between 4 ZEO front-ends
<Proxy balancer://lbyourorganization>
BalancerMember http://127.0.0.1:13001/
BalancerMember http://127.0.0.1:13002/
BalancerMember http://127.0.0.1:13003/
BalancerMember http://127.0.0.1:13004/
</Proxy>
# Note: You might want to disable this URL of being public
# as it can be used to access Apache live settings
<Location /balancer-manager>
SetHandler balancer-manager
Order Deny,Allow
# Your trusted IP addresses
Allow from 123.123.123.123
</Location>
ProxyPass /balancer-manager !
ProxyPass / balancer://lbyourorganization/http://localhost/VirtualHostBase/https/production.yourorganization.org:443/yourorganization_plone_site/VirtualHostRoot/
ProxyPassReverse / balancer://lbyourorganization/http://localhost/VirtualHostBase/https/production.yourorganization.org:443/yourorganization_plone_site/VirtualHostRoot/
# Disk cache configuration
CacheEnable disk /
# Must point to www-data writable directly which depends on OS
CacheRoot "/var/cache/yourorganization-production"
CacheLastModifiedFactor 0.1
# Debug header flags all requests coming from this server
Header append X-YourOrganization-Production yes
</VirtualHost>