Apache 2 Packaging Guidelines ============================= This document describes handling and behavior of reverse dependencies which would like to interact with the Apache 2 HTTP server Contents ======== 1. Overview 2. Packaging Modules 2.1 '.load' and '.conf' files 2.2 Maintainer scripts 3. Packaging Sites and Configurations for Web Applications 3.1 Web application module dependencies 3.2 Package dependencies 4. Maintainer Scripts 4.1 Enabling Configurations 4.2 Switching MPMs 5. Tools 5.1 a2query 5.2 apache2-maintscript-helper 5.3 dh_apache2 6. Version 6.1 Changes 1 Overview ========== The Apache 2 web server package in Debian supports two types of reverse dependencies: modules and web applications. They need to be treated differently as their requirements are different. We have special requirements for how to declare dependencies against Apache 2 web server packages depending on the type of package. Refer to the appropriate parts for extensive information. Furthermore, there are several helper tools available to assist with common tasks. These are outlined in their respective sub sections as well. You should use these tools to get maintainer scripts and dependencies right. This document adopts the normative wording of the Debian Policy Manual ยง1.1[1]. The words "must", "should", and "may", and the adjectives "required", "recommended", and "optional", are used to distinguish the significance of the various guidelines in this policy document. [1] http://www.debian.org/doc/debian-policy/ch-scope.html#s1.1 2 Packaging Modules =================== Modules are packages which are installing third party extensions to the Apache 2 web server which can be loaded at runtime to extend the functionality of the core server. Please be aware that such compiled modules make use of a stable Application Binary Interface (ABI) and therefore need a recompile if the web server changes. Hence be careful how you declare dependencies against the web server. You need to make sure it does not break upon upgrades. A module package providing an Apache module must obey these policies to make sure it can be upgraded without breakage of local sites. To achieve this, a package must build-depend on apache2-dev. That package provides the 'apxs' compile helper which makes sure the module to be compiled is compatible with the Apache 2 web server and the C headers the server is providing as a public interface. If an updated package is not buildable with Apache 2.2 anymore, the apache2-dev build-dependency should be versioned ">> 2.4~", because older versions of apache2-threaded-dev did provide apache2-dev. A module package that uses openssl specific interfaces in mod_ssl, either by using the mod_ssl_openssl.h header, or by using mod_ssl-internal private interfaces (don't do that!), must build-depend on apache2-ssl-dev to ensure that the correct version of the openssl headers are used. In this case, dh_apache2 will also create a dependency on a apache2-api-YYYYMMDD-opensslM.M virtual package. The resulting binary package should be called libapache2-mod- and MUST NOT depend on apache2 or apache2-bin. Instead a module package must depend on our virtual package providing the module magic number which denotes the ABI compatibility version number. The virtual package is called apache2-api-YYYYMMDD and is guaranteed to be stable through all binary updates of 2.4.x. The dh_apache2 helper assists in getting the dependencies right. 2.1 '.load' and '.conf' files ----------------------------- The module must install a 'module.load' file to /etc/apache2/modules-available, where 'module' is the name of the installed module minus the "mod_" prefix. The '.load' file must contain an appropriate "LoadModule" directive only. Additionally maintainers may use a magic line in '.load' files to declare module dependencies and conflicts which need to be resolved to load a module for a local site. This is useful if a module depends on other modules to be loaded, or to conflict with other modules if they can't be loaded at the same time. a2enmod and a2dismod will parse any "magic comment lines" with the format "# Depends: module [module [...]]" and "# Conflicts: module [module [...]]"; for example to load mod_foo: In 'foo.load': # Depends: bar # Conflicts: baz LoadModule foo_module /usr/lib/modules/mod_foo.so Additionally, if required, a 'foo.conf' configuration file to configure the module may be installed along with the 'load' file, following the same naming scheme. This is useful if the module in question requires some initial configuration to be useful. No magic comments are recognized in '.conf' files. Otherwise they have the same functionality and requirements as configuration files (see section 3 below). You should use only directives provided by default by our web server configuration or which are provided by your module itelf in a supplied '.conf' file. In some rare cases it can't be avoided that a module depends on an another module being loaded already before its own loading process can succeed. The module load order is guaranteed to be sorted alphabetically, which could lead to problems if the new module to be loaded sorts later. In most cases such pre-load dependencies can be avoided upstream - consider filing a bug. If there is no way out of this problem, you may want to add a conditional Include in your own module file. Suppose mod_foo relies on mod_bar to be loaded first. You may want to write a module 'load' file like this: # Depends: bar Include mods-enabled/bar.load LoadModule foo_module /usr/lib/modules/mod_foo.so Please note that the bar.load file must also contain a matching "" guard as it would be loaded twice otherwise. Use this method extremely sparingly and in agreement with related package maintainers only. Note that such a module '.load' file must still contain a "Depends:" magic line to make sure that the a2enmod/a2dismod dependency resolver works correctly. 2.2 Maintainer scripts ---------------------- Maintainer scripts should not invoke a2enmod directly. Instead, the apache2-maintscript-helper should be used. Please be aware that the helper is not guaranteed to be installed on the target system. There are certain setups which do not require Debian specific configurations, so modules must not do anything in maintainer scripts which makes use of Debian-specific enhancements like apache2-maintscript-helper, a2enmod, or a2query unconditionally. It is recommended to invoke it like this: if [ -e /usr/share/apache2/apache2-maintscript-helper ] ; then . /usr/share/apache2/apache2-maintscript-helper apache2_invoke enmod foo fi The dh_apache2 helper can be used to install module configuration and load files. Additionally it generates appropriate maintainer scripts. The apache2-maintscript-helper provides a few functions for common tasks. See their respective reference documentations below. If maintainer scripts use a2enmod/a2dismod manually, they must invoke them with the "-m" (maintainer mode) switch. 3 Packaging Sites and Configurations for Web Applications ========================================================= Web applications are different from modules in that they do not have a hard dependency on the web server. Typically they require a running web server, but they do not need to worry about binary compatibility of modules. We accept that there are other web servers besides Apache; thus we discourage package maintainers of web applications from depending unconditionally on Apache. That said, we provide several helpers to assist web application packagers to invoke configuration snippets to enable a web application in the Apache 2 web server. We differentiate between two sub-types: sites and general configuration. Sites are installed to /etc/apache2/sites-available and configure a particular virtual host. Special care must be taken when installing a site configuration to make sure it does not interfere with site-local configuration used by the administrator. Typically there are only a few use cases where a Debian package should include a virtual host configuration. The general configuration snippets are installed to /etc/apache2/conf-available instead. Package maintainers are advised to avoid "local-" prefixes to installed conffiles, and ideally use "packagename.conf" to avoid name clashes. This type of configuration must be used when installing a global (i.e. virtual host independent) configuration. Usually these configuration snippets will be included in the global server context via the conf-enabled directory. However, it is planned to allow the administrator to only enable the configuration snippets in a selected set of virtual hosts. Typically a "packagename.conf" should enable a global alias pointing to your web application along with a script-dependendent per-script configuration; for example: Alias /packagename /usr/share/packagename ... Please be careful about the directives you are using. Some might be provided by modules which are not enabled by default. By default you can unconditionally use directives from these modules: mod_access_compat, mod_alias, mod_auth_basic, mod_authn_file, mod_authz_host, mod_authz_user, mod_autoindex, mod_deflate, mod_dir, mod_env, mod_filter, mod_logio, mod_mime, mod_negotiation, mod_setenvif, mod_unixd, mod_version, mod_watchdog. Check the module documentation for the modules providing directives you are using. Note that not all directives are really required. If your configuration can be enhanced by mod_rewrite rules, but does not necessarily need to use them, you could do something like: ... on RewriteRule ... (Note that some common uses of mod_rewrite for web applications can be replaced by the relatively new FallbackResource directive.) 3.1 Web application module dependencies --------------------------------------- There are use cases where a configuration really needs a certain module to be enabled. This is tricky to achieve for web applications as dependencies could lead to complex dependency chains which could break unrelated web applications installed alongside your package. Thus, we do not resolve module dependencies for web applications automatically, but they may be expressed (see 'load' files in section 2.1), and a2enconf will warn the site administrator about modules which need to enabled. Moreover, modules can be arbitrarily enabled and disabled by local administrators, so a web application must make sure not to break the web server's start-up if a required module is not available. The syntax for config snippets to express dependencies is identical to the syntax in modules' '.load' files. Within your package.conf file you still need to protect non-default directives with clauses as there is no guarantee that the modules are actually enabled. It is acceptable if your configuration file turns into a no-op as long as it does not break the server start-up. For both types of configuration (configurations and sites), dh_apache2 can be used to assist packagers. 3.2 Package dependencies ------------------------ Web applications must only depend on (or recommend) the apache2 package. Web applications must not depend on or recommend the packages apache2-bin or apache2-data. Generally, web server dependencies should be declared in the form: Depends: apache2 | | httpd-cgi Using dh_apache2 assists you to do so, although dh_apache2 declares a weaker Recommends relation only. While a consolidated and consistent behavior among web applications would be desirable, from Apache's point of view, both alternatives are acceptable. If your web application depends on a particular web server module you need to depend on that, too. For example, PHP applications might need to formulate dependency lines in the form: Depends: libapache2-mod-php5 | php5-cgi | php5-fpm Recommends: apache2 | | httpd-cgi A with modules, web applications may enable their configuration files in maintainer scripts. Use of dh_apache2 is recommended to achieve this. Generally, special care should be taken not to use Apache2 Debian helper scripts like a2query and a2enmod unconditionally. You can use the apache2-maintscript-helper tools provided by the apache2 package for common tasks this way: if [ -e /usr/share/apache2/apache2-maintscript-helper ] ; then . /usr/share/apache2/apache2-maintscript-helper apache2_invoke enconf foo fi Refer to the reference documentation below to learn how to use apache2-maintscript-helper. Do not enable or disable modules in web application maintainer scripts; instead protect your configuration with clauses if you require non-standard modules. 4 Maintainer Scripts ==================== Though already discussed briefly in previous sections, here follow some clarifications regarding the invocation of wrapper scripts in maintainer scripts of modules and web applications. 4.1 Enabling Configurations --------------------------- Both modules and web applications should use the apache2-maintscript-helper in general. The helper will obey local policies to decide when to enable a piece of configuration, to reload the web server, and so on. Moreover, it will remember whether a module was activated by the site administrator or a maintainer script. Thus, it is particularly important you do not use "a2enmod" and so on directly (though a2query is acceptable). This is a summary of how the apache2-maintscript-helper should be invoked in maintainer scripts: Modules: Unless a maintainer or debconf script verified that no configuration was to be installed at all, e.g. for scripts supporting several web servers, modules should unconditionally call apache2_invoke in their "postinst configure" sections. It will obey site-local policies in future and will make sure that disabled modules are not enabled again during upgrades of a module package. Modules need to be disabled on removal (and purge anyway), as otherwise their configuration will be broken (as LoadModule would fail because of the missing shared object file). Thus, modules need to call "apache2_invoke dismod" on both removal and purge. It's apache2_invoke's job to deal with upgrades and it will remember modules it removed during removal and will reenable them during re-install. Web Applications: Web Applications derive the same behavior as modules if the web application can be run with a sensible out-of-box configuration; don't enable it otherwise. Likewise, web application should also be disabled on removal (and on purge anyway), because important files may be missing (and that's the point of package removal, anyway). 4.2 Switching MPMs ------------------ Only modules are allowed to switch the enabled MPM. Web applications must not switch the enabled MPM in their maintainer scripts. To actually switch the MPM, packagers can use a2query to find out whether it is necessary, and if so, can switch it by using the corresponding helper function provided in apache2-maintscript-helper. Do not try to switch the MPM yourself - the helper function takes special care not to leave the site in a state without an enabled MPM, which is a fatal error. The helper call may fail. Your maintainer script must cope with this possibility. It is not recommended to make your maintainer script fail if the MPM could not be changed. Instead emit a warning. You can use the apache2_msg function from apache2-maintscript-helper which will also log to syslog. If you are using debconf anyway you may want to consider using that - but continue operation. However, make sure you only enable the module in question if the MPM was changed successfully. See below for an example snippet: if [ -e /usr/share/apache2/apache2-maintscript-helper ] ; then . /usr/share/apache2/apache2-maintscript-helper # mod_foo requires the prefork MPM if [ $(a2query -M) != 'prefork' ] ; then if apache2_switch_mpm prefork ; then apache2_invoke enmod foo else apache2_msg err "Could not switch to prefork, not enabling mod_foo" fi else apache2_invoke enmod foo fi fi 5. Tools ======== This is an overview of tools supplied with the Apache2 package which can assist in building web application and module packages. 5.1 apache2-maintscript-helper ------------------------------ The apache2-maintscript-helper is a collection of functions which can be sourced in maintainer scripts to do required tasks in a simple and standardized way. It is NOT a script; it is a library (insofar as shell functions can be libraries). This is to avoid users calling these functions. They are not meant to be used by users. The helper is installed within the apache2 binary package. Thus you MUST NOT use any function of it unconditionally, as for both modules and web applications there are use cases when this package is not added as a dependency. Thus, use it in a protected conditional like this only: if [ -e /usr/share/apache2/apache2-maintscript-helper ] ; then . /usr/share/apache2/apache2-maintscript-helper fi The helper provides functions to enable and disable configuration files, restart the web server, switch the MPM in use and similar. Refer to the source code for detailed interface documentation. When available, please use the apache2-maintscript-helper instead of calling helper scripts directly, as these functions are careful to invoke and use the appropriate helper. Later versions may be configurable to allow the administrator to influence which actions are performed. Always check the return code of the called function to find out whether something went wrong: if ! apache2_invoke enmod modulename ; then echo "Whoops! Something went wrong" fi 5.2 dh_apache2 -------------- dh_apache2 is a debhelper which can be used to install modules, module configuration, site configuration, and global configuration snippets. It assists you to set appropriate dependencies and maintainer scripts. Refer to dh_apache2(1) for full usage guidelines. 5.2 a2enmod ----------- a2enmod and its special invocations a2enconf, a2ensite, a2dismod, a2dissite and a2disconf can be used to enable all types of Apache 2 configuration files. When invoking these helpers in maintainer scripts, you should carefully check their error return codes. These scripts must always be used with the -q (quiet) and -m (maintainer mode) switches in maintainer scripts. Preferably, you should not interface with this scripts directly; instead it is recommended to use apache2-maintscript-helper. For detailed usage refer to their respective man pages. 5.3 a2query ---------- a2query is a query tool to retrieve runtime status information about the Apache 2 web server instance. You can use this tool to get information about loaded modules, the MPM used on the installation site, the module magic number and other useful information. Use this script instead of accessing configuration files in /etc/apache2 directly as it tries its best to return useful information even on incomplete or broken configurations. For example, you can use a2query to retrieve the MPM enabled on the local site and make actions dependent on the result like this: [ -x /usr/sbin/a2query ] || exit $? CUR_MPM=$(a2query -M) || exit $? case "$CUR_MPM" in worker) ;; ... esac Refer to the a2query(1) man page for the full documentation. Please note that the apache2-maintscript-helper can be used to interface with this task as well. 6 Version ========= Document version: 1.0 Starting with Apache2 2.4.2-2 this document is versioned. Any change which affects packaging is denoted by an increased major nummer; clarifications, spelling fixes and minor edits are denoted by minor numbers. In future, a changelog will appear here as well. 6.1 Changes ----------- 1.0: * first version of this document which is versioned.