2014-04-14 15:26:48 +01:00
{ config , lib , pkgs , . . . }:
2007-12-12 13:58:15 +00:00
2014-04-14 15:26:48 +01:00
with lib ;
2009-03-06 12:26:41 +00:00
2009-07-15 12:19:11 +01:00
let
2007-12-12 13:58:15 +00:00
2008-04-24 12:56:38 +01:00
mainCfg = config . services . httpd ;
2011-09-14 19:20:50 +01:00
2015-10-20 22:49:32 +01:00
httpd = mainCfg . package . out ;
2012-07-23 20:48:21 +01:00
2012-10-17 16:47:30 +01:00
version24 = ! versionOlder httpd . version " 2 . 4 " ;
2012-07-23 20:48:21 +01:00
httpdConf = mainCfg . configFile ;
2007-12-12 13:58:15 +00:00
2016-06-22 13:24:25 +01:00
php = mainCfg . phpPackage . override { apacheHttpd = httpd . dev ; /* o t h e r w i s e i t o n l y g e t s . o u t */ } ;
phpMajorVersion = head ( splitString " . " php . version ) ;
2007-12-12 13:58:15 +00:00
2017-06-15 12:07:14 +01:00
mod_perl = pkgs . apacheHttpdPackages . mod_perl . override { apacheHttpd = httpd ; } ;
2016-12-15 11:36:07 +00:00
2016-11-12 14:35:32 +00:00
defaultListen = cfg : if cfg . enableSSL
then [ { ip = " * " ; port = 443 ; } ]
else [ { ip = " * " ; port = 80 ; } ] ;
getListen = cfg :
let list = ( lib . optional ( cfg . port != 0 ) { ip = " * " ; port = cfg . port ; } ) ++ cfg . listen ;
in if list == [ ]
then defaultListen cfg
else list ;
listenToString = l : " ${ l . ip } : ${ toString l . port } " ;
2008-09-14 02:30:45 +01:00
2009-07-15 12:19:11 +01:00
extraModules = attrByPath [ " e x t r a M o d u l e s " ] [ ] mainCfg ;
2013-11-12 12:48:19 +00:00
extraForeignModules = filter isAttrs extraModules ;
extraApacheModules = filter isString extraModules ;
2007-12-12 13:58:15 +00:00
2011-09-14 19:20:50 +01:00
2008-02-14 13:20:26 +00:00
makeServerInfo = cfg : {
2008-02-11 11:51:51 +00:00
# Canonical name must not include a trailing slash.
2016-11-12 14:35:32 +00:00
canonicalNames =
let defaultPort = ( head ( defaultListen cfg ) ) . port ; in
map ( port :
( if cfg . enableSSL then " h t t p s " else " h t t p " ) + " : / / " +
cfg . hostName +
( if port != defaultPort then " : ${ toString port } " else " " )
) ( map ( x : x . port ) ( getListen cfg ) ) ;
2008-02-19 14:54:19 +00:00
# Admin address: inherit from the main server if not specified for
# a virtual host.
2013-10-29 13:03:39 +00:00
adminAddr = if cfg . adminAddr != null then cfg . adminAddr else mainCfg . adminAddr ;
2008-02-19 14:54:19 +00:00
2008-02-19 17:37:05 +00:00
vhostConfig = cfg ;
serverConfig = mainCfg ;
2008-02-14 09:54:25 +00:00
fullConfig = config ; # machine config
2008-02-11 11:51:51 +00:00
} ;
2009-11-06 16:23:25 +00:00
2013-10-28 20:58:32 +00:00
allHosts = [ mainCfg ] ++ mainCfg . virtualHosts ;
2011-09-14 19:20:50 +01:00
2009-11-06 16:23:25 +00:00
2008-02-14 13:20:26 +00:00
callSubservices = serverInfo : defs :
2008-02-14 09:54:25 +00:00
let f = svc :
2011-09-14 19:20:50 +01:00
let
2009-11-06 16:23:25 +00:00
svcFunction =
if svc ? function then svc . function
2017-02-06 00:08:58 +00:00
# instead of using serviceType="mediawiki"; you can copy mediawiki.nix to any location outside nixpkgs, modify it at will, and use serviceExpression=./mediawiki.nix;
else if svc ? serviceExpression then import ( toString svc . serviceExpression )
2013-10-29 00:20:33 +00:00
else import ( toString " ${ toString ./. } / ${ if svc ? serviceType then svc . serviceType else svc . serviceName } . n i x " ) ;
2013-10-28 21:09:16 +00:00
config = ( evalModules
{ modules = [ { options = res . options ; config = svc . config or svc ; } ] ;
check = false ;
} ) . config ;
2009-11-06 16:23:25 +00:00
defaults = {
extraConfig = " " ;
extraModules = [ ] ;
extraModulesPre = [ ] ;
extraPath = [ ] ;
extraServerPath = [ ] ;
globalEnvVars = [ ] ;
robotsEntries = " " ;
startupScript = " " ;
2010-07-14 13:58:38 +01:00
enablePHP = false ;
2016-12-15 11:36:07 +00:00
enablePerl = false ;
2010-02-15 19:02:42 +00:00
phpOptions = " " ;
2009-11-06 16:23:25 +00:00
options = { } ;
2014-02-25 12:44:45 +00:00
documentRoot = null ;
2009-11-06 16:23:25 +00:00
} ;
2014-04-14 15:26:48 +01:00
res = defaults // svcFunction { inherit config lib pkgs serverInfo php ; } ;
2009-11-06 16:23:25 +00:00
in res ;
2008-02-14 13:20:26 +00:00
in map f defs ;
2011-09-14 19:20:50 +01:00
# !!! callSubservices is expensive
2008-02-19 17:37:05 +00:00
subservicesFor = cfg : callSubservices ( makeServerInfo cfg ) cfg . extraSubservices ;
2008-02-14 14:14:39 +00:00
2008-02-19 17:37:05 +00:00
mainSubservices = subservicesFor mainCfg ;
2013-10-28 20:58:32 +00:00
allSubservices = mainSubservices ++ concatMap subservicesFor mainCfg . virtualHosts ;
2008-02-05 16:25:07 +00:00
2009-07-15 12:19:11 +01:00
enableSSL = any ( vhost : vhost . enableSSL ) allHosts ;
2011-09-14 19:20:50 +01:00
2008-02-05 16:25:07 +00:00
2007-12-12 13:58:15 +00:00
# Names of modules from ${httpd}/modules that we want to load.
2011-09-14 19:20:50 +01:00
apacheModules =
2007-12-12 13:58:15 +00:00
[ # HTTP authentication mechanisms: basic and digest.
" a u t h _ b a s i c " " a u t h _ d i g e s t "
# Authentication: is the user who he claims to be?
2012-10-17 14:11:53 +01:00
" a u t h n _ f i l e " " a u t h n _ d b m " " a u t h n _ a n o n "
2012-10-17 16:47:30 +01:00
( if version24 then " a u t h n _ c o r e " else " a u t h n _ a l i a s " )
2007-12-12 13:58:15 +00:00
# Authorization: is the user allowed access?
" a u t h z _ u s e r " " a u t h z _ g r o u p f i l e " " a u t h z _ h o s t "
# Other modules.
" e x t _ f i l t e r " " i n c l u d e " " l o g _ c o n f i g " " e n v " " m i m e _ m a g i c "
2008-01-03 17:11:36 +00:00
" c e r n _ m e t a " " e x p i r e s " " h e a d e r s " " u s e r t r a c k " /* " u n i q u e _ i d " */ " s e t e n v i f "
2012-07-06 19:23:55 +01:00
" m i m e " " d a v " " s t a t u s " " a u t o i n d e x " " a s i s " " i n f o " " d a v _ f s "
2007-12-12 13:58:15 +00:00
" v h o s t _ a l i a s " " n e g o t i a t i o n " " d i r " " i m a g e m a p " " a c t i o n s " " s p e l i n g "
2008-02-18 15:00:26 +00:00
" u s e r d i r " " a l i a s " " r e w r i t e " " p r o x y " " p r o x y _ h t t p "
2011-09-14 19:20:50 +01:00
]
2012-10-17 16:47:30 +01:00
++ optionals version24 [
2012-10-17 14:21:32 +01:00
" m p m _ ${ mainCfg . multiProcessingModule } "
2012-10-17 15:57:18 +01:00
" a u t h z _ c o r e "
2012-10-17 14:21:32 +01:00
" u n i x d "
2014-11-06 13:27:02 +00:00
" c a c h e " " c a c h e _ d i s k "
" s l o t m e m _ s h m "
2014-11-06 20:58:26 +00:00
" s o c a c h e _ s h m c b "
2014-12-15 12:04:33 +00:00
# For compatibility with old configurations, the new module mod_access_compat is provided.
" a c c e s s _ c o m p a t "
2012-10-17 14:21:32 +01:00
]
2012-07-06 19:23:55 +01:00
++ ( if mainCfg . multiProcessingModule == " p r e f o r k " then [ " c g i " ] else [ " c g i d " ] )
2010-07-14 13:58:38 +01:00
++ optional enableSSL " s s l "
++ extraApacheModules ;
2011-09-14 19:20:50 +01:00
2007-12-12 13:58:15 +00:00
2012-10-17 16:47:30 +01:00
allDenied = if version24 then ''
Require all denied
'' e l s e ''
2012-10-17 15:57:18 +01:00
Order deny , allow
Deny from all
'' ;
2012-10-17 16:47:30 +01:00
allGranted = if version24 then ''
Require all granted
'' e l s e ''
2012-10-17 15:57:18 +01:00
Order allow , deny
Allow from all
'' ;
2014-07-10 13:32:08 +01:00
loggingConf = ( if mainCfg . logFormat != " n o n e " then ''
2019-01-31 02:04:58 +00:00
ErrorLog $ { mainCfg . logDir } /error.log
2007-12-12 13:58:15 +00:00
LogLevel notice
LogFormat " % h % l % u % t \" % r \" % > s % b \" % { R e f e r e r } i \" \" % { U s e r - A g e n t } i \" " combined
LogFormat " % h % l % u % t \" % r \" % > s % b " common
LogFormat " % { R e f e r e r } i - > % U " referer
LogFormat " % { U s e r - a g e n t } i " agent
2019-01-31 02:04:58 +00:00
CustomLog $ { mainCfg . logDir } /access.log $ { mainCfg . logFormat }
2014-07-10 13:32:08 +01:00
'' e l s e ''
ErrorLog /dev/null
'' ) ;
2007-12-12 13:58:15 +00:00
browserHacks = ''
BrowserMatch " M o z i l l a / 2 " nokeepalive
BrowserMatch " M S I E 4 \. 0 b 2 ; " nokeepalive downgrade-1 .0 force-response-1 .0
BrowserMatch " R e a l P l a y e r 4 \. 0 " force-response-1 .0
BrowserMatch " J a v a / 1 \. 0 " force-response-1 .0
BrowserMatch " J D K / 1 \. 0 " force-response-1 .0
BrowserMatch " M i c r o s o f t D a t a A c c e s s I n t e r n e t P u b l i s h i n g P r o v i d e r " redirect-carefully
BrowserMatch " ^ W e b D r i v e " redirect-carefully
BrowserMatch " ^ W e b D A V F S / 1 . [ 0 1 2 ] " redirect-carefully
BrowserMatch " ^ g n o m e - v f s " redirect-carefully
'' ;
sslConf = ''
2014-11-06 20:58:26 +00:00
SSLSessionCache $ { if version24 then " s h m c b " else " s h m " }: $ { mainCfg . stateDir } /ssl_scache ( 512000 )
2007-12-12 13:58:15 +00:00
2014-11-06 20:58:26 +00:00
$ { if version24 then " M u t e x " else " S S L M u t e x " } posixsem
2007-12-12 13:58:15 +00:00
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
2015-03-09 13:09:43 +00:00
2019-01-09 16:30:19 +00:00
SSLProtocol $ { mainCfg . sslProtocols }
SSLCipherSuite $ { mainCfg . sslCiphers }
2015-10-04 22:13:50 +01:00
SSLHonorCipherOrder on
2007-12-12 13:58:15 +00:00
'' ;
mimeConf = ''
TypesConfig $ { httpd } /conf/mime.types
AddType application/x-x509-ca-cert . crt
AddType application/x-pkcs7-crl . crl
2008-02-05 16:25:07 +00:00
AddType application/x-httpd-php . php . phtml
2007-12-12 13:58:15 +00:00
< IfModule mod_mime_magic . c >
MIMEMagicFile $ { httpd } /conf/magic
< /IfModule >
'' ;
2008-02-14 13:20:26 +00:00
perServerConf = isMainServer : cfg : let
2007-12-12 13:58:15 +00:00
2008-02-14 13:20:26 +00:00
serverInfo = makeServerInfo cfg ;
2007-12-12 13:58:15 +00:00
2008-02-14 13:20:26 +00:00
subservices = callSubservices serverInfo cfg . extraSubservices ;
2008-02-05 16:25:07 +00:00
2014-02-25 12:44:45 +00:00
maybeDocumentRoot = fold ( svc : acc :
if acc == null then svc . documentRoot else assert svc . documentRoot == null ; acc
) null ( [ cfg ] ++ subservices ) ;
documentRoot = if maybeDocumentRoot != null then maybeDocumentRoot else
2014-06-30 13:56:10 +01:00
pkgs . runCommand " e m p t y " { } " m k d i r - p $ o u t " ;
2008-02-14 13:20:26 +00:00
documentRootConf = ''
DocumentRoot " ${ documentRoot } "
< Directory " ${ documentRoot } " >
Options Indexes FollowSymLinks
AllowOverride None
2012-10-17 15:57:18 +01:00
$ { allGranted }
2008-02-14 13:20:26 +00:00
< /Directory >
'' ;
2014-09-18 17:48:28 +01:00
robotsTxt =
2014-09-18 18:04:59 +01:00
concatStringsSep " \n " ( filter ( x : x != " " ) (
2014-09-18 17:48:28 +01:00
# If this is a vhost, the include the entries for the main server as well.
2014-09-18 18:04:59 +01:00
( if isMainServer then [ ] else [ mainCfg . robotsEntries ] ++ map ( svc : svc . robotsEntries ) mainSubservices )
++ [ cfg . robotsEntries ]
++ ( map ( svc : svc . robotsEntries ) subservices ) ) ) ;
2008-02-14 13:20:26 +00:00
in ''
2016-11-12 14:35:32 +00:00
$ { concatStringsSep " \n " ( map ( n : " S e r v e r N a m e ${ n } " ) serverInfo . canonicalNames ) }
2008-02-14 13:20:26 +00:00
2008-02-19 14:41:20 +00:00
$ { concatMapStrings ( alias : " S e r v e r A l i a s ${ alias } \n " ) cfg . serverAliases }
2013-10-29 13:03:39 +00:00
$ { if cfg . sslServerCert != null then ''
2008-04-24 12:56:38 +01:00
SSLCertificateFile $ { cfg . sslServerCert }
SSLCertificateKeyFile $ { cfg . sslServerKey }
2015-03-27 12:11:30 +00:00
$ { if cfg . sslServerChain != null then ''
SSLCertificateChainFile $ { cfg . sslServerChain }
'' e l s e " " }
2008-04-24 12:56:38 +01:00
'' e l s e " " }
2011-09-14 19:20:50 +01:00
2008-04-24 12:56:38 +01:00
$ { if cfg . enableSSL then ''
SSLEngine on
'' e l s e i f e n a b l e S S L t h e n / * i . e . , S S L i s e n a b l e d f o r s o m e h o s t , b u t n o t t h i s o n e * /
''
SSLEngine off
'' e l s e " " }
2013-10-29 13:03:39 +00:00
$ { if isMainServer || cfg . adminAddr != null then ''
2008-02-14 13:20:26 +00:00
ServerAdmin $ { cfg . adminAddr }
'' e l s e " " }
2008-02-20 13:29:08 +00:00
$ { if ! isMainServer && mainCfg . logPerVirtualHost then ''
2019-01-31 02:04:58 +00:00
ErrorLog $ { mainCfg . logDir } /error- $ { cfg . hostName } . log
CustomLog $ { mainCfg . logDir } /access- $ { cfg . hostName } . log $ { cfg . logFormat }
2008-02-20 13:29:08 +00:00
'' e l s e " " }
2014-09-18 17:48:28 +01:00
$ { optionalString ( robotsTxt != " " ) ''
Alias /robots.txt $ { pkgs . writeText " r o b o t s . t x t " robotsTxt }
'' }
2008-02-14 13:20:26 +00:00
2014-02-25 12:44:45 +00:00
$ { if isMainServer || maybeDocumentRoot != null then documentRootConf else " " }
2008-02-14 13:20:26 +00:00
2008-04-24 12:56:38 +01:00
$ { if cfg . enableUserDir then ''
2011-09-14 19:20:50 +01:00
2008-04-24 12:56:38 +01:00
UserDir public_html
UserDir disabled root
2011-09-14 19:20:50 +01:00
2008-04-24 12:56:38 +01:00
< Directory " / h o m e / * / p u b l i c _ h t m l " >
AllowOverride FileInfo AuthConfig Limit Indexes
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
< Limit GET POST OPTIONS >
2012-10-17 15:57:18 +01:00
$ { allGranted }
2008-04-24 12:56:38 +01:00
< /Limit >
< LimitExcept GET POST OPTIONS >
2012-10-17 15:57:18 +01:00
$ { allDenied }
2008-04-24 12:56:38 +01:00
< /LimitExcept >
< /Directory >
2011-09-14 19:20:50 +01:00
2008-04-24 12:56:38 +01:00
'' e l s e " " }
2013-11-11 07:18:46 +00:00
$ { if cfg . globalRedirect != null && cfg . globalRedirect != " " then ''
2008-04-24 12:56:38 +01:00
RedirectPermanent / $ { cfg . globalRedirect }
'' e l s e " " }
$ {
let makeFileConf = elem : ''
Alias $ { elem . urlPath } $ { elem . file }
'' ;
in concatMapStrings makeFileConf cfg . servedFiles
}
2008-02-14 13:20:26 +00:00
$ {
let makeDirConf = elem : ''
Alias $ { elem . urlPath } $ { elem . dir } /
< Directory $ { elem . dir } >
2008-04-24 12:56:38 +01:00
Options + Indexes
2012-10-17 15:57:18 +01:00
$ { allGranted }
2008-04-24 12:56:38 +01:00
AllowOverride All
2008-02-14 13:20:26 +00:00
< /Directory >
'' ;
in concatMapStrings makeDirConf cfg . servedDirs
}
$ { concatMapStrings ( svc : svc . extraConfig ) subservices }
2008-02-18 15:00:26 +00:00
$ { cfg . extraConfig }
2008-02-05 16:25:07 +00:00
'' ;
2011-09-14 19:20:50 +01:00
2012-07-23 20:48:21 +01:00
confFile = pkgs . writeText " h t t p d . c o n f " ''
2011-09-14 19:20:50 +01:00
2007-12-12 13:58:15 +00:00
ServerRoot $ { httpd }
2012-10-17 16:47:30 +01:00
$ { optionalString version24 ''
2012-10-17 16:38:43 +01:00
DefaultRuntimeDir $ { mainCfg . stateDir } /runtime
'' }
2008-04-24 12:56:38 +01:00
PidFile $ { mainCfg . stateDir } /httpd.pid
2007-12-12 13:58:15 +00:00
2012-07-06 19:23:55 +01:00
$ { optionalString ( mainCfg . multiProcessingModule != " p r e f o r k " ) ''
# mod_cgid requires this.
ScriptSock $ { mainCfg . stateDir } /cgisock
'' }
2007-12-12 13:58:15 +00:00
< IfModule prefork . c >
2010-04-21 21:55:57 +01:00
MaxClients $ { toString mainCfg . maxClients }
MaxRequestsPerChild $ { toString mainCfg . maxRequestsPerChild }
2007-12-12 13:58:15 +00:00
< /IfModule >
2008-04-19 11:21:42 +01:00
$ { let
2016-11-12 14:35:32 +00:00
listen = concatMap getListen allHosts ;
toStr = listen : " L i s t e n ${ listenToString listen } \n " ;
uniqueListen = uniqList { inputList = map toStr listen ; } ;
in concatStrings uniqueListen
2008-04-19 11:21:42 +01:00
}
2007-12-12 13:58:15 +00:00
2008-04-24 12:56:38 +01:00
User $ { mainCfg . user }
Group $ { mainCfg . group }
2007-12-12 13:58:15 +00:00
2008-02-05 16:25:07 +00:00
$ { let
load = { name , path }: " L o a d M o d u l e ${ name } _ m o d u l e ${ path } \n " ;
allModules =
2010-07-14 13:58:38 +01:00
concatMap ( svc : svc . extraModulesPre ) allSubservices
++ map ( name : { inherit name ; path = " ${ httpd } / m o d u l e s / m o d _ ${ name } . s o " ; } ) apacheModules
2016-02-06 21:27:48 +00:00
++ optional mainCfg . enableMellon { name = " a u t h _ m e l l o n " ; path = " ${ pkgs . apacheHttpdPackages . mod_auth_mellon } / m o d u l e s / m o d _ a u t h _ m e l l o n . s o " ; }
2016-06-22 13:24:25 +01:00
++ optional enablePHP { name = " p h p ${ phpMajorVersion } " ; path = " ${ php } / m o d u l e s / l i b p h p ${ phpMajorVersion } . s o " ; }
2016-12-15 11:36:07 +00:00
++ optional enablePerl { name = " p e r l " ; path = " ${ mod_perl } / m o d u l e s / m o d _ p e r l . s o " ; }
2011-09-14 19:20:50 +01:00
++ concatMap ( svc : svc . extraModules ) allSubservices
2010-07-14 13:58:38 +01:00
++ extraForeignModules ;
2008-02-14 13:20:26 +00:00
in concatMapStrings load allModules
2007-12-12 13:58:15 +00:00
}
AddHandler type-map var
< Files ~ " ^ \. h t " >
2012-10-17 15:57:18 +01:00
$ { allDenied }
2007-12-12 13:58:15 +00:00
< /Files >
$ { mimeConf }
$ { loggingConf }
$ { browserHacks }
2007-12-12 15:30:17 +00:00
Include $ { httpd } /conf/extra/httpd-default.conf
2007-12-12 13:58:15 +00:00
Include $ { httpd } /conf/extra/httpd-autoindex.conf
Include $ { httpd } /conf/extra/httpd-multilang-errordoc.conf
Include $ { httpd } /conf/extra/httpd-languages.conf
2011-09-14 19:20:50 +01:00
2019-02-07 19:13:45 +00:00
TraceEnable off
2008-04-24 12:56:38 +01:00
$ { if enableSSL then sslConf else " " }
2007-12-12 13:58:15 +00:00
2008-02-05 16:25:07 +00:00
# Fascist default - deny access to everything.
2007-12-12 13:58:15 +00:00
< Directory / >
Options FollowSymLinks
AllowOverride None
2012-10-17 15:57:18 +01:00
$ { allDenied }
2008-02-14 07:42:52 +00:00
< /Directory >
# But do allow access to files in the store so that we don't have
# to generate <Directory> clauses for every generated file that we
# want to serve.
2011-10-30 15:19:58 +00:00
< Directory /nix/store >
2012-10-17 15:57:18 +01:00
$ { allGranted }
2007-12-12 13:58:15 +00:00
< /Directory >
2008-02-14 13:20:26 +00:00
# Generate directives for the main server.
2008-04-24 12:56:38 +01:00
$ { perServerConf true mainCfg }
2011-09-14 19:20:50 +01:00
2008-02-14 13:20:26 +00:00
# Always enable virtual hosts; it doesn't seem to hurt.
2008-04-24 19:32:05 +01:00
$ { let
2016-11-12 14:35:32 +00:00
listen = concatMap getListen allHosts ;
uniqueListen = uniqList { inputList = listen ; } ;
directives = concatMapStrings ( listen : " N a m e V i r t u a l H o s t ${ listenToString listen } \n " ) uniqueListen ;
2012-10-17 16:47:30 +01:00
in optionalString ( ! version24 ) directives
2008-04-24 19:32:05 +01:00
}
2007-12-12 15:30:17 +00:00
2008-02-14 13:20:26 +00:00
$ { let
2008-04-24 12:56:38 +01:00
makeVirtualHost = vhost : ''
2016-11-12 14:35:32 +00:00
< VirtualHost $ { concatStringsSep " " ( map listenToString ( getListen vhost ) ) } >
2008-04-24 12:56:38 +01:00
$ { perServerConf false vhost }
2008-04-19 11:21:42 +01:00
< /VirtualHost >
2008-04-24 12:56:38 +01:00
'' ;
2013-10-28 20:58:32 +00:00
in concatMapStrings makeVirtualHost mainCfg . virtualHosts
2008-04-24 12:56:38 +01:00
}
2007-12-12 13:58:15 +00:00
'' ;
2010-02-15 19:02:42 +00:00
2014-05-20 10:50:39 +01:00
enablePHP = mainCfg . enablePHP || any ( svc : svc . enablePHP ) allSubservices ;
2010-07-14 13:58:38 +01:00
2016-12-15 11:36:07 +00:00
enablePerl = mainCfg . enablePerl || any ( svc : svc . enablePerl ) allSubservices ;
2010-07-14 13:58:38 +01:00
2010-02-15 19:02:42 +00:00
# Generate the PHP configuration file. Should probably be factored
# out into a separate module.
phpIni = pkgs . runCommand " p h p . i n i "
{ options = concatStringsSep " \n "
( [ mainCfg . phpOptions ] ++ ( map ( svc : svc . phpOptions ) allSubservices ) ) ;
}
''
2016-04-29 07:26:20 +01:00
cat $ { php } /etc/php.ini > $ out
2010-02-15 19:02:42 +00:00
echo " $ o p t i o n s " > > $ out
'' ;
2007-12-12 13:58:15 +00:00
in
2009-07-15 12:19:11 +01:00
{
###### interface
options = {
2011-09-14 19:20:50 +01:00
2009-07-15 12:19:11 +01:00
services . httpd = {
2011-09-14 19:20:50 +01:00
2009-07-15 12:19:11 +01:00
enable = mkOption {
2013-10-29 13:03:39 +00:00
type = types . bool ;
2009-07-15 12:19:11 +01:00
default = false ;
2013-10-29 13:03:39 +00:00
description = " W h e t h e r t o e n a b l e t h e A p a c h e H T T P S e r v e r . " ;
2009-07-15 12:19:11 +01:00
} ;
2012-07-24 00:01:48 +01:00
package = mkOption {
2014-02-27 12:22:04 +00:00
type = types . package ;
2014-11-06 13:27:02 +00:00
default = pkgs . apacheHttpd ;
2016-01-17 18:34:55 +00:00
defaultText = " p k g s . a p a c h e H t t p d " ;
2013-10-29 13:03:39 +00:00
description = ''
2012-07-23 20:48:21 +01:00
Overridable attribute of the Apache HTTP Server package to use .
2013-10-29 13:03:39 +00:00
'' ;
2012-07-23 20:48:21 +01:00
} ;
configFile = mkOption {
2013-10-29 13:03:39 +00:00
type = types . path ;
2012-07-23 20:48:21 +01:00
default = confFile ;
2016-01-17 18:34:55 +00:00
defaultText = " c o n f F i l e " ;
example = literalExample '' p k g s . w r i t e T e x t " h t t p d . c o n f " " # m y c u s t o m c o n f i g f i l e . . . " '' ;
2013-10-29 13:03:39 +00:00
description = ''
Override the configuration file used by Apache . By default ,
NixOS generates one automatically .
'' ;
2012-07-23 20:48:21 +01:00
} ;
2009-11-06 16:23:25 +00:00
extraConfig = mkOption {
2013-10-29 13:03:39 +00:00
type = types . lines ;
2009-11-06 16:23:25 +00:00
default = " " ;
2013-10-29 13:03:39 +00:00
description = ''
Cnfiguration lines appended to the generated Apache
configuration file . Note that this mechanism may not work
when <option> configFile < /option > is overridden .
'' ;
2009-11-06 16:23:25 +00:00
} ;
2009-07-15 12:19:11 +01:00
extraModules = mkOption {
2013-10-29 13:03:39 +00:00
type = types . listOf types . unspecified ;
2009-07-15 12:19:11 +01:00
default = [ ] ;
2014-04-19 21:59:25 +01:00
example = literalExample '' [ " p r o x y _ c o n n e c t " { n a m e = " p h p 5 " ; p a t h = " ''$ { p k g s . p h p } / m o d u l e s / l i b p h p 5 . s o " ; } ] '' ;
2009-07-15 12:19:11 +01:00
description = ''
2013-10-29 13:03:39 +00:00
Additional Apache modules to be used . These can be
specified as a string in the case of modules distributed
with Apache , or as an attribute set specifying the
2009-07-15 12:19:11 +01:00
<varname> name < /varname > and <varname> path < /varname > of the
module .
'' ;
} ;
logPerVirtualHost = mkOption {
2013-10-29 13:03:39 +00:00
type = types . bool ;
2009-07-15 12:19:11 +01:00
default = false ;
2013-10-29 13:03:39 +00:00
description = ''
2009-07-15 12:19:11 +01:00
If enabled , each virtual host gets its own
2019-02-20 12:43:25 +00:00
<filename> access . log < /filename > and
<filename> error . log < /filename > , namely suffixed by the
2009-07-15 12:19:11 +01:00
<option> hostName < /option > of the virtual host .
2013-10-29 13:03:39 +00:00
'' ;
2009-07-15 12:19:11 +01:00
} ;
user = mkOption {
2013-10-29 13:03:39 +00:00
type = types . str ;
2009-07-15 12:19:11 +01:00
default = " w w w r u n " ;
2013-10-29 13:03:39 +00:00
description = ''
2009-07-15 12:19:11 +01:00
User account under which httpd runs . The account is created
automatically if it doesn't exist .
2013-10-29 13:03:39 +00:00
'' ;
2009-07-15 12:19:11 +01:00
} ;
group = mkOption {
2013-10-29 13:03:39 +00:00
type = types . str ;
2009-07-15 12:19:11 +01:00
default = " w w w r u n " ;
2013-10-29 13:03:39 +00:00
description = ''
2009-07-15 12:19:11 +01:00
Group under which httpd runs . The account is created
automatically if it doesn't exist .
2013-10-29 13:03:39 +00:00
'' ;
2009-07-15 12:19:11 +01:00
} ;
logDir = mkOption {
2013-10-29 13:03:39 +00:00
type = types . path ;
2009-07-15 12:19:11 +01:00
default = " / v a r / l o g / h t t p d " ;
2013-10-29 13:03:39 +00:00
description = ''
2009-07-15 12:19:11 +01:00
Directory for Apache's log files . It is created automatically .
2013-10-29 13:03:39 +00:00
'' ;
2009-07-15 12:19:11 +01:00
} ;
stateDir = mkOption {
2013-10-29 13:03:39 +00:00
type = types . path ;
default = " / r u n / h t t p d " ;
description = ''
2009-07-15 12:19:11 +01:00
Directory for Apache's transient runtime state ( such as PID
files ) . It is created automatically . Note that the default ,
2013-10-29 13:03:39 +00:00
<filename> /run/httpd < /filename > , is deleted at boot time .
'' ;
2009-07-15 12:19:11 +01:00
} ;
2009-11-06 16:23:25 +00:00
virtualHosts = mkOption {
2013-10-28 20:58:32 +00:00
type = types . listOf ( types . submodule (
{ options = import ./per-server-options.nix {
2014-04-14 15:26:48 +01:00
inherit lib ;
2013-10-28 20:58:32 +00:00
forMainServer = false ;
} ;
} ) ) ;
2009-11-06 16:23:25 +00:00
default = [ ] ;
example = [
{ hostName = " f o o " ;
documentRoot = " / d a t a / w e b r o o t - f o o " ;
}
{ hostName = " b a r " ;
documentRoot = " / d a t a / w e b r o o t - b a r " ;
}
] ;
description = ''
Specification of the virtual hosts served by Apache . Each
element should be an attribute set specifying the
configuration of the virtual host . The available options
are the non-global options permissible for the main host .
'' ;
} ;
2016-02-06 21:27:48 +00:00
enableMellon = mkOption {
type = types . bool ;
default = false ;
description = " W h e t h e r t o e n a b l e t h e m o d _ a u t h _ m e l l o n m o d u l e . " ;
} ;
2014-05-20 10:50:39 +01:00
enablePHP = mkOption {
type = types . bool ;
default = false ;
description = " W h e t h e r t o e n a b l e t h e P H P m o d u l e . " ;
} ;
2016-06-22 13:24:25 +01:00
phpPackage = mkOption {
type = types . package ;
default = pkgs . php ;
defaultText = " p k g s . p h p " ;
description = ''
Overridable attribute of the PHP package to use .
'' ;
} ;
2016-12-15 11:36:07 +00:00
enablePerl = mkOption {
type = types . bool ;
default = false ;
description = " W h e t h e r t o e n a b l e t h e P e r l m o d u l e ( m o d _ p e r l ) . " ;
} ;
2010-02-15 19:02:42 +00:00
phpOptions = mkOption {
2013-10-29 13:03:39 +00:00
type = types . lines ;
2010-02-15 19:02:42 +00:00
default = " " ;
example =
''
date . timezone = " C E T "
'' ;
description =
" O p t i o n s a p p e n d e d t o t h e P H P c o n f i g u r a t i o n f i l e < f i l e n a m e > p h p . i n i < / f i l e n a m e > . " ;
2010-01-07 09:01:40 +00:00
} ;
2012-07-06 19:23:55 +01:00
multiProcessingModule = mkOption {
2013-10-29 13:03:39 +00:00
type = types . str ;
2012-07-06 19:23:55 +01:00
default = " p r e f o r k " ;
example = " w o r k e r " ;
description =
''
Multi-processing module to be used by Apache . Available
modules are <literal> prefork < /literal > ( the default ;
handles each request in a separate child process ) ,
<literal> worker < /literal > ( hybrid approach that starts a
number of child processes each running a number of
threads ) and <literal> event < /literal > ( a recent variant of
<literal> worker < /literal > that handles persistent
connections more efficiently ) .
'' ;
} ;
2010-04-21 21:55:57 +01:00
maxClients = mkOption {
2013-10-29 13:03:39 +00:00
type = types . int ;
2010-04-21 21:55:57 +01:00
default = 150 ;
example = 8 ;
description = " M a x i m u m n u m b e r o f h t t p d p r o c e s s e s ( p r e f o r k ) " ;
} ;
maxRequestsPerChild = mkOption {
2013-10-29 13:03:39 +00:00
type = types . int ;
2010-04-21 21:55:57 +01:00
default = 0 ;
example = 500 ;
description =
" M a x i m u m n u m b e r o f h t t p d r e q u e s t s a n s w e r e d p e r h t t p d c h i l d ( p r e f o r k ) , 0 m e a n s u n l i m i t e d " ;
} ;
2019-01-09 16:30:19 +00:00
sslCiphers = mkOption {
type = types . str ;
default = " H I G H : ! a N U L L : ! M D 5 : ! E X P " ;
description = " C i p h e r S u i t e a v a i l a b l e f o r n e g o t i a t i o n i n S S L p r o x y h a n d s h a k e . " ;
} ;
sslProtocols = mkOption {
type = types . str ;
2019-02-07 19:05:44 +00:00
default = " A l l - S S L v 2 - S S L v 3 - T L S v 1 " ;
example = " A l l - S S L v 2 - S S L v 3 " ;
2019-01-09 16:30:19 +00:00
description = " A l l o w e d S S L / T L S p r o t o c o l v e r s i o n s . " ;
} ;
2009-11-06 16:23:25 +00:00
}
# Include the options shared between the main server and virtual hosts.
// ( import ./per-server-options.nix {
2014-04-14 15:26:48 +01:00
inherit lib ;
2009-11-06 16:23:25 +00:00
forMainServer = true ;
} ) ;
2009-07-15 12:19:11 +01:00
} ;
###### implementation
config = mkIf config . services . httpd . enable {
2014-11-06 13:27:02 +00:00
2013-11-06 01:32:22 +00:00
assertions = [ { assertion = mainCfg . enableSSL == true
2013-11-11 04:08:36 +00:00
-> mainCfg . sslServerCert != null
&& mainCfg . sslServerKey != null ;
2014-11-06 13:27:02 +00:00
message = " S S L i s e n a b l e d f o r h t t p d , b u t s s l S e r v e r C e r t a n d / o r s s l S e r v e r K e y h a v e n ' t b e e n s p e c i f i e d . " ; }
2013-11-06 01:32:22 +00:00
] ;
2009-07-15 12:19:11 +01:00
2018-07-13 01:59:00 +01:00
warnings = map ( cfg : '' a p a c h e - h t t p d ' s p o r t o p t i o n i s d e p r e c a t e d . U s e l i s t e n = [ { / * i p = " * " ; * / p o r t = ${ toString cfg . port } ; } ] ; i n s t e a d '' ) ( lib . filter ( cfg : cfg . port != 0 ) allHosts ) ;
2016-11-12 14:35:32 +00:00
2018-06-30 00:58:35 +01:00
users . users = optionalAttrs ( mainCfg . user == " w w w r u n " ) ( singleton
2012-08-03 15:52:53 +01:00
{ name = " w w w r u n " ;
2014-06-11 10:36:15 +01:00
group = mainCfg . group ;
2009-03-06 12:26:41 +00:00
description = " A p a c h e h t t p d u s e r " ;
2012-08-03 16:05:25 +01:00
uid = config . ids . uids . wwwrun ;
2014-06-11 10:17:42 +01:00
} ) ;
2009-07-15 12:19:11 +01:00
2018-06-30 00:58:35 +01:00
users . groups = optionalAttrs ( mainCfg . group == " w w w r u n " ) ( singleton
2012-08-03 15:52:53 +01:00
{ name = " w w w r u n " ;
2012-08-03 16:05:25 +01:00
gid = config . ids . gids . wwwrun ;
2014-06-11 10:17:42 +01:00
} ) ;
2007-12-12 13:58:15 +00:00
2009-07-15 12:19:11 +01:00
environment . systemPackages = [ httpd ] ++ concatMap ( svc : svc . extraPath ) allSubservices ;
2009-03-06 12:26:41 +00:00
2010-02-15 19:02:42 +00:00
services . httpd . phpOptions =
''
; Needed for PHP's mail ( ) function .
sendmail_path = sendmail - t - i
2019-02-07 19:25:55 +00:00
; Don't advertise PHP
expose_php = off
2017-10-31 16:31:02 +00:00
'' + o p t i o n a l S t r i n g ( ! i s N u l l c o n f i g . t i m e . t i m e Z o n e ) ''
2010-02-15 19:02:42 +00:00
; Apparently PHP doesn't use $ TZ .
date . timezone = " ${ config . time . timeZone } "
'' ;
2013-01-16 11:33:18 +00:00
systemd . services . httpd =
2012-06-16 05:19:43 +01:00
{ description = " A p a c h e H T T P D " ;
2009-10-12 18:09:38 +01:00
2012-08-14 23:15:37 +01:00
wantedBy = [ " m u l t i - u s e r . t a r g e t " ] ;
2014-03-17 14:01:10 +00:00
wants = [ " k e y s . t a r g e t " ] ;
2012-11-01 22:32:12 +00:00
after = [ " n e t w o r k . t a r g e t " " f s . t a r g e t " " p o s t g r e s q l . s e r v i c e " " k e y s . t a r g e t " ] ;
2009-10-12 18:09:38 +01:00
2011-11-25 16:32:54 +00:00
path =
[ httpd pkgs . coreutils pkgs . gnugrep ]
++ # Needed for PHP's mail() function. !!! Probably the
# ssmtp module should export the path to sendmail in
# some way.
optional config . networking . defaultMailServer . directDelivery pkgs . ssmtp
++ concatMap ( svc : svc . extraServerPath ) allSubservices ;
2011-08-09 15:07:44 +01:00
2011-11-25 16:32:54 +00:00
environment =
2014-01-31 20:18:24 +00:00
optionalAttrs enablePHP { PHPRC = phpIni ; }
2016-02-06 21:27:48 +00:00
// optionalAttrs mainCfg . enableMellon { LD_LIBRARY_PATH = " ${ pkgs . xmlsec } / l i b " ; }
2014-01-31 20:18:24 +00:00
// ( listToAttrs ( concatMap ( svc : svc . globalEnvVars ) allSubservices ) ) ;
2009-10-12 18:09:38 +01:00
preStart =
''
2012-07-09 15:27:39 +01:00
mkdir - m 0750 - p $ { mainCfg . stateDir }
2013-11-18 16:00:24 +00:00
[ $ ( id - u ) != 0 ] || chown root . ${ mainCfg . group } $ { mainCfg . stateDir }
2012-10-17 16:47:30 +01:00
$ { optionalString version24 ''
2012-10-17 16:38:43 +01:00
mkdir - m 0750 - p " ${ mainCfg . stateDir } / r u n t i m e "
2013-11-18 16:00:24 +00:00
[ $ ( id - u ) != 0 ] || chown root . ${ mainCfg . group } " ${ mainCfg . stateDir } / r u n t i m e "
2012-10-17 16:38:43 +01:00
'' }
2009-10-12 18:09:38 +01:00
mkdir - m 0700 - p $ { mainCfg . logDir }
# Get rid of old semaphores. These tend to accumulate across
# server restarts, eventually preventing it from restarting
2013-08-10 22:07:13 +01:00
# successfully.
2009-10-12 18:09:38 +01:00
for i in $ ( $ { pkgs . utillinux } /bin/ipcs - s | grep ' $ { mainCfg . user } ' | cut - f2 - d ' ' ) ; do
$ { pkgs . utillinux } /bin/ipcrm - s $ i
done
# Run the startup hooks for the subservices.
for i in $ { toString ( map ( svn : svn . startupScript ) allSubservices ) } ; do
echo Running Apache startup hook $ i . . .
$ i
done
'' ;
2013-07-09 14:08:48 +01:00
serviceConfig . ExecStart = " @ ${ httpd } / b i n / h t t p d h t t p d - f ${ httpdConf } " ;
2012-11-01 22:32:12 +00:00
serviceConfig . ExecStop = " ${ httpd } / b i n / h t t p d - f ${ httpdConf } - k g r a c e f u l - s t o p " ;
2016-04-07 16:52:48 +01:00
serviceConfig . ExecReload = " ${ httpd } / b i n / h t t p d - f ${ httpdConf } - k g r a c e f u l " ;
2013-07-09 14:08:48 +01:00
serviceConfig . Type = " f o r k i n g " ;
2013-11-18 16:00:24 +00:00
serviceConfig . PIDFile = " ${ mainCfg . stateDir } / h t t p d . p i d " ;
2012-11-01 22:32:12 +00:00
serviceConfig . Restart = " a l w a y s " ;
2015-01-19 21:47:44 +00:00
serviceConfig . RestartSec = " 5 s " ;
2009-10-12 18:09:38 +01:00
} ;
2009-03-06 12:26:41 +00:00
} ;
2007-12-12 13:58:15 +00:00
}