We hope you find this tutorial helpful. In addition to guides like this one, we provide simple cloud infrastructure for developers. Learn more →

How To Migrate your Apache Configuration from 2.2 to 2.4 Syntax.

Posted Mar 31, 2014 95.9k views Apache


The Apache web server is currently the most popular web server in the world. It is used to serve web content of all kinds and is a powerful application that is highly customizable.

Many people are familiar with the Apache 2.2 configuration syntax, but some distributions are now shipping with Apache 2.4 by default. An example of this transition is Ubuntu 14.04 LTS coming from Ubuntu 12.04 LTS. While in most cases the syntax is the same, there are some important differences and some common directives have been deprecated.

In this guide, we will discuss some of the new syntax and some of the other changes that you should know about when coming from an Apache 2.2 background. We will use Ubuntu 14.04 as an example of a distribution with Apache 2.4, and compare it against the 2.2 version of Apache that ships with releases like Ubuntu 12.04.

Authorization Changes

One of the major changes that Apache 2.4 makes is the preferred way of authorizing users.

Authorization refers to the directives that define what an authenticated user can do. It lays out criteria to check to decide if operations or access should be allowed.

This is different from authentication, which must happen first. Authentication procedures define how a user is able to positively identify themselves to the server. Authentication has not changed much from 2.2, while authorization has gotten an overhaul.

First of all, authorization components can now use the Require syntax that was previously made available for authentication. This creates an easy way to define authorization order rather than relying on complex rule sets. You can instead order them in a logical way, specifying a default and then exceptions.

For instance, you can set a default for accepting traffic, but wish to block a specific malicious user, you can add something like this:

Require all granted
Require not ip

This will set a default policy of accepting everybody and then specify a qualifier that the request is not coming from the IP address. To do this, you will need to require both of these to be true, which we will learn how to do momentarily with the RequireAll directive block.

Authorization can be selected not only based on the user or group itself, but also taking into consideration the other factors by using env, host, or ip, or with the catch-all value all.

  • all: This provider matches all traffic. It is useful for setting default values.
  • env: This tests whether an environmental variable is set.
  • host: This is used to test the host name of a connecting client.
  • ip: This is used to test the IP address of the connecting user.

These can be controlled based on the order that they are specified. You will usually see them inside of one of these special blocks:

  • RequireAll: All of the authorization requirements in the block must be fulfilled to allow access.
  • RequireAny: If any of the authorization requirements in this block are met, this block is marked as satisfied.
  • RequireNone: If any of the requirements listed succeed, the directive will fail.

This let's you have quite a bit of flexibility in regards to how you set up authorization. You can nest these directive blocks within one another like this:

        Require user root
        Require ip
            Require group sysadmins
            Require group useraccounts
            Require user anthony
            Require group restrictedadmin
            Require host bad.host.com

As you can see, we can define some pretty elaborate authorization paths. The above example will authorize if the user is root and coming from the IP It will also authorize a user named "anthony" or any members of the groups "sysadmins" or "useraccounts", but ONLY if they are not also part of the "restrictedadmin" group or coming from a flagged host at bad.host.com.

These authentication blocks are much easier to understand than the classic directives that were used for access control. In past versions of Apache, you would use the Order, Allow from, Deny from, and Satisfy directives. These have not been removed, but have been deprecated in favor of the new syntax, which is easier to understand and more consistent.

They have however, been moved to a separate module called mod_access_compat. Make sure you enable this module if you require the legacy authorization directives. However, I would suggest implementing your conditions in the new syntax, both for future support, and because it is significantly easier to figure out the implications of the policies you are selecting.

Other Changes in Apache

There are a variety of other changes that you should be aware of that will affect how you build your configuration files.

Some of these may require you to change names or override new defaults. There is a more complete list of the changes here, but we will discuss some of the ones that may trip you up.

Connection and Child Limiting

A few directives have undergone name changes to better describe their functionality.

  • MaxConnectionsPerChild: This directive is used to replace the MaxRequestsPerChild. This change was made in order to better reflect what the directive actually is used for. Since the values actually limit the number of connections, this is a better name for the parameter.
  • MaxRequestWorkers: This directive was created to replace the MaxClients option. This is because with asynchronous multi-processing modules, the number of clients should not be assumed to be the same as the number of worker threads. This helps specify exactly the portion of this configuration that is affected by the directive.

AllowOverride Changes

The AllowOverride directive that is used to permit directory specific configuration files to alter default settings, has undergone a slight change that might affect your configurations.

By default, the value for this setting is now None. This will allow you to secure your server more easily by defaulting to a more locked-down state. It is still very simple to specify that .htaccess files should be read and processed in directories that require it, but you should need fewer global and large-scoped AllowOverride None declarations in order to achieve this.

The strategy of locking down the server by default and then overriding the security to allow specific instances of directory-based settings is something most users do already. This change will only help ensure that users are not open to attack as easily should they forget to implement these manually.

SendFile Default Changed

The EnableSendfile directive that is used to send a file on the server to a client without having to read the contents is now defaulted to Off.

This is a security measure that is used to ensure that the system in question supports the operation correctly. Incorrect implementation can be a liability or can cause operations to fail. These can be operating system-specific, dependant on specific hardware, or different due to the method of accessing the content (remote filesystems, etc).

Defaulting this directive to disabled allows the administer to verify their system's compatibility and do some testing to ensure proper functionality prior to enabling.

Implementation Details

While these are not exactly specific to the Apache 2.4 release, some of the default configuration files that are shipping with distributions have been changed when the transition was made.

One instance of this is in Debian and Ubuntu releases, Apache 2.4's main configuration file at /etc/apache2/apache2.conf now handles including additional files slightly differently.

In 2.2, these distributions sourced any files within the conf.d and sites-enabled directory to allow additional configuration files, most commonly used for virtualhost specifications. These directives looked like this:

Include conf.d/
Include sites-enabled/

Wildcard matching is a new feature that allows you to include specific file patterns instead of having to pass a whole directory in its entirety. This means that while traditionally, you could get by with something like the above, you could have more flexibility by using:

Include conf.d/*.conf
Include sites-enabled/*.conf

However, this new syntax also can cause some problems if you are expecting it to work exactly like before. The Include directive, when used with wildcard matching, will fail if no matching file is found, resulting in an error.

To get around this, a new directive called IncludeOptional was created. This works exactly the same, but will not result in a failure if the wildcard does not match any files.

To take advantage of this, some distributions have begun to include additional directories with:

IncludeOptional conf-enabled/*.conf
IncludeOptional sites-enabled/*.conf

As you can see, there is an additional implementation tweak that has been added here: the creation of separate conf-enabled and conf-available directories to mirror the sites-* and mods-* directories. The main takeaway here though is that specific file patterns are now being specified. All valid configuration files are required to end in .conf with this configuration.

This might take some getting used to if you typically called your virtualhost files things like default, or site1.com. However, this provides a greater amount of flexibility, because we can have non-configuration files in the directory, like old versions, tests, and README files.

This means that for testing, you can simply do something like:

cd /etc/apache2/sites-enabled/
cp mainconfig.conf mainconfig.conf.bak
nano mainconfig.conf

While you could go through the a2dissite and a2ensite operations, this is an additional method that may be more natural for some people. It also keeps your old working file in the enabled directory, which, while not being exactly semantic, may be easier to find to reimplement if you need to revert to your old version.

Another change that you may notice in your configurations is that some of the directives have been moved around, and some of the default virtualhost directives have changed. These three blocks, which in the past were in the default virtualhost file, are no longer present:

<Directory />
        Options FollowSymLinks
        AllowOverride None
<Directory /var/www/>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride None
        Order allow,deny
        allow from all

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
        AllowOverride None
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all

The top two blocks are now implemented within the apache2.conf file in recent versions of Ubuntu, since they should be set in any configuration. They have been updated to use the Require directives:

<Directory />
    Options FollowSymLinks
    AllowOverride None
    Require all denied
<Directory /var/www/>
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted

The cig-bin directory specification has been removed from the virtualhost file and implemented in the conf-available/serve-cgi-bin.conf file. This is a more modular approach and leaves the virtualhost file responsible for only the directives that are unique. In fact, the new default virtualhost, with all comments removed, is simply:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

As you can see, this can really help us to pare down our site-specific configuration files.


By auditing your existing configurations and updating certain procedures to take advantage of the new directives and best practices, migrating to Apache 2.4 is not too difficult. Functionally, it should provide the same capabilities with additional features and do it all with easier to understand syntax.

By Justin Ellingwood


Creative Commons License