Rack of Ethernet switches.

Apache on FreeBSD — Getting Started

Steps Toward The Goal

On the first page I showed how to set up a Google Compute Engine virtual machine, and on the previous page I finished setting up FreeBSD. That including installing the Apache and PHP software packages. Now let's set up the web server!

On this page I will:
1: Configure Apache to start automatically.
2: Specify a directory index.
3: Support redirection with .htaccess.
4: Cache bulky, static data.
5: Customize log format and content.

On following pages I will set up HTTP/2 and PHP, install dual free Let's Encrypt TLS certificates for RSA and ECC, and adjust the Apache configuration for a good score from the authoritative Qualys server analysis.

Starting Apache

I added apache24_enable="YES" to /etc/rc.conf and then started the apache24 service. That serves out a very simple "It works!" page.

I created a tar archive of the site and uploaded it to the new server. Then I extracted the archive into /usr/local/www/htdocs. Then:

# cd /usr/local/www/apache24
# mv data data-original
# ln -s /usr/local/www/htdocs data
# mkdir /usr/local/www/logs 

That way web content and logs go under /usr/local/www, very similar to the usual /var/www and therefore less confusing than being another level deeper under apache24.

Restarting the server resulted in data being served out, but not the way I wanted it.

My Apache Customization Plan

Here is my Apache customization to-do list:

Use Index.html (and not index or htm)

An index file is used when the client requests a directory. For example, http://cromwell-intl.com/ will be treated as a request for the index file in the root directory of the web site. This requires the mod_dir module. Apache should load that module by default, but let's check.

Index.html is my site's standard index file name, versus Apache's default lower-case index.html.

Be Flexible And Efficient

All directives should be enabled in .htaccess files. Rewriting URLs should be possible, so the mod_rewrite module should be loaded.

The server should tell the client to cache bulky, infrequently changing data like images, CSS style files, JavaScript libraries, and font files for a longer time. This requires the mod_expires module.

Customize the Logs

The default configuration logs the User-Agent field. I'm not interested in that, I can leave it out and significantly reduce the log data size.

Apache regularly polls its child processes to verify that they are responding correctly. This leads to many logged requests for "OPTIONS * HTTP/1.0". Those should not go into the logs.

I wanted to log the TLS version, so I could see if dropping TLS v1.0 support would cost me any significant traffic and thus ad revenue. Per the Qualys SSL server test, supporting TLS 1.0 through 1.2 allows all clients except Java 6u45 and IE6/XP. If I drop TLS 1.0 support, I also lose Android 2.3.7, 4.0.4, 4.1.1, 4.2.2, and 4.3; Baidu Jan 2015; IE6/XP; IE7/Vista; IE8/XP; IE8-10/Win7; IE10/WinPhone; Java7u25; OpenSSL 0.9.8y; Safari 5.1.9/OSX 10.6.8; and Safari 6.0.4/OSX 10.8.4.

I later decided to reduce log size at least for now by not logging requests for images, CSS, Javascript, and font files.

Apache Configuration

Let's make that happen!

The Apache configuration on FreeBSD is in /usr/local/etc/apache24. I made sure that the provided httpd.conf was identical to httpd.conf.sample, and then started changing httpd.conf.

Here are the initial changes I made in httpd.conf. The following omits comments and empty lines in the resulting file, and shows line numbers of the original file. Added lines are marked with "+++". The Include directive was the last entry in the original file, and line 536 was its last line.

   173  LoadModule dir_module libexec/apache24/mod_dir.so

   248  DocumentRoot "/usr/local/www/apache24/data"
   249  <Directory "/usr/local/www/apache24/data">
   262      Options Indexes FollowSymLinks
   269      ## AllowOverride None
   +++      AllowOverride All
   274      Require all granted
   275  </Directory>

   281  <IfModule dir_module>
   282      ## DirectoryIndex index.html
   +++      DirectoryIndex Index.html
   283  </IfModule>

   300  ## ErrorLog "/var/log/httpd-error.log"
   +++  ErrorLog "/var/local/www/logs/httpd-error.log"

   309  <IfModule log_config_module>
   314      ## LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
   +++      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" %{SSL_PROTOCOL}x %{SSL_CIPHER}x" combined
   315      LogFormat "%h %l %u %t \"%r\" %>s %b" common
   +++      SetEnvIf Request_Method "^OPTIONS$" no_log
   +++      SetEnvIf Request_URI ".(jpg|jpeg|png|css|gif|ico|js|ttf)" no_log
   317      <IfModule logio_module>
   319        LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
   320      </IfModule>
   329      ## CustomLog "/var/log/httpd-access.log" common
   +++      CustomLog "/usr/local/www/log/httpd-access.log" common
   335      #CustomLog "/var/log/httpd-access.log" combined
   +++      CustomLog "/usr/local/www/logs/httpd-access.log" combined env=!no_log
   336  </IfModule>

   452  # Customizable error responses come in three flavors:
   453  # 1) plain text 2) local redirects 3) external redirects
   454  #
   455  # Some examples:
   456  #ErrorDocument 500 "The server made a boo boo."
   457  #ErrorDocument 404 /missing.html
   458  #ErrorDocument 404 "/cgi-bin/missing_handler.pl"
   459  #ErrorDocument 402 http://www.example.com/subscription_info.html
   +++  ErrorDocument 404 /ssi/404page.html

   535  Include etc/apache24/Includes/*.conf
   536
   +++  ######################################################################
   +++  ## Added to original
   +++
   +++  ## Enable some modules
   +++  LoadModule expires_module libexec/apache24/mod_expires.so
   +++  LoadModule rewrite_module libexec/apache24/mod_rewrite.so
   +++
   +++  # Capture TLS version and cipher.  Pages could include:
   +++  #   <?php echo('Protocol: ' . $_SERVER["HTTP_X_SSL_PROTOCOL"]); ?>
   +++  #   <?php echo('Cipher:   ' . $_SERVER["HTTP_X_SSL_CIPHER"]); ?>
   +++  SSLOptions +StdEnvVars
   +++  RequestHeader set X-SSL-Protocol %{SSL_PROTOCOL}s
   +++  RequestHeader set X-SSL-Cipher %{SSL_CIPHER}s
   +++
   +++  # Image caching: Cache-Control in header
   +++  <FilesMatch "\.(ico|pdf|jpg|jpeg|png|gif|js|css|ttf)$">
   +++      Header set Cache-Control "max-age=864000,public"
   +++  </FilesMatch>
   +++  # Image caching: expires for images.  Must add MIME type for icon.
   +++  ExpiresActive On
   +++  ExpiresByType image/png "access plus 1 month"
   +++  ExpiresByType image/gif "access plus 1 month"
   +++  ExpiresByType image/jpeg "access plus 1 month"
   +++  ExpiresByType text/css "access plus 1 days"
   +++  AddType image/vnd.microsoft.icon .ico
   +++  ExpiresByType image/vnd.microsoft.icon "access plus 3 months"

Next Step

First, restart the service and test the pages.

Proceed to the next step to see how to configure Apache for HTTP/2 and PHP.

Next step: Enable HTTP/2 and configure PHP