Christians Tagebuch: apache

The latest posts in full-text for feed readers.


git-http-backend on Apache 2.4

Moving to a new server, I also had to setup HTTP access for my Git repositories at git.cweiske.de.

My old server was Debian 8 with Apache 2.2, the new one Debian 9 with Apache 2.4. Simply copying the configuration did not work - I got an error:

AH01630: client denied by server configuration: /usr/lib/git-core/git-http-backend

I did not want to make the whole /usr/lib/git-core/ directory executable, but only git-http-backend. At first I tried it with:

<Files "/usr/lib/git-core/git-http-backend">
    Options +ExecCGI
    Require all granted
</Files>

- but that did not work. The documentation about files says:

Directives enclosed in a <Files> section apply to any file with the specified name, regardless of what directory it lies in.

So the correct way was to nest a <Files> tag inside a <Directory> tag:

<Directory "/usr/lib/git-core/">
    <Files "git-http-backend">
        Options +ExecCGI
        Require all granted
    </Files>
</Directory>

Full configuration

This is the full configuration for the virtual host:


    ServerName git.cweiske.de
    HeaderName HEADER
    DocumentRoot /home/cweiske/www/git.cweiske.de/

    Include /etc/apache2/sites-available/cweiske/includes/linkback.conf
    Include /etc/apache2/sites-available/cweiske/includes/letsencrypt-acme-challenges.conf

    SetEnv GITWEB_CONFIG /home/cweiske/www/git.cweiske.de/gitweb.conf
    ScriptAlias /gitweb.cgi /usr/share/gitweb/gitweb.cgi

    #smart http protocol
    # by default allows GET only, not push.
    # we serve it over the same URLs as the normal gitweb URLs!
    SetEnv GIT_PROJECT_ROOT /var/lib/git-public/
    ScriptAliasMatch \
        "(?x)^/(.*git/(HEAD | \
                        info/refs | \
                        objects/(info/[^/]+ | \
                                 [0-9a-f]{2}/[0-9a-f]{38} | \
                                 pack/pack-[0-9a-f]{40}\.(pack|idx)) | \
                        git-(upload|receive)-pack))$" \
        /usr/lib/git-core/git-http-backend/$1

    CustomLog /var/log/apache2/cweiske/git.cweiske.de-access.log combined
    ErrorLog  /var/log/apache2/cweiske/git.cweiske.de-error.log

    SSLEngine On
    SSLCertificateFile /etc/letsencrypt/live/git.cweiske.de/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/git.cweiske.de/privkey.pem

    ServerSignature Off

    
        Options +FollowSymLinks +ExecCGI
	AddHandler cgi-script .cgi
        Require all granted

	DirectoryIndex /gitweb.cgi
	
        RewriteEngine On
	RewriteCond %{REQUEST_FILENAME} !-f
	RewriteCond %{REQUEST_FILENAME} !-d
	RewriteRule ^.* /gitweb.cgi/$0  [L,PT]
    

    
        
            Options +ExecCGI
            Require all granted
        
    

    
    	Require all denied
    
]]>

Published on 2018-12-20 in , ,


Enable .phar handling in your web server

PHP allows us to pack up whole applications in a single .phar file, but no web server software today lets PHP handle .phar files, giving you a download dialog or displaying the text contents of the file.

News about this topic in 2017: Webserver .phar handling lands in distributions.

mod_php on Apache

Debian

Open /etc/apache2/mods-enabled/php5.conf and change the line

]]>

into

]]>

Corresponding bug report and patch: #639268

Fedora

Edit /etc/httpd/conf.d/php.conf and add the line

Corresponding bug report: #1117140

Mac OS X

Open /etc/apache2/other/php5.conf and add the line

AddType application/x-httpd-php .phar

below the similar line ending with .php.

PHP-FPM

nginx

Use the following configuration to make PHP-FPM handle .php and .phar files:

Be aware of PHP bug #67587. You will get an endless redirection loop for all requests with a non-empty PATH_INFO (file.phar/foo). The fix is already committed and will released with PHP 5.6.0, 5.5.15 and 5.4.31.

Published on 2014-07-23 in , ,


Apache: Slow rewrite rule

One online shop at work saw a drastic performance loss after upgrading: Even accessing static .js files took at least 0.7 seconds.

Upon debugging we saw that the slowness went away when we disabled Apache's RewriteEngine. That led us to inspect each RewriteRule, and in the end we found that this one was the troublemaker:

RewriteRule  ^(.*)/(.*){1,15}/(.*)\.html$  http://../$2 [R=301,L]

The second * is the culprit here; it's not needed for the intended function and makes the regex the slower the longer the input URL is.

The totally correct rule would have been:

RewriteRule  ^[^/]+/[^/]{1,15}/[^/]+\.html$  http://../$2 [R=301,L]

Published on 2017-01-09 in ,


SSL certificate chains

SSL certificate verification

Your browser knows a list of Certificate Authorities (CAs) that it trusts; this list is called the "trust store". On Firefox 41 you can find it at Preferences / Advanced / Certificates / View Certificates / Authorities.

When connecting to a web site via HTTPS, the web server sends the public part of the web site's SSL certificate to your browser. The browser then checks if the certificate is signed by one of the CAs in its trust store.

 Browser -----[asks]----> Trust store
           +----------------------+          +-------------+
           |   SSL certificate    |          |Do we trust  |
           |valid for: example.org|          | 0x123456789 |
           |signed by: 0x123456789|          |           ? |
           +----------------------+          +-------------+
]]>

If it finds the certificate in the trust store, all is fine and the green lock icon is shown. If it does not find a trusted CA certificate, a warning is shown:

This Connection is Untrusted

You have asked Firefox to connect securely to example.org, but we can't confirm that your connection is secure.

Normally, when you try to connect securely, sites will present trusted identification to prove that you are going to the right place. However, this site's identity can't be verified.

What Should I Do?

If you usually connect to this site without problems, this error could mean that someone is trying to impersonate the site, and you shouldn't continue.

example.org uses an invalid security certificate.

The certificate is not trusted because the issuer certificate is unknown. The server might not be sending the appropriate intermediate certificates. An additional root certificate may need to be imported.

(Error code: sec_error_unknown_issuer)

What is a SSL certificate chain?

In reality, the web site's certificate will not be signed by the CA's certificate directly.

Web site certificate signing at CAs is done automatically these days. Imagine what happens when the CA's certificate gets stolen - the certificate's new owners would be able to issue certificates for all domain names, and the CA could do nothing against it - except telling browser vendors to remove its certificate from the trust store, which would mean that the CA could close its doors.

Instead, the certificate authority's main certificate (root certificate) is locked away on some offline storage medium in a safe. It was only used to sign some intermediate certificates, which have a limited life span, and which can be distrusted and revoked in case they get compromised.

|valid for: signing      |--->|valid for: signing    |
|signed by: 0x112345678|    |signed by: 0x223456789  |    |in browser trust store|
+----------------------+    +------------------------+    +----------------------+
]]>

Missing links

These intermediate certificates are used to sign web site certificates - but the browsers do not know about them. If your web server only sends out the domain's SSL certificate, the browser will show the "untrusted connection" warning, because it does only see that the certificate is signed by the intermediate certificate - which it does not know anything about it; it cannot make the connection to the CA's root certificate.

The solution to this problem is to send a certificate chain that contains both the web site's certificate as well as the intermediate certificate. With that information, the browser can follow the trust chain from the web site's certificate via the intermediate certificate up to the root certificate which is has in its trust store.

The Mozilla Certificate Authority FAQ writes about this :

Why does SSL handshake fail due to missing intermediate certificate?

This type of error indicates that the web server is incorrectly configured. The web server itself has to send the intermediate certificate along with their own SSL cert to complete the certificate chain. Only root certificates or trust anchors are included in the Mozilla root store.

Web server configuration

Apache

Since Apache 2.4.8 you can use the SSLCertificateFile directive to point to a file that contains both the web site's certificate and the intermediate certificate. Versions lower than 2.4.8 have to use the SSLCertificateChainFile directive.

Simply concatenate first the website certificate, then the intermediate certificate into the file:

$ cat /path/to/example.org.pem > /path/to/example.org-chain.pem
$ cat /path/to/intermediate.pem >> /path/to/example.org-chain.pem

Then add the following code to your virtual host configuration:

SSLCertificateFile    "/path/to/example.org-chain.pem"
SSLCertificateKeyFile "/path/to/example.org.key"

Published on 2015-10-16 in , ,


Apache: Automatically convert rST to HTML

At work, our intranet search engine indexes meeting minutes and documentation we wrote in reStructuredText format. Finding and clicking such files results in plain text being shown in the browser, not always easy to read.

My goal last friday was to make Apache automatically convert .rst files to HTML when a browser accesses the file.

Setup

The python-docutils package contains rst2html which does what I wanted: Read rST from stdin and write HTML to stdout.

Apache on the other hand has mod_ext_filter which was made for piping content through an external tool. The setup was easy:


    SetOutputFilter rst2html

]]>

This works fine but gives everyone HTML, even the tools that only understand plain text. Luckily, we can detect if a HTTP client supports HTML by reading the Accept header. mod_ext_filter is able to conditionally turn on filters based on environment variables, and with mod_setenvif we have a facility to set environment variables based on HTTP headers:


    SetEnvIf Accept text/html supports_html
    SetOutputFilter rst2html

]]>

The HTTP support check is very basic; we do not parse quality values at all. It suffices for now, but I'd also like a better solution.

If you know a better solution, please send a mail.

Published on 2014-10-27 in ,


Apache: Unable to open logs

Today at work I needed to add a SSLProxyEngine directive to my Puppet server configuration.

Unfortunately the puppetlabs/apache module does not support this directive without enabling SSL on the vhost, so I had to manually generate the config file.

After an hour, I had the configuration in place but starting Apache gave me the following output:

$ /etc/init.d/apache2 restart
[....] Restarting web server: apache2no listening sockets available,
shutting down Unable to open logs
Action 'start' failed.
The Apache error log may have more information.
 failed!

The log directory /var/log/apache2/ was really not owned by www-data, so I fixed that. I tried to fix many more things, and finally strace'ed the apache process: Still the same error message, but not a single access to a log directory or file.

The real cause of the problem was that my apache configuration did not include a Listen directive, which meant that my vhost, although defined, was not used.

Still: a message Unable to open logs is hardly proper for a missing Listen line in the config.

Published on 2014-05-27 in , ,


Using SSL Client Certificates with PHP

Imagine you visit a web site and are instantly and automatically logged in.

Without filling in username and password in a login form.
Without filling the OpenID field and clicking 3 times.
Without clicking the button of your browser's autologin extension.
Without a single cookie sent from your browser to the server.

Yet, you authenticate yourself at and get authorized by the web server.


Yes, this is possible - with SSL client certificates. I use them daily to access my self-hosted online bookmark manager and feed reader.

During the last weeks I spent quite some time implementing SSL Client Certificate support in SemanticScuttle, and want to share my experiences here.

A bit about client certificates

Client certificates are, as the name indicates, installed on the client - that is the web browser - and transferred to the server when the server requests them and the user agrees to send it.

Chromium asks for a client certificate

The certificates are issued by a Certificate Authority (CA), that is a commercial issuer, a free one like CAcert.org, your company or just you yourself, thanks to the power of the openssl command line tool (or a web frontend like OpenCA).

The CA is responsible for giving you a client certificate and a matching private key for it. The client certificate itself is sent to the server, while the private key is used to sign the request. This signature is verified on the server side, so the server knows that you are really the one that the certificate belongs to.

Note that client certificates can only be used when accessing the server with HTTPS.

The certificates also have an expiration date, after which they are not valid anymore and need to be renewed. When implementing access control, we need to take this into account.

Server side

Your web server must be configured for HTTPS, which means you need a SSL server certificate. Get that working first, before tackling the client certificates.

Until some years ago, there was a rule "one port, one certificate". You could only run one single HTTPS website on a single port on the server, except in certain circumstances. The HTTPS port is 443, and using another port for the next SSL-secured domain means to get problems with firewalls and much harder linking - just using "https://example.org/" does not work anymore, you need some port number in it which you - as a visitor - don't know in advance.

The "special circumstances" were wildcard domains and the assumption that you only wanted to secure subdomains: app1.example.org, app2.example.org etc.

The problems lie in the foundations of SSL: SSL certificate exchange is being made before any HTTP protocol data are submitted, and since the certificate contains the domain name, you cannot deliver the correct certificate when you have several SSL hosts on the same port.

Server Name Indication

Fast-forward to now. We have SNI which solves the problem and gives nobody an excuse anymore to not have SSL secured domains.

With SNI, the browser does send (indicate) the host name it wants to contact during certificate exchange, which causes the server to return the correct certificate.

All current browsers on current operating systems support that. Older systems with Windows XP or OpenSSL < 0.98f do not support it and will get the certificate of the first SSL host.

Obtaining a server certificate

I assume you're going to get the certificate from CAcert.

First, generate a Certificate Signing Request with the CSR generator. Store the key file under

/etc/ssl/private/bookmarks.cweiske.de.key

Use the the .csr file and the CAcert web interface to generate a signed certificate. Store it as

/etc/ssl/private/bookmarks.cweiske.de-cacert.pem

Now fetch both official CAcert certificates (root and class 3) and put both together into

/etc/ssl/private/cacert-1and3.crt

Server configuration

A basic virtual host configuration with SSL looks like this:


    ServerName bookmarks.cweiske.de

    LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
    CustomLog /var/log/apache2/access_log vcommon

    VirtualDocumentRoot /home/cweiske/Dev/html/hosts/bookmarks.cweiske.de
    
        AllowOverride all
    

    SSLEngine On
    SSLCertificateFile /etc/ssl/private/bookmarks.cweiske.de-cacert.pem
    SSLCertificateKeyFile /etc/ssl/private/bookmarks.cweiske.de.key

    SSLCACertificateFile /etc/ssl/private/cacert-1and3.crt
]]>

Apart from that, you might need to enable the SSL module in your webserver, i.e. by executing

$ a2enmod ssl

Restart your HTTP server. You should be able to request the pages via HTTPS now.

Make the server request client certificates

A web server does not require any kind of client certificate by default; this is something that needs to be activated.

The client certs may be required or optional, which leaves you the comfortable option to let users login normally via username/password or with SSL certificates - just as they wish.

Modify your virtual host as follows:



    SSLVerifyClient optional
    SSLVerifyDepth 1
    SSLOptions +StdEnvVars
]]>

There are several options you need to set:

SSLVerifyClient optional

You may choose optional or require here. optional asks the browser for a client certificate but accepts if the browser (the user) does choose not to send any certificate. This is the best option if you want to be able to login with and without a certificate.

The setting require makes the web server terminate the connection when no client certificate is sent by the browser. This option may be used when all users have their client certificate set.

If you want to allow self-signed certificates that are not signed by one of the official CAs, use SSLVerifyClient optional_no_ca.

SSLVerifyDepth 1

Your client certificate is signed by a certificate authority (CA), and your web server trusts the CA specified in SSLCACertificateFile. CA certificates itself may be signed by another authority, i.e. like

CAcert >> your own CA >> your client certificate

In this case, you have a higher depth. For most cases, 1 is enough.

SSLOptions +StdEnvVars

This makes your web server pass the SSL environment variables to PHP, so that your application can detect that a client certificate is available and read its data.

In case you need the complete client certificate, you have to add +ExportCertData to the line.

This multiplies the size of data exchanged between the web server process and PHP, which is why it's deactivated most times.

If you restart your web server now, it will request a client certificate from you.

It may happen that the browser does not pop up the cert selection dialog. The web server may send a list of CAs that it considers valid to the browser. If the browser does not have a certificate from one of those CAs, it does not display the popup.

You can fix this issue by setting SSLCADNRequestFile or SSLCADNRequestPath .

Thanks to Gerard Caulfield for bringing this to my attention.

Logging

With Apache, you may use SSL client certificate details in your log files: Create a new log format and use the SSL client environment variables :

%{SSL_CLIENT_S_DN_Email}e %{SSL_CLIENT_M_SERIAL}e

Thanks to Hans Schou for this idea.

Adding client certificate support to your PHP application

Let's collect the requirements for SSL client cert support in a typical PHP application:

  1. Users get automatically logged in when they visit the page. To be able to do that, we need to know that a certificate belongs to a certain user account.
  2. Register a SSL certificate with an existing account. You also want to let users register multiple certificates because they probably have different ones at home and at work.
  3. When registering a new account, automatically associate the client certificate with the new account. This is the most unobtrusive way of getting clients to use SSL certificates.
  4. Let users remove associated client certificates. Their computer may be compromised or the certificate has just been lost (yes, you can revoke certificates, but that's another story).
  5. Don't bitch when users renew their certificate. Log them in as before.

Accessing certificate data

When a client certificate is available, the $_SERVER variable contains a bunch of SSL_CLIENT_* variables .

$_SERVER['SSL_CLIENT_VERIFY'] is an important one. Don't use the certificate if it does not equal SUCCESS. When no certificate is passed, it is NONE.

Another important variable is SSL_CLIENT_M_SERIAL with the serial that uniquely identifies a certificate from a certain Certificate Authority.

All variables with SSL_CLIENT_I_* are about the issuer, that is the CA. SSL_CLIENT_S_* are about the "subject", the user that sent the client certificate.

SSL_CLIENT_S_DN_CN for example contains the user's name - "Christian Weiske" in my case - which can be used during registration together with SSL_CLIENT_S_DN_Email to give a smooth user experience.

Always remember that you need to configure your web server to pass the variables to your PHP process.

Certificate identification

Associating a user account with a client certificate is brutally possible by just enabling +ExportCertData and storing the client certificate in your user database.

This is bad for two reasons:

  • When the certificate expires and gets renewed, the user cannot login anymore.
  • You need to pass more data to each PHP process and store more data than needed in your user database.

According to the PostgreSQL manual ,

The combination of certificate serial number and certificate issuer is guaranteed to uniquely identify a certificate (but not its owner — the owner ought to regularly change his keys, and get new certificates from the issuer).

So we can use SSL_CLIENT_M_SERIAL together with SSL_CLIENT_I_DN to uniquely identify a certificate, without storing its as a whole.

A "renewed" certificate is in reality a new certificate with a new serial number. Thus the serial changes after renewal.

The combination of issuer + SSL_CLIENT_S_DN_Email should be more stable; letting the user login even when he renewed his certificate - but only if he didn't change his email address.

SemanticScuttle uses the following code to check if a certificate is valid:

Storing user certificates

While you can calculate a hash over serial and issuer DN, it's better to store each of the values separately in the database. This has the advantage that you may display them in the user's certificate list, and allow him to identify the cert later on.

Here is the database table structure of SemanticScuttle:

Apart from the two required columns, we also store the subject's name and email to again allow better certificate identification:

Certificate list in SemanticScuttle
Certificate list in SemanticScuttle

Registering certificates

The user needs to be able to manually register his current certificate with the application. Automatic registration without confirmation may not be desired, so the best is to just drop that idea.

SemanticScuttle offers a "register current certificate" button on the user profile page:

No certificates in SemanticScuttle
No certificates and a registration button in SemanticScuttle

Another option that improves usability is to associate the client certificate upon user registration. There should be a checkbox which alerts the user of that detail and allows him to disable it.

The following code registers the current certificate with the user's account in SemanticScuttle:

getTableName()
    . ' '. $this->db->sql_build_array(
        'INSERT', array(
        'uId'               => $userId,
        'sslSerial'         => $_SERVER['SSL_CLIENT_M_SERIAL'],
        'sslClientIssuerDn' => $_SERVER['SSL_CLIENT_I_DN'],
        'sslName'           => $_SERVER['SSL_CLIENT_S_DN_CN'],
        'sslEmail'          => $_SERVER['SSL_CLIENT_S_DN_Email']
    )
);
]]>

You might want to store the certificate's expiration date and automatically remove them when it is reached.

OCSP checks

The Online Certificate Status Protocol allows you to check if a certificate has been revoked. Revocation is useful if your certificate has been compromised somehow; it could be stolen or the password gotten public.

A certificate contains information about the CA's OCSP server, you can view it by running

$ openssl x509 -text -in /path/to/cert.pem
...
            Authority Information Access:
                OCSP - URI:http://ocsp.cacert.org
...

This information is not available in the standard SSL environment variables but need to be extracted from the certificate data, which means that +ExportCertData needs to be enabled.

PHP's OpenSSL extension does not have a method to generate, send or evaluate OCSP requests, so checking the certificate is only possible with the openssl ocsp commandline tool or by implementing it yourself.

The command line tool is easy to use after you stored the client certificate on disk. At first we need the URL

$ openssl x509 -in /tmp/client-cert.pem -noout -text |grep OCSP
    OCSP - URI:http://ocsp.cacert.org

Now that the URL is ours, it can be queried:

$ openssl ocsp -CAfile /etc/ssl/private/cacert-1and3.crt\
 -issuer /etc/ssl/private/cacert-1and3.crt\
 -cert /tmp/client-cert.pem\
 -url http://ocsp.cacert.org

Example output of a revoked certificate:

At the time of writing, there sadly does not seem to be any PHP library that eases verifying SSL client certificates.

Let the HTTP server do the work

Apache since version 2.3 is able to do the OCSP checks itself if you activate the SSLOCSPEnable option.

Published on 2011-06-03 in , , , , , ,


Relative .htpasswd path

Using Apache's HTTP Basic authentication is a quick and easy way to protect your website with username and passwords:

AuthType Basic
AuthName "Please enter username and password"
AuthUserFile /var/www/hostname/.htpasswd
Require valid-user

The problem I have is that AuthUserFile is not relative to the virtual host's document root, but to the server root, which is /etc/apache2/ on Debian and Ubuntu.

Putting .htpasswd files into /etc/apache2/ is weird (and requires root access), and the only other option is to make the AuthUserFile path absolute, e.g. /var/www/hostname/.htpasswd.

Absolute paths are not portable across servers - on my dev machine, the path is /home/cweiske/Dev/html/hostname/.htpasswd, while on the server in the data center it is /home/cweiske/www/hostname/.htpasswd.

IfDefine to the rescue

Luckily, Apache provides the IfDefine directive. It's like an if statement in a programming language, but is limited to parameters that are passed to the httpd process as command line options, e.g. /usr/sbin/apache2 -Dfoo.

Now Apache is started via an init script, not via command line. Modifying the init script is also not something you want since it'll get overwritten with the next package update.

After digging around the apache2 init and configuration files, I found /etc/apache2/envvars: It allows you to set environment variables that get passed to the apache process on startup. One of these variables is APACHE_ARGUMENTS which apache2ctl passes as command line argument to the httpd process.

The solution

So the solution I am using now is the following. On my development machine, I define a development variable and activate the password check if that is not set.

I do not define a live variable because I don't always have access to the server configuration, and it also has the advantage that the password protection does still work when the server config gets reset somehow.

/etc/apache2/envvars

export APACHE_ARGUMENTS=-Ddevelopment

.htaccess


    AuthType Basic
    AuthName "Please enter username and password"
    AuthUserFile /var/www/hostname/.htpasswd
    Require valid-user

]]>

Published on 2012-05-30 in , , ,


Web server log stats for multiple vhosts

Our Apache web server handles more than two dozen virtual hosts, and we are all keen to see statistics about our visitors: From where they are, which pages are most frequented, which search terms are used to find us and so on. A nice tool to analyze the log files and generate HTML statistic pages from them is AWStats.

The stock AWStats on Debian is unfortunately only useful for a single vhost. It further does not keep the full historic data (detailled montly stats) and does not generate index files for them (since it doesn't need to).

To help with that situation, I built my awstats-helper scripts. Written in PHP, they do the following things:

  • Generate detailled monthly statistics for each vhost
  • Keep an archive of the monthly statistics
  • Generate an index page for each vhost so you can access the different months easily
  • Generate an index page for all vhosts for easy navigation between vhosts

Installation

$ cd /usr/local/src
$ git clone git://git.cweiske.de/awstats-helper.git
$ cd awstats-helper

Setup

First, copy config.php.dist to config.php and adjust it. Usually you only need to change the htmldir setting and point it to the directory you want the HTML files generated in.

Then create a awstats config file for each vhost in /etc/awstats/ and call it awstats.foo.example.org.conf. Put the following lines in it:

Include "/etc/awstats/awstats.conf"
LogFile="/var/log/apache2/foo.example.org-access.log"
SiteDomain="foo.example.org"
DefaultFile=""

Now the initial setup is done and we can run the initial data collection:

$ php update-sites.php
$ php create-historic.php

If that worked out, add two cronjobs: One to generate today's month's data every couple of hours, and one to finish last month's data at the next month:

$ crontab -e
# enter the following:
5 */6 * * * php /usr/local/src/awstats-helper/update-sites.php
5   3 1 * * php /usr/local/src/awstats-helper/update-lastmonth.php

This updates the current data every 6 hours and updates last month's data 3:05 on the first of each month.

That's it! Happy analyzing.

Published on 2011-12-07 in , , ,


Reverse proxy with Apache

Sometimes applications provide a HTTP interface but run standalone without a dedicated web server software like Apache or nginx. If you're already running such a HTTP server, port 80 is already in use and cannot be used by the application.

Using non-standard ports to expose the application to the world is possible, but makes firewall management harder and prevents some people from using your service because their company's firewall does not allow the non-standard port.

The applications often do not provide HTTPS, authentication or name based hosting support, so there are many reasons to put them behind a real web server that has everything.

Setup

What we need is the main web server to tunnel the HTTP requests to the applications and send the responses back to the visitor.

At first, enable the HTTP proxy module in Apache (example for Debian):

$ a2enmod proxy_http

Then add a virtual host with the following configuration:


    ServerName application.example.org

    ProxyRequests Off
    
        Order deny,allow
        Allow from all
    
    ProxyPass / http://localhost:8082/
    ProxyPassReverse / http://localhost:8082/

    CustomLog /var/log/apache2/application.example.org-access.log combined
    ErrorLog  /var/log/apache2/application.example.org-error.log

]]>

Restart your web server. Fin.

You just set up a reverse proxy that tunnels client requests to http://application.example.org to the application listening on the local port 8082, and back. The application on port 8082 may be listening on the loopback interface only for more security.

Published on 2011-12-05 in , ,