From 94937ba2aad159d68d2b2860165bb7f378448147 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 14 Feb 2008 13:20:26 +0000 Subject: [PATCH] * Support for declaring virtual hosts, like httpd = { ... virtualHosts = [ { hostName = "foo"; documentRoot = "/data/webroot-foo"; ... } { hostName = "bar"; documentRoot = "/data/webroot-bar"; ... } ]; }; Each virtual host can specify almost any option also permitted in the top-level httpd configuration. svn path=/nixos/trunk/; revision=10682 --- system/options.nix | 68 +------- upstart-jobs/apache-httpd/default.nix | 148 +++++++++++------- .../apache-httpd/per-server-options.nix | 86 ++++++++++ upstart-jobs/apache-httpd/subversion.nix | 2 +- 4 files changed, 185 insertions(+), 119 deletions(-) create mode 100644 upstart-jobs/apache-httpd/per-server-options.nix diff --git a/system/options.nix b/system/options.nix index 7c452d02435b..3e802253d07d 100644 --- a/system/options.nix +++ b/system/options.nix @@ -1194,13 +1194,6 @@ "; }; - adminAddr = mkOption { - example = "admin@example.org"; - description = " - E-mail address of the server administrator. - "; - }; - logDir = mkOption { default = "/var/log/httpd"; description = " @@ -1225,54 +1218,6 @@ "; }; - documentRoot = mkOption { - default = null; - example = "/data/webserver/docs"; - description = " - The path of Apache's document root directory. If left undefined, - an empty directory in the Nix store will be used as root. - "; - }; - - servedDirs = mkOption { - default = []; - example = [ - { urlPath = "/nix"; - dir = "/home/eelco/Dev/nix-homepage"; - } - ]; - description = " - This option provides a simple way to serve static directories. - "; - }; - - servedFiles = mkOption { - default = []; - example = [ - { urlPath = "/foo/bar.png"; - dir = "/home/eelco/some-file.png"; - } - ]; - description = " - This option provides a simple way to serve individual, static files. - "; - }; - - # !!! this is a mis-nomer, should be "extraConfig" or something. - extraDirectories = mkOption { - default = ""; - example = " - - Options FollowSymlinks - AllowOverride All - - "; - description = " - These lines go to httpd.conf verbatim. They will go after - directories and directory aliases defined by default. - "; - }; - mod_php = mkOption { default = false; description = "Whether to enable the PHP module."; @@ -1367,14 +1312,11 @@ }; - extraSubservices = mkOption { - default = []; - description = " - Extra subservices to enable in the webserver. - "; - }; - - }; + } // # Include the options shared between the main server and virtual hosts. + (import ../upstart-jobs/apache-httpd/per-server-options.nix { + inherit mkOption; + forMainServer = true; + }); vsftpd = { enable = mkOption { diff --git a/upstart-jobs/apache-httpd/default.nix b/upstart-jobs/apache-httpd/default.nix index 69d50757bf14..aff915e4a2b0 100644 --- a/upstart-jobs/apache-httpd/default.nix +++ b/upstart-jobs/apache-httpd/default.nix @@ -9,23 +9,25 @@ let httpd = pkgs.apacheHttpd; - serverInfo = { + makeServerInfo = cfg: { # Canonical name must not include a trailing slash. canonicalName = - "http://" + - cfg.hostName + + "http://${cfg.hostName}" + (if cfg.httpPort != 80 then ":${toString cfg.httpPort}" else ""); serverConfig = cfg; fullConfig = config; # machine config }; - subservices = + callSubservices = serverInfo: defs: let f = svc: let config = pkgs.lib.addDefaultOptionValues res.options svc.config; res = svc.function {inherit config pkgs serverInfo;}; in res; - in map f cfg.extraSubservices; + in map f defs; + + + allSubservices = callSubservices (makeServerInfo cfg) cfg.extraSubservices; # !!! should be in lib @@ -33,10 +35,6 @@ let pkgs.runCommand name {inherit text;} "ensureDir $out; echo -n \"$text\" > $out/$name"; - documentRoot = if cfg.documentRoot != null then cfg.documentRoot else - pkgs.runCommand "empty" {} "ensureDir $out"; - - # Names of modules from ${httpd}/modules that we want to load. apacheModules = [ # HTTP authentication mechanisms: basic and digest. @@ -84,6 +82,7 @@ let ''; + # !!! integrate with virtual hosting below sslConf = '' Listen ${toString cfg.httpsPort} @@ -128,24 +127,65 @@ let ''; - documentRootConf = '' - DocumentRoot "${documentRoot}" + perServerConf = isMainServer: cfg: let - - Options Indexes FollowSymLinks - AllowOverride None - Order allow,deny - Allow from all - - ''; + serverInfo = makeServerInfo cfg; + subservices = callSubservices serverInfo cfg.extraSubservices; - robotsTxt = pkgs.writeText "robots.txt" '' - ${pkgs.lib.concatStrings (map (svc: svc.robotsEntries) subservices)} - ''; - - robotsConf = '' - Alias /robots.txt ${robotsTxt} + documentRoot = if cfg.documentRoot != null then cfg.documentRoot else + pkgs.runCommand "empty" {} "ensureDir $out"; + + documentRootConf = '' + DocumentRoot "${documentRoot}" + + + Options Indexes FollowSymLinks + AllowOverride None + Order allow,deny + Allow from all + + ''; + + robotsTxt = pkgs.writeText "robots.txt" '' + ${concatMapStrings (svc: svc.robotsEntries) subservices} + ''; + + robotsConf = '' + Alias /robots.txt ${robotsTxt} + ''; + + in '' + ServerName ${serverInfo.canonicalName} + + ${if isMainServer || cfg.adminAddr != "" then '' + ServerAdmin ${cfg.adminAddr} + '' else ""} + + ${robotsConf} + + ${if isMainServer || cfg.documentRoot != null then documentRootConf else ""} + + ${ + let makeDirConf = elem: '' + Alias ${elem.urlPath} ${elem.dir}/ + + Order allow,deny + Allow from all + AllowOverride None + + ''; + in concatMapStrings makeDirConf cfg.servedDirs + } + + ${ + let makeFileConf = elem: '' + Alias ${elem.urlPath} ${elem.file} + ''; + in concatMapStrings makeFileConf cfg.servedFiles + } + + ${concatMapStrings (svc: svc.extraConfig) subservices} ''; @@ -153,10 +193,6 @@ let ServerRoot ${httpd} - ServerAdmin ${cfg.adminAddr} - - ServerName ${serverInfo.canonicalName} - PidFile ${cfg.stateDir}/httpd.pid @@ -172,10 +208,10 @@ let ${let load = {name, path}: "LoadModule ${name}_module ${path}\n"; allModules = - pkgs.lib.concatMap (svc: svc.extraModulesPre) subservices ++ + pkgs.lib.concatMap (svc: svc.extraModulesPre) allSubservices ++ map (name: {inherit name; path = "${httpd}/modules/mod_${name}.so";}) apacheModules ++ - pkgs.lib.concatMap (svc: svc.extraModules) subservices; - in pkgs.lib.concatStrings (map load allModules) + pkgs.lib.concatMap (svc: svc.extraModules) allSubservices; + in concatMapStrings load allModules } ${if cfg.enableUserDir then '' @@ -232,30 +268,32 @@ let Allow from all - ${robotsConf} + # Generate directives for the main server. + ${perServerConf true cfg} - ${documentRootConf} + # Always enable virtual hosts; it doesn't seem to hurt. + NameVirtualHost *:* - ${ - let makeDirConf = elem: '' - Alias ${elem.urlPath} ${elem.dir}/ - - Order allow,deny - Allow from all - AllowOverride None - + # Catch-all: since this is the first virtual host, any + # non-matching requests will use the main server configuration. + + + + ${let + perServerOptions = import ./per-server-options.nix { + inherit (pkgs.lib) mkOption; + forMainServer = false; + }; + makeVirtualHost = vhostIn: + let + # Fill in defaults for missing options. + vhost = pkgs.lib.addDefaultOptionValues perServerOptions vhostIn; + in '' + + ${perServerConf false vhost} + ''; - in pkgs.lib.concatStrings (map makeDirConf cfg.servedDirs) - } - - ${ - let makeFileConf = elem: '' - Alias ${elem.urlPath} ${elem.file} - ''; - in pkgs.lib.concatStrings (map makeFileConf cfg.servedFiles) - } - - ${pkgs.lib.concatStrings (map (svc: svc.extraConfig) subservices)} + in concatMapStrings makeVirtualHost cfg.virtualHosts} ''; @@ -276,7 +314,7 @@ in } ]; - extraPath = [httpd] ++ pkgs.lib.concatMap (svc: svc.extraPath) subservices; + extraPath = [httpd] ++ pkgs.lib.concatMap (svc: svc.extraPath) allSubservices; # Statically verify the syntactic correctness of the generated # httpd.conf. @@ -306,10 +344,10 @@ in ${ let f = {name, value}: "env ${name}=${value}\n"; - in pkgs.lib.concatStrings (map f (pkgs.lib.concatMap (svc: svc.globalEnvVars) subservices)) + in pkgs.lib.concatStrings (map f (pkgs.lib.concatMap (svc: svc.globalEnvVars) allSubservices)) } - env PATH=${pkgs.coreutils}/bin:${pkgs.gnugrep}/bin:${pkgs.lib.concatStringsSep ":" (pkgs.lib.concatMap (svc: svc.extraServerPath) subservices)} + env PATH=${pkgs.coreutils}/bin:${pkgs.gnugrep}/bin:${pkgs.lib.concatStringsSep ":" (pkgs.lib.concatMap (svc: svc.extraServerPath) allSubservices)} ${pkgs.diffutils}/bin:${pkgs.gnused}/bin diff --git a/upstart-jobs/apache-httpd/per-server-options.nix b/upstart-jobs/apache-httpd/per-server-options.nix new file mode 100644 index 000000000000..08f60b2cc6d1 --- /dev/null +++ b/upstart-jobs/apache-httpd/per-server-options.nix @@ -0,0 +1,86 @@ +# This file defines the options that can be used both for the Apache +# main server configuration, and for the virtual hosts. (The latter +# has additional options that affect the web server as a whole, like +# the user/group to run under.) + +{forMainServer, mkOption}: + +{ + + hostName = mkOption { + default = "localhost"; + description = " + Canonical hostname for the server. + "; + }; + + httpPort = mkOption { + default = 80; + description = " + Port for unencrypted HTTP requests. + "; + }; + + adminAddr = mkOption ({ + example = "admin@example.org"; + description = " + E-mail address of the server administrator. + "; + } // (if forMainServer then {} else {default = "";})); + + documentRoot = mkOption { + default = null; + example = "/data/webserver/docs"; + description = " + The path of Apache's document root directory. If left undefined, + an empty directory in the Nix store will be used as root. + "; + }; + + servedDirs = mkOption { + default = []; + example = [ + { urlPath = "/nix"; + dir = "/home/eelco/Dev/nix-homepage"; + } + ]; + description = " + This option provides a simple way to serve static directories. + "; + }; + + servedFiles = mkOption { + default = []; + example = [ + { urlPath = "/foo/bar.png"; + dir = "/home/eelco/some-file.png"; + } + ]; + description = " + This option provides a simple way to serve individual, static files. + "; + }; + + # !!! this is a mis-nomer, should be "extraConfig" or something. + extraDirectories = mkOption { + default = ""; + example = " + + Options FollowSymlinks + AllowOverride All + + "; + description = " + These lines go to httpd.conf verbatim. They will go after + directories and directory aliases defined by default. + "; + }; + + extraSubservices = mkOption { + default = []; + description = " + Extra subservices to enable in the webserver. + "; + }; + +} diff --git a/upstart-jobs/apache-httpd/subversion.nix b/upstart-jobs/apache-httpd/subversion.nix index ae78f90e22c5..60c3d71c62dd 100644 --- a/upstart-jobs/apache-httpd/subversion.nix +++ b/upstart-jobs/apache-httpd/subversion.nix @@ -404,6 +404,6 @@ in { }; - }; + }; }