* 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
This commit is contained in:
Eelco Dolstra 2008-02-14 13:20:26 +00:00
parent bfbe92236a
commit 94937ba2aa
4 changed files with 185 additions and 119 deletions

View File

@ -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 = "
<Directory /home>
Options FollowSymlinks
AllowOverride All
</Directory>
";
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 {

View File

@ -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
<Directory "${documentRoot}">
Options Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory>
'';
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}"
<Directory "${documentRoot}">
Options Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory>
'';
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}/
<Directory ${elem.dir}>
Order allow,deny
Allow from all
AllowOverride None
</Directory>
'';
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
<IfModule prefork.c>
@ -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
</Directory>
${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}/
<Directory ${elem.dir}>
Order allow,deny
Allow from all
AllowOverride None
</Directory>
# Catch-all: since this is the first virtual host, any
# non-matching requests will use the main server configuration.
<VirtualHost *:*>
</VirtualHost>
${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 ''
<VirtualHost *:*>
${perServerConf false vhost}
</VirtualHost>
'';
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

View File

@ -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 = "
<Directory /home>
Options FollowSymlinks
AllowOverride All
</Directory>
";
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.
";
};
}

View File

@ -404,6 +404,6 @@ in {
};
};
};
}