Often during development, I want to expose a web application for review to a limited set of people. The easiest way to do this is to impose a password when these users connect to the application. Most often, I configure a virtual host for the application in Apache-2.4 and set it up with basic HTTP authentication using passwords.

First, create the password file using the htpasswd.exe utility, and save it under /conf as users.pwd (or whatever you want). Then for the application’s virtual host, setup password protection:

LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule authn_file_module modules/mod_authn_file.so
# Password-protected resources
<VirtualHost *:81>
    # Secure access
    <Location /.*>
        AuthType Basic
        AuthName "Protected Sites"
        AuthBasicProvider file
        AuthUserFile "G:\Apache2.4\conf\users.pwd"
        Order Deny,Allow
        Satisfy All
        Deny from all
        Require valid-user
    </Location>

    # Application
    ProxyPass / http://localhost:8091/
    ProxyPassReverse / http://localhost:8091/
</VirtualHost>

Restart Apache for changes to take effect. Access to :81 applications will pop-up a password dialog for the client.

References:

* http://httpd.apache.org/docs/2.4/programs/htpasswd.html
* http://httpd.apache.org/docs/2.4/howto/auth.html
* http://httpd.apache.org/docs/2.4/mod/mod_auth_basic.html
* http://httpd.apache.org/docs/2.4/mod/mod_authn_file.html

It should go without mention that this is an inherently insecure way of executing scripts, but there are situations when it is the most convenient, without having to build elaborate web applications that handle scripting (or write your scripts in PHP). For instance, this is how I execute build jobs internally from other web applications elsewhere on my network. My test/build environment is automated using Perl. With that, though, I have a strict security policy in place on the virtual host to prevent misuse.

RewriteEngine On
RewriteRule "^/scripts/([^./]*)\.html(.*)" "/build_scripts/$1.pl \"$2\"" [PT]

So if I were to call https://strive-ltd.com:987/scripts/build.htm?id=123&version=4567, the system would execute the script build.pl under an imaginary /build_scripts/ directory, passing it the query string.

You may come across those rare times when you might want to ensure that various requests arriving on a server port are all routed to the same application internally. It may be that you have exposed multiple ports (say, one for internal users and another for external users) or you want to a “catch-all” situation on your default port (including capturing arbitrary subdomains).

You can address this need by on Apache HTTP Server 2.4 by redirecting the requests to a specific host:

RewriteEngine On
RewriteCond "%{HTTP_HOST}"   "!^www.strive-ltd.com"        [NC,OR]
RewriteCond "%{SERVER_NAME}" "!^www.strive-ltd.com"        [NC]
RewriteRule "(.*)"           "http://www.strive-ltd.com$1" [R]

It is common practice to refer to other websites’ resources on your own website, usually images, video, and audio. But if you have proprietary resources or don’t want to assume the bandwidth overhead of hosting them for other websites, you can block that activity. Simply direct the virtual host to reject requests for such resources unless they are requested from your own domain (presumably from your pages).

Here’s an example for blocking the use of images except if from my own domain, using the Apache HTTP Server.

RewriteEngine On
RewriteCond "%{HTTP_REFERER}" !=""
RewriteCond "%{HTTP_REFERER}" "!^http(s)*://(.+\.)*strive-ltd.com/.*$" [NC]
RewriteRule "\.(jpg|gif|png)$ - [F]

The only risk is blocking valid requests from clients that have not set their referer header.

This strategy is obviously not foolproof: it does not prevent the images from being downloaded and used apart from your website. Once the page with the images is viewed, they can be recovered from the computer’s internet cache or saved them from your pages locally quite easily. But at least it shifts the intent and bandwidth usage to whoever chooses to use them otherwise.

Supposing you have one IP address and one web-accessible port (80), and want to service multiple websites from it. To wit, I want to provide HTTP access SVN (under the /svn context) and phpMyAdmin (under the /phpmyadmin context) on the IP/port I have exposed on my network. phpMyAdmin can be run by Apache-2.4 itself, but SVN is run on another machine on the network. So how do I configure Apache for this goal?

Enable the appropriate modules on the Apache server:

# Enable the proxy_module, rewrite_module and proxy_http_module
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Setup the (default) virtual host to proxy the web applications of interest:

<VirtualHost *:80>
    # SVN
    ProxyPass /svn http://workhorse:8081/svn
    ProxyPassReverse /svn http://workhorse:8081/svn

    # phpMyAdmin
    ProxyPass /phpmyadmin !
    Alias /phpmyadmin "G:\phpMyAdmin"
    <Directory "G:\phpMyAdmin">
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

So from my given domain, say strive-ltd.com, I can access SVN via strive-ltd.com/svn and phpMyAdmin via strive-ltd.com/phpmyadmin. Simple proxying allows me to share the same port among various websites by name.

References

* http://httpd.apache.org/docs/2.4/mod/mod_alias.html
* http://httpd.apache.org/docs/2.4/mod/mod_proxy.html

With increased traffic and activity on your Apache HTTP Server, you will notice that logs begin getting huge. Very large log files can become a performance bottleneck, so it is recommended to rotate them. My fastest growing log is the access log, and here is how I configured it for daily rotation in httpd.conf:

CustomLog "|bin/rotatelogs.exe -l logs/access-%Y.%m.%d.log 86400" combined

This custom log directive instructs Apache to create a new log everyday for logging server access, using a default logging pattern.

On a local network, you can create or modify files directly on another computer if their parent folders are shared over the network. You can achieve the same behavior over the internet (on a remote web server) by using WebDAV, an extension of the HTTP specification.

On my network, I have used this technology for a “download folder” where I archive all kinds of files I download from the internet and want accessible on multiple computers. Normally, I would use Dropbox or other cloud storage options (which, by the way, use this technology themselves behind the scenes). Enabling WebDAV on my internal web server requires no third-party allegiances, and allows me to access the files over HTTP from any of my Internet-enabled devices.

Here’s how to enable WebDAV on Apache HTTP Server 2.4:

[1] Assuming you have installed Apache HTTPD Server at G:\Apache2.4, create a directory that will be publicly exposed for webdav operations, such as G:\Apache2.4\htdocs\public_files.

[2] Create a user password file at G:\Apache2.4\conf\users.passwords with syntax. The format of the password file is “<username> <password>” lines for each user you want to access the directory.

[3] Uncomment the mod_dav modules in httpd.conf, and ensure that the actual .so files exist.

LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule dav_lock_module modules/mod_dav_lock.so

[4] Declare the DAV usage at bottom, set these directives.

<IfModule dav_lock_module>
    DavLockDB "G:\Apache2.4\modules\davdb"
</IfModule>
<Directory "G:\Apache2.4\htdocs\public_files">
    Require all granted
    Dav On
    AuthType Basic
    AuthName DAV
    AuthUserFile users.passwords
</Directory>

[5] Restart Apache, and ensure no errors occur (check the logs).

[6] You will need a WebDAV client such as CarotDAV (http://rei.to/carotdav_en.html). You can discover other clients at https://secure.cloudsafe.com/pages/topics_clients.html, which has more reviews of WebDAV clients. My general observation is that this whole setup works only for small files (less than 50MB), but I believe there is a way to change that configuration.

References:

* http://en.wikipedia.org/wiki/WebDAV
* http://svnbook.red-bean.com/en/1.7/svn.webdav.basic.html

All web applications that I build these days will display the build/version information in the footer or a release page. The build number plugin allows me to avail the source code version to your applications at build time dynamically.

To use the plugin, configure it in Maven:

    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>buildnumber-maven-plugin</artifactId>
        <version>1.0</version>
        <executions>
            <execution>
                <phase>initialize</phase>
                <goals>
                    <goal>create</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <doCheck>false</doCheck>
            <doUpdate>false</doUpdate>
            <timestampFormat>{0,date,yyyy.MM.dd}</timestampFormat>
        </configuration>
    </plugin>

Then set a Maven property to hold the build/version information that can be used during build.

    <properties>
        <build.version>Build#${buildNumber}, Version#${project.version} (${timestamp})</build.version>
    </properties>

At build time, the property “build.version” will contain something similar to “Build#5, Version#1.1-SNAPSHOT (2011.08.30)” where build# is the current Subversion SVN version, version# is the Maven version, and the date of build in parentheses.

I usually pass the property right on to the web context so that it can be used in presentation logic.

References:

* http://mojo.codehaus.org/buildnumber-maven-plugin/usage.html

I really do not understand why some programmers still use System.out and System.err in production code, especially when their applications are not interactive or use a console display. What use is that?

For most Java applications, there is a myriad of logging frameworks. I prefer Log4J though, for how straight-forward and simple it is to use. Here’s how to integrate it:

    1. Add the logger dependency to your Maven POM:
          <dependency>
              <groupId>log4j</groupId>
              <artifactId>log4j</artifactId>
              <version>1.2.16</version>
          </dependency>
    2. Create a “log4j.properties” in src/main/resources (or wherever it’ll end up in your classpath), and add the following:
      log4j.rootCategory                            = INFO, S
      log4j.logger.com.strive                        = FINE
      log4j.appender.S                            = org.apache.log4j.ConsoleAppender
      log4j.appender.S.layout                        = org.apache.log4j.PatternLayout
      log4j.appender.S.layout.ConversionPattern    = %d %p %C{1.} [%t] %m%n
    3. In your code, access the logger thus:
      // Logger
      protected static Logger logger = Logger.getLogger("com.strive");
      
      // Usage example
      logger.error("Error while doing something", exception);

 

Read more about configuring the logger at http://logging.apache.org/log4j/1.2/manual.html. There are even ports of the framework t0 PHP and .Net. You can also configure your logging to be available via a server port for remote monitoring (using Apache Chainsaw).

 

Almost everywhere I have encountered an Apache HTTP Server, it is always configured to serve out websites built in PHP. Although I am primarily a Java developer, I deal with PHP quite frequently as the presentation technology of choice for a lot of websites. Here’s how to configure Apache to dish out PHP content:

  1. Download the platform-appropriate thread-safe .zip of PHP, and extract to a location on your system.
  2. Add the installation directory to the PATH environment variable, so that it is possible to run PHP on the command line.
  3. Test your installation by running “php -i” on the command-line.
  4. Update Apache’s httpd.conf with the following settings (example):
    LoadModule php5_module "C:\PHP5\php-5.4.0\php5apache2_4.dll"
    <IfModule php5_module>
        AddType application/x-httpd-php .php
        PHPIniDir "C:\PHP5\php-5.4.0"
        DirectoryIndex index.php index.html
    </IfModule>
  5. Update the php.ini PHP configuration file. I usually just make a copy of the production INI and rename it “php.ini”.
  6. Restart Apache, ensure it starts without errors.
  7. Create a test PHP document in Apache’s htdocs and ensure that it can be accessed.

Please note that if your Apache is 32-bit, you should stick with the 32-bit flavor of PHP as well.

References:

* http://php.net/manual/en/book.apache.php