diff options
author | Vladimír Čunát <vcunat@gmail.com> | 2015-04-26 22:52:08 +0200 |
---|---|---|
committer | Vladimír Čunát <vcunat@gmail.com> | 2015-04-26 22:52:08 +0200 |
commit | 30f31c9afcc34336d1d47c62ad4ed39d2dee402a (patch) | |
tree | e3549d198c833f11e5f6062e10a3fefb9d25a670 /nixos/modules/services | |
parent | c1cc2348e4d49ab742e964593a7f74cc53c7f9b7 (diff) | |
parent | 2cb3dc68120701406ac48d7a4da5ff097b092f85 (diff) | |
download | nixlib-30f31c9afcc34336d1d47c62ad4ed39d2dee402a.tar nixlib-30f31c9afcc34336d1d47c62ad4ed39d2dee402a.tar.gz nixlib-30f31c9afcc34336d1d47c62ad4ed39d2dee402a.tar.bz2 nixlib-30f31c9afcc34336d1d47c62ad4ed39d2dee402a.tar.lz nixlib-30f31c9afcc34336d1d47c62ad4ed39d2dee402a.tar.xz nixlib-30f31c9afcc34336d1d47c62ad4ed39d2dee402a.tar.zst nixlib-30f31c9afcc34336d1d47c62ad4ed39d2dee402a.zip |
Merge 'master' into staging
(relatively simple conflicts)
Diffstat (limited to 'nixos/modules/services')
27 files changed, 1197 insertions, 57 deletions
diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix index d9b5bf7b5e6f..06ba4b9b5acb 100644 --- a/nixos/modules/services/audio/mpd.nix +++ b/nixos/modules/services/audio/mpd.nix @@ -11,7 +11,7 @@ let mpdConf = pkgs.writeText "mpd.conf" '' music_directory "${cfg.musicDirectory}" playlist_directory "${cfg.dataDir}/playlists" - db_file "${cfg.dataDir}/tag_cache" + db_file "${cfg.dbFile}" state_file "${cfg.dataDir}/state" sticker_file "${cfg.dataDir}/sticker.sql" log_file "syslog" @@ -93,6 +93,14 @@ in { }; }; + + dbFile = mkOption { + type = types.str; + default = "${cfg.dataDir}/tag_cache"; + description = '' + The path to MPD's database. + ''; + }; }; }; diff --git a/nixos/modules/services/backup/tarsnap.nix b/nixos/modules/services/backup/tarsnap.nix index 155161945cd9..f8eeb4378443 100644 --- a/nixos/modules/services/backup/tarsnap.nix +++ b/nixos/modules/services/backup/tarsnap.nix @@ -5,20 +5,21 @@ with lib; let cfg = config.services.tarsnap; - optionalNullStr = e: v: if e == null then "" else v; - configFile = cfg: '' cachedir ${config.services.tarsnap.cachedir} keyfile ${config.services.tarsnap.keyfile} ${optionalString cfg.nodump "nodump"} ${optionalString cfg.printStats "print-stats"} ${optionalString cfg.printStats "humanize-numbers"} - ${optionalNullStr cfg.checkpointBytes "checkpoint-bytes "+cfg.checkpointBytes} + ${optionalString (cfg.checkpointBytes != null) ("checkpoint-bytes "+cfg.checkpointBytes)} ${optionalString cfg.aggressiveNetworking "aggressive-networking"} ${concatStringsSep "\n" (map (v: "exclude "+v) cfg.excludes)} ${concatStringsSep "\n" (map (v: "include "+v) cfg.includes)} ${optionalString cfg.lowmem "lowmem"} ${optionalString cfg.verylowmem "verylowmem"} + ${optionalString (cfg.maxbw != null) ("maxbw "+toString cfg.maxbw)} + ${optionalString (cfg.maxbwRateUp != null) ("maxbw-rate-up "+toString cfg.maxbwRateUp)} + ${optionalString (cfg.maxbwRateDown != null) ("maxbw-rate-down "+toString cfg.maxbwRateDown)} ''; in { @@ -166,6 +167,33 @@ in slowing down the archiving process. ''; }; + + maxbw = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + Abort archival if upstream bandwidth usage in bytes + exceeds this threshold. + ''; + }; + + maxbwRateUp = mkOption { + type = types.nullOr types.int; + default = null; + example = literalExample "25 * 1000"; + description = '' + Upload bandwidth rate limit in bytes. + ''; + }; + + maxbwRateDown = mkOption { + type = types.nullOr types.int; + default = null; + example = literalExample "50 * 1000"; + description = '' + Download bandwidth rate limit in bytes. + ''; + }; }; } )); diff --git a/nixos/modules/services/logging/fluentd.nix b/nixos/modules/services/logging/fluentd.nix index 61eeec504e0d..3aa27a152669 100644 --- a/nixos/modules/services/logging/fluentd.nix +++ b/nixos/modules/services/logging/fluentd.nix @@ -33,6 +33,7 @@ in { wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = "${pkgs.fluentd}/bin/fluentd -c ${pkgs.writeText "fluentd.conf" cfg.config}"; + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; }; }; }; diff --git a/nixos/modules/services/misc/etcd.nix b/nixos/modules/services/misc/etcd.nix index 284361a04d9e..26d2753879d0 100644 --- a/nixos/modules/services/misc/etcd.nix +++ b/nixos/modules/services/misc/etcd.nix @@ -11,7 +11,7 @@ in { enable = mkOption { description = "Whether to enable etcd."; default = false; - type = types.uniq types.bool; + type = types.bool; }; name = mkOption { diff --git a/nixos/modules/services/misc/ihaskell.nix b/nixos/modules/services/misc/ihaskell.nix new file mode 100644 index 000000000000..7f7f981de498 --- /dev/null +++ b/nixos/modules/services/misc/ihaskell.nix @@ -0,0 +1,76 @@ +{ pkgs, lib, config, ... }: + +with lib; + +let + + cfg = config.services.ihaskell; + ihaskell = pkgs.ihaskell.override { + inherit (cfg.haskellPackages) ihaskell ghcWithPackages; + packages = self: cfg.extraPackages self; + }; + +in + +{ + options = { + services.ihaskell = { + enable = mkOption { + default = false; + example = true; + description = "Autostart an IHaskell notebook service."; + }; + + haskellPackages = mkOption { + default = pkgs.haskellngPackages; + defaultText = "pkgs.haskellngPackages"; + example = literalExample "pkgs.haskell-ng.packages.ghc784"; + description = '' + haskellPackages used to build IHaskell and other packages. + This can be used to change the GHC version used to build + IHaskell and the packages listed in + <varname>extraPackages</varname>. + ''; + }; + + extraPackages = mkOption { + default = self: []; + example = literalExample '' + haskellPackages: [ + haskellPackages.wreq + haskellPackages.lens + ] + ''; + description = '' + Extra packages available to ghc when running ihaskell. The + value must be a function which receives the attrset defined + in <varname>haskellPackages</varname> as the sole argument. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + + users.extraUsers.ihaskell = { + group = config.users.extraGroups.ihaskell.name; + description = "IHaskell user"; + home = "/var/lib/ihaskell"; + createHome = true; + uid = config.ids.uids.ihaskell; + }; + + users.extraGroups.ihaskell.gid = config.ids.gids.ihaskell; + + systemd.services.ihaskell = { + description = "IHaskell notebook instance"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + serviceConfig = { + User = config.users.extraUsers.ihaskell.name; + Group = config.users.extraGroups.ihaskell.name; + ExecStart = "${pkgs.stdenv.shell} -c \"cd $HOME;${ihaskell}/bin/ihaskell-notebook\""; + }; + }; + }; +} diff --git a/nixos/modules/services/misc/plex.nix b/nixos/modules/services/misc/plex.nix new file mode 100644 index 000000000000..f4642b5157ee --- /dev/null +++ b/nixos/modules/services/misc/plex.nix @@ -0,0 +1,87 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.plex; + plex = pkgs.plex; +in +{ + options = { + services.plex = { + enable = mkEnableOption "Enable Plex Media Server"; + + # FIXME: In order for this config option to work, symlinks in the Plex + # package in the Nix store have to be changed to point to this directory. + dataDir = mkOption { + type = types.str; + default = "/var/lib/plex"; + description = "The directory where Plex stores its data files."; + }; + + user = mkOption { + type = types.str; + default = "plex"; + description = "User account under which Plex runs."; + }; + + group = mkOption { + type = types.str; + default = "plex"; + description = "Group under which Plex runs."; + }; + }; + }; + + config = mkIf cfg.enable { + # Most of this is just copied from the RPM package's systemd service file. + systemd.services.plex = { + description = "Plex Media Server"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + preStart = '' + test -d "${cfg.dataDir}" || { + echo "Creating initial Plex data directory in \"${cfg.dataDir}\"." + mkdir -p "${cfg.dataDir}" + chown -R ${cfg.user}:${cfg.group} "${cfg.dataDir}" + } + # Copy the database skeleton files to /var/lib/plex/.skeleton + test -d "${cfg.dataDir}/.skeleton" || mkdir "${cfg.dataDir}/.skeleton" + for db in "com.plexapp.plugins.library.db"; do + cp "${plex}/usr/lib/plexmediaserver/Resources/base_$db" "${cfg.dataDir}/.skeleton/$db" + chmod u+w "${cfg.dataDir}/.skeleton/$db" + chown ${cfg.user}:${cfg.group} "${cfg.dataDir}/.skeleton/$db" + done + ''; + serviceConfig = { + Type = "simple"; + User = cfg.user; + Group = cfg.group; + PermissionsStartOnly = "true"; + ExecStart = "/bin/sh -c '${plex}/usr/lib/plexmediaserver/Plex\\ Media\\ Server'"; + }; + environment = { + PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR=cfg.dataDir; + PLEX_MEDIA_SERVER_HOME="${plex}/usr/lib/plexmediaserver"; + PLEX_MEDIA_SERVER_MAX_PLUGIN_PROCS="6"; + PLEX_MEDIA_SERVER_TMPDIR="/tmp"; + LD_LIBRARY_PATH="${plex}/usr/lib/plexmediaserver"; + LC_ALL="en_US.UTF-8"; + LANG="en_US.UTF-8"; + }; + }; + + users.extraUsers = mkIf (cfg.user == "plex") { + plex = { + group = cfg.group; + uid = config.ids.uids.plex; + }; + }; + + users.extraGroups = mkIf (cfg.group == "plex") { + plex = { + gid = config.ids.gids.plex; + }; + }; + }; +} diff --git a/nixos/modules/services/misc/rippled.nix b/nixos/modules/services/misc/rippled.nix index 85a1ed8ae9e3..03fcc003a404 100644 --- a/nixos/modules/services/misc/rippled.nix +++ b/nixos/modules/services/misc/rippled.nix @@ -12,7 +12,7 @@ let path=${db.path} ${optionalString (db.compression != null) ("compression=${b2i db.compression}") } ${optionalString (db.onlineDelete != null) ("online_delete=${toString db.onlineDelete}")} - ${optionalString (db.advisoryDelete != null) ("advisory_delete=${toString db.advisoryDelete}")} + ${optionalString (db.advisoryDelete != null) ("advisory_delete=${b2i db.advisoryDelete}")} ${db.extraOpts} ''; @@ -71,6 +71,13 @@ let [sntp_servers] ${concatStringsSep "\n" cfg.sntpServers} + ${optionalString cfg.statsd.enable '' + [insight] + server=statsd + address=${cfg.statsd.address} + prefix=${cfg.statsd.prefix} + ''} + [rpc_startup] { "command": "log_level", "severity": "${cfg.logLevel}" } '' + cfg.extraConfig; @@ -142,7 +149,6 @@ let default = null; type = types.nullOr types.path; }; - }; }; }; @@ -150,7 +156,7 @@ let dbOptions = { type = mkOption { description = "Rippled database type."; - type = types.enum ["rocksdb" "nudb" "sqlite"]; + type = types.enum ["rocksdb" "nudb" "sqlite" "hyperleveldb"]; default = "rocksdb"; }; @@ -317,7 +323,7 @@ in Path to the ripple database. ''; type = types.path; - default = "/var/lib/rippled/db"; + default = "/var/lib/rippled"; }; validationQuorum = mkOption { @@ -366,6 +372,22 @@ in default = "error"; }; + statsd = { + enable = mkEnableOption "Whether enable statsd monitoring for rippled"; + + address = mkOption { + description = "The UDP address and port of the listening StatsD server."; + default = "127.0.0.1:8125"; + type = types.str; + }; + + prefix = mkOption { + description = "A string prepended to each collected metric."; + default = ""; + type = types.str; + }; + }; + extraConfig = mkOption { default = ""; description = '' @@ -400,6 +422,8 @@ in serviceConfig = { ExecStart = "${cfg.package}/bin/rippled --fg --conf ${cfg.config}"; User = "rippled"; + Restart = "on-failure"; + LimitNOFILE=10000; }; }; diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix index d6babb8e9a51..8b3741bca0af 100644 --- a/nixos/modules/services/network-filesystems/samba.nix +++ b/nixos/modules/services/network-filesystems/samba.nix @@ -4,6 +4,10 @@ with lib; let + smbToString = x: if builtins.typeOf x == "bool" + then (if x then "true" else "false") + else toString x; + cfg = config.services.samba; samba = cfg.package; @@ -15,9 +19,9 @@ let shareConfig = name: let share = getAttr name cfg.shares; in - "[${name}]\n " + (toString ( + "[${name}]\n " + (smbToString ( map - (key: "${key} = ${toString (getAttr key share)}\n") + (key: "${key} = ${smbToString (getAttr key share)}\n") (attrNames share) )); @@ -27,12 +31,12 @@ let [ global ] security = ${cfg.securityType} passwd program = /var/setuid-wrappers/passwd %u - pam password change = ${if cfg.syncPasswordsByPam then "yes" else "no"} - invalid users = ${toString cfg.invalidUsers} + pam password change = ${smbToString cfg.syncPasswordsByPam} + invalid users = ${smbToString cfg.invalidUsers} ${cfg.extraConfig} - ${toString (map shareConfig (attrNames cfg.shares))} + ${smbToString (map shareConfig (attrNames cfg.shares))} ''); # This may include nss_ldap, needed for samba if it has to use ldap. @@ -151,7 +155,7 @@ in example = { srv = { path = "/srv"; - "read only" = "yes"; + "read only" = true; comment = "Public samba share."; }; }; @@ -193,7 +197,7 @@ in "samba-setup" = { description = "Samba Setup Task"; script = setupScript; - unitConfig.RequiresMountsFor = "/var/samba /var/log/samba"; + unitConfig.RequiresMountsFor = "/var/lib/samba"; }; }; }; diff --git a/nixos/modules/services/networking/asterisk.nix b/nixos/modules/services/networking/asterisk.nix new file mode 100644 index 000000000000..b079cb227303 --- /dev/null +++ b/nixos/modules/services/networking/asterisk.nix @@ -0,0 +1,223 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.asterisk; + + asteriskUser = "asterisk"; + + varlibdir = "/var/lib/asterisk"; + spooldir = "/var/spool/asterisk"; + logdir = "/var/log/asterisk"; + + asteriskEtc = pkgs.stdenv.mkDerivation + ((mapAttrs' (name: value: nameValuePair + # Fudge the names to make bash happy + ((replaceChars ["."] ["_"] name) + "_") + (value) + ) cfg.confFiles) // + { + confFilesString = concatStringsSep " " ( + attrNames cfg.confFiles + ); + + name = "asterisk.etc"; + + # Default asterisk.conf file + # (Notice that astetcdir will be set to the path of this derivation) + asteriskConf = '' + [directories] + astetcdir => @out@ + astmoddir => ${pkgs.asterisk}/lib/asterisk/modules + astvarlibdir => /var/lib/asterisk + astdbdir => /var/lib/asterisk + astkeydir => /var/lib/asterisk + astdatadir => /var/lib/asterisk + astagidir => /var/lib/asterisk/agi-bin + astspooldir => /var/spool/asterisk + astrundir => /var/run/asterisk + astlogdir => /var/log/asterisk + astsbindir => ${pkgs.asterisk}/sbin + ''; + extraConf = cfg.extraConfig; + + # Loading all modules by default is considered sensible by the authors of + # "Asterisk: The Definitive Guide". Secure sites will likely want to + # specify their own "modules.conf" in the confFiles option. + modulesConf = '' + [modules] + autoload=yes + ''; + + # Use syslog for logging so logs can be viewed with journalctl + loggerConf = '' + [general] + + [logfiles] + syslog.local0 => notice,warning,error + ''; + + buildCommand = '' + mkdir -p "$out" + + # Create asterisk.conf, pointing astetcdir to the path of this derivation + echo "$asteriskConf" | sed "s|@out@|$out|g" > "$out"/asterisk.conf + echo "$extraConf" >> "$out"/asterisk.conf + + echo "$modulesConf" > "$out"/modules.conf + + echo "$loggerConf" > "$out"/logger.conf + + # Config files specified in confFiles option override all other files + for i in $confFilesString; do + conf=$(echo "$i"_ | sed 's/\./_/g') + echo "''${!conf}" > "$out"/"$i" + done + ''; + }); +in + +{ + options = { + services.asterisk = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable the Asterisk PBX server. + ''; + }; + + extraConfig = mkOption { + default = ""; + type = types.lines; + example = '' + [options] + verbose=3 + debug=3 + ''; + description = '' + Extra configuration options appended to the default + <literal>asterisk.conf</literal> file. + ''; + }; + + confFiles = mkOption { + default = {}; + type = types.attrsOf types.str; + example = literalExample + '' + { + "extensions.conf" = ''' + [tests] + ; Dial 100 for "hello, world" + exten => 100,1,Answer() + same => n,Wait(1) + same => n,Playback(hello-world) + same => n,Hangup() + + [softphones] + include => tests + + [unauthorized] + '''; + "sip.conf" = ''' + [general] + allowguest=no ; Require authentication + context=unauthorized ; Send unauthorized users to /dev/null + srvlookup=no ; Don't do DNS lookup + udpbindaddr=0.0.0.0 ; Listen on all interfaces + nat=force_rport,comedia ; Assume device is behind NAT + + [softphone](!) + type=friend ; Match on username first, IP second + context=softphones ; Send to softphones context in + ; extensions.conf file + host=dynamic ; Device will register with asterisk + disallow=all ; Manually specify codecs to allow + allow=g722 + allow=ulaw + allow=alaw + + [myphone](softphone) + secret=GhoshevFew ; Change this password! + '''; + "logger.conf" = ''' + [general] + + [logfiles] + ; Add debug output to log + syslog.local0 => notice,warning,error,debug + '''; + } + ''; + description = '' + Sets the content of config files (typically ending with + <literal>.conf</literal>) in the Asterisk configuration directory. + + Note that if you want to change <literal>asterisk.conf</literal>, it + is preferable to use the <option>services.asterisk.extraConfig</option> + option over this option. If <literal>"asterisk.conf"</literal> is + specified with the <option>confFiles</option> option (not recommended), + you must be prepared to set your own <literal>astetcdir</literal> + path. + + See + <link xlink:href="http://www.asterisk.org/community/documentation"/> + for more examples of what is possible here. + ''; + }; + + extraArguments = mkOption { + default = []; + type = types.listOf types.str; + example = + [ "-vvvddd" "-e" "1024" ]; + description = '' + Additional command line arguments to pass to Asterisk. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + users.extraUsers = singleton + { name = asteriskUser; + uid = config.ids.uids.asterisk; + description = "Asterisk daemon user"; + home = varlibdir; + }; + + systemd.services.asterisk = { + description = '' + Asterisk PBX server + ''; + + wantedBy = [ "multi-user.target" ]; + + preStart = '' + # Copy skeleton directory tree to /var + for d in '${varlibdir}' '${spooldir}' '${logdir}'; do + # TODO: Make exceptions for /var directories that likely should be updated + if [ ! -e "$d" ]; then + cp --recursive ${pkgs.asterisk}/"$d" "$d" + chown --recursive ${asteriskUser} "$d" + find "$d" -type d | xargs chmod 0755 + fi + done + ''; + + serviceConfig = { + ExecStart = + let + # FIXME: This doesn't account for arguments with spaces + argString = concatStringsSep " " cfg.extraArguments; + in + "${pkgs.asterisk}/bin/asterisk -U ${asteriskUser} -C ${asteriskEtc}/asterisk.conf ${argString} -F"; + Type = "forking"; + PIDFile = "/var/run/asterisk/asterisk.pid"; + }; + }; + }; +} diff --git a/nixos/modules/services/networking/btsync.nix b/nixos/modules/services/networking/btsync.nix index 8b90f295ed46..d0123b79e3f8 100644 --- a/nixos/modules/services/networking/btsync.nix +++ b/nixos/modules/services/networking/btsync.nix @@ -293,7 +293,7 @@ in systemd.services.btsync = with pkgs; { description = "Bittorrent Sync Service"; wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; + after = [ "network.target" "local-fs.target" ]; serviceConfig = { Restart = "on-abort"; UMask = "0002"; @@ -305,7 +305,7 @@ in systemd.services."btsync@" = with pkgs; { description = "Bittorrent Sync Service for %i"; - after = [ "network.target" ]; + after = [ "network.target" "local-fs.target" ]; serviceConfig = { Restart = "on-abort"; User = "%i"; diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix index be0acb27324a..f4063a3406f1 100644 --- a/nixos/modules/services/networking/cjdns.nix +++ b/nixos/modules/services/networking/cjdns.nix @@ -44,6 +44,9 @@ let }) else ""; + parseModules = x: + x // { connectTo = mapAttrs (name: value: { inherit (value) password publicKey; }) x.connectTo; }; + # would be nice to merge 'cfg' with a //, # but the json nesting is wacky. cjdrouteConf = builtins.toJSON ( { @@ -53,8 +56,8 @@ let }; authorizedPasswords = map (p: { password = p; }) cfg.authorizedPasswords; interfaces = { - ETHInterface = if (cfg.ETHInterface.bind != "") then [ cfg.ETHInterface ] else [ ]; - UDPInterface = if (cfg.UDPInterface.bind != "") then [ cfg.UDPInterface ] else [ ]; + ETHInterface = if (cfg.ETHInterface.bind != "") then [ (parseModules cfg.ETHInterface) ] else [ ]; + UDPInterface = if (cfg.UDPInterface.bind != "") then [ (parseModules cfg.UDPInterface) ] else [ ]; }; privateKey = "@CJDNS_PRIVATE_KEY@"; @@ -151,12 +154,14 @@ in ETHInterface = { bind = mkOption { - default = ""; - example = "eth0"; - description = '' - Bind to this device for native ethernet operation. - ''; - }; + default = ""; + example = "eth0"; + description = + '' + Bind to this device for native ethernet operation. + <literal>all</literal> is a pseudo-name which will try to connect to all devices. + ''; + }; beacon = mkOption { type = types.int; diff --git a/nixos/modules/services/networking/ddclient.nix b/nixos/modules/services/networking/ddclient.nix index f01deb6ee7c8..92f6396b3588 100644 --- a/nixos/modules/services/networking/ddclient.nix +++ b/nixos/modules/services/networking/ddclient.nix @@ -127,8 +127,8 @@ in wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; serviceConfig = { - # This may change back to forking if too many problems occur: - type = "simple"; + # Uncomment this if too many problems occur: + # Type = "forking"; User = ddclientUser; Group = "nogroup"; #TODO get this to work PermissionsStartOnly = "true"; diff --git a/nixos/modules/services/networking/dnsmasq.nix b/nixos/modules/services/networking/dnsmasq.nix index 7ddabf73106e..18086154b6b0 100644 --- a/nixos/modules/services/networking/dnsmasq.nix +++ b/nixos/modules/services/networking/dnsmasq.nix @@ -28,6 +28,7 @@ in services.dnsmasq = { enable = mkOption { + type = types.bool; default = false; description = '' Whether to run dnsmasq. @@ -35,14 +36,16 @@ in }; resolveLocalQueries = mkOption { + type = types.bool; default = true; description = '' Whether dnsmasq should resolve local queries (i.e. add 127.0.0.1 to - /etc/resolv.conf) + /etc/resolv.conf). ''; }; servers = mkOption { + type = types.listOf types.string; default = []; example = [ "8.8.8.8" "8.8.4.4" ]; description = '' @@ -51,11 +54,11 @@ in }; extraConfig = mkOption { - type = types.string; + type = types.lines; default = ""; description = '' Extra configuration directives that should be added to - <literal>dnsmasq.conf</literal> + <literal>dnsmasq.conf</literal>. ''; }; @@ -81,7 +84,7 @@ in }; systemd.services.dnsmasq = { - description = "dnsmasq daemon"; + description = "Dnsmasq Daemon"; after = [ "network.target" "systemd-resolved.service" ]; wantedBy = [ "multi-user.target" ]; path = [ dnsmasq ]; diff --git a/nixos/modules/services/networking/i2p.nix b/nixos/modules/services/networking/i2p.nix new file mode 100644 index 000000000000..bad22c791388 --- /dev/null +++ b/nixos/modules/services/networking/i2p.nix @@ -0,0 +1,42 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.i2p; + homeDir = "/var/lib/i2p"; +in { + ###### interface + options.services.i2p = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enables i2p as a running service upon activation. + ''; + }; + }; + + ###### implementation + config = mkIf cfg.enable { + users.extraUsers.i2p = { + group = "i2p"; + description = "i2p User"; + home = homeDir; + createHome = true; + uid = config.ids.uids.i2p; + }; + users.extraGroups.i2p.gid = config.ids.gids.i2p; + systemd.services.i2p = { + description = "I2P router with administration interface for hidden services"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + User = "i2p"; + WorkingDirectory = homeDir; + Restart = "on-abort"; + ExecStart = "${pkgs.i2p}/bin/i2prouter-plain"; + }; + }; + }; +} diff --git a/nixos/modules/services/networking/lambdabot.nix b/nixos/modules/services/networking/lambdabot.nix new file mode 100644 index 000000000000..4ef7c7c9ab63 --- /dev/null +++ b/nixos/modules/services/networking/lambdabot.nix @@ -0,0 +1,81 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.lambdabot; + + rc = builtins.toFile "script.rc" cfg.script; + +in + +{ + + ### configuration + + options = { + + services.lambdabot = { + + enable = mkOption { + type = types.bool; + default = false; + description = "Enable the Lambdabot IRC bot"; + }; + + package = mkOption { + type = types.package; + default = pkgs.lambdabot; + description = "Used lambdabot package"; + }; + + script = mkOption { + type = types.str; + default = ""; + description = "Lambdabot script"; + }; + + }; + + }; + + ### implementation + + config = mkIf cfg.enable { + + systemd.services.lambdabot = { + description = "Lambdabot daemon"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + # Workaround for https://github.com/lambdabot/lambdabot/issues/117 + script = '' + mkdir -p ~/.lambdabot + cd ~/.lambdabot + mkfifo /run/lambdabot/offline + ( + echo 'rc ${rc}' + while true; do + cat /run/lambdabot/offline + done + ) | ${cfg.package}/bin/lambdabot + ''; + serviceConfig = { + User = "lambdabot"; + RuntimeDirectory = [ "lambdabot" ]; + }; + }; + + users.extraUsers.lambdabot = { + group = "lambdabot"; + description = "Lambdabot daemon user"; + home = "/var/lib/lambdabot"; + createHome = true; + uid = config.ids.uids.lambdabot; + }; + + users.extraGroups.lambdabot.gid = config.ids.gids.lambdabot; + + }; + +} diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix index b2740bd33b7f..c25532511a07 100644 --- a/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixos/modules/services/networking/ssh/sshd.nix @@ -281,10 +281,8 @@ in config = mkIf cfg.enable { - users.extraUsers = singleton - { name = "sshd"; - uid = config.ids.uids.sshd; - description = "SSH privilege separation user"; + users.extraUsers.sshd = + { description = "SSH privilege separation user"; home = "/var/empty"; }; @@ -379,7 +377,7 @@ in Port ${toString port} '') cfg.ports} - ${concatMapStrings ({ port, addr }: '' + ${concatMapStrings ({ port, addr, ... }: '' ListenAddress ${addr}${if port != null then ":" + toString port else ""} '') cfg.listenAddresses} @@ -418,7 +416,7 @@ in (data.publicKey != null && data.publicKeyFile == null); message = "knownHost ${name} must contain either a publicKey or publicKeyFile"; }) - ++ flip map cfg.listenAddresses ({ addr, port }: { + ++ flip map cfg.listenAddresses ({ addr, port, ... }: { assertion = addr != null; message = "addr must be specified in each listenAddresses entry"; }); diff --git a/nixos/modules/services/networking/sslh.nix b/nixos/modules/services/networking/sslh.nix index e251571dca31..c87fe914df8b 100644 --- a/nixos/modules/services/networking/sslh.nix +++ b/nixos/modules/services/networking/sslh.nix @@ -81,7 +81,7 @@ in description = "Applicative Protocol Multiplexer (e.g. share SSH and HTTPS on the same port)"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; - serviceConfig.ExecStart = "${pkgs.sslh}/bin/sslh -F ${configFile}"; + serviceConfig.ExecStart = "${pkgs.sslh}/bin/sslh -F${configFile}"; serviceConfig.KillMode = "process"; serviceConfig.PIDFile = "${cfg.pidfile}"; }; diff --git a/nixos/modules/services/security/hologram.nix b/nixos/modules/services/security/hologram.nix new file mode 100644 index 000000000000..f9abf38942f4 --- /dev/null +++ b/nixos/modules/services/security/hologram.nix @@ -0,0 +1,102 @@ +{pkgs, config, lib, ...}: + +with lib; + +let + cfg = config.services.hologram-server; + + cfgFile = pkgs.writeText "hologram-server.json" (builtins.toJSON { + ldap = { + host = cfg.ldapHost; + bind = { + dn = cfg.ldapBindDN; + password = cfg.ldapBindPassword; + }; + insecureldap = cfg.ldapInsecure; + userattr = cfg.ldapUserAttr; + baseDN = cfg.ldapBaseDN; + }; + aws = { + account = cfg.awsAccount; + defaultrole = cfg.awsDefaultRole; + }; + stats = cfg.statsAddress; + listen = cfg.listenAddress; + }); +in { + options = { + services.hologram-server = { + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the Hologram server for AWS instance credentials"; + }; + + listenAddress = mkOption { + type = types.str; + default = "0.0.0.0:3100"; + description = "Address and port to listen on"; + }; + + ldapHost = mkOption { + type = types.str; + description = "Address of the LDAP server to use"; + }; + + ldapInsecure = mkOption { + type = types.bool; + default = false; + description = "Whether to connect to LDAP over SSL or not"; + }; + + ldapUserAttr = mkOption { + type = types.str; + default = "cn"; + description = "The LDAP attribute for usernames"; + }; + + ldapBaseDN = mkOption { + type = types.str; + description = "The base DN for your Hologram users"; + }; + + ldapBindDN = mkOption { + type = types.str; + description = "DN of account to use to query the LDAP server"; + }; + + ldapBindPassword = mkOption { + type = types.str; + description = "Password of account to use to query the LDAP server"; + }; + + awsAccount = mkOption { + type = types.str; + description = "AWS account number"; + }; + + awsDefaultRole = mkOption { + type = types.str; + description = "AWS default role"; + }; + + statsAddress = mkOption { + type = types.str; + default = ""; + description = "Address of statsd server"; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.services.hologram-server = { + description = "Provide EC2 instance credentials to machines outside of EC2"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + ExecStart = "${pkgs.goPackages.hologram}/bin/hologram-server --debug --conf ${cfgFile}"; + }; + }; + }; +} diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix index d40f7d6d05d9..853b458cf589 100644 --- a/nixos/modules/services/system/dbus.nix +++ b/nixos/modules/services/system/dbus.nix @@ -133,6 +133,8 @@ in # Don't restart dbus-daemon. Bad things tend to happen if we do. systemd.services.dbus.reloadIfChanged = true; + systemd.services.dbus.restartTriggers = [ configDir ]; + environment.pathsToLink = [ "/etc/dbus-1" "/share/dbus-1" ]; }; diff --git a/nixos/modules/services/system/nscd.nix b/nixos/modules/services/system/nscd.nix index 0879d9b85bd8..caedc2e42173 100644 --- a/nixos/modules/services/system/nscd.nix +++ b/nixos/modules/services/system/nscd.nix @@ -42,11 +42,7 @@ in config = mkIf cfg.enable { - users.extraUsers = singleton - { name = "nscd"; - uid = config.ids.uids.nscd; - description = "Name service cache daemon user"; - }; + users.extraUsers.nscd.description = "Name service cache daemon user"; systemd.services.nscd = { description = "Name Service Cache Daemon"; diff --git a/nixos/modules/services/ttys/agetty.nix b/nixos/modules/services/ttys/agetty.nix index 3958be33df2c..85ee23c1a3dd 100644 --- a/nixos/modules/services/ttys/agetty.nix +++ b/nixos/modules/services/ttys/agetty.nix @@ -10,6 +10,15 @@ with lib; services.mingetty = { + autologinUser = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Username of the account that will be automatically logged in at the console. + If unspecified, a login prompt is shown as usual. + ''; + }; + greetingLine = mkOption { type = types.str; default = ''<<< Welcome to NixOS ${config.system.nixosVersion} (\m) - \l >>>''; @@ -46,28 +55,30 @@ with lib; ###### implementation - config = { - + config = let + autologinArg = optionalString (config.services.mingetty.autologinUser != null) "--autologin ${config.services.mingetty.autologinUser}"; + gettyCmd = extraArgs: "@${pkgs.utillinux}/sbin/agetty agetty --login-program ${pkgs.shadow}/bin/login ${autologinArg} ${extraArgs}"; + in { systemd.services."getty@" = - { serviceConfig.ExecStart = "@${pkgs.utillinux}/sbin/agetty agetty --noclear --login-program ${pkgs.shadow}/bin/login --keep-baud %I 115200,38400,9600 $TERM"; + { serviceConfig.ExecStart = gettyCmd "--noclear --keep-baud %I 115200,38400,9600 $TERM"; restartIfChanged = false; }; systemd.services."serial-getty@" = { serviceConfig.ExecStart = let speeds = concatStringsSep "," (map toString config.services.mingetty.serialSpeed); - in "@${pkgs.utillinux}/sbin/agetty agetty --login-program ${pkgs.shadow}/bin/login %I ${speeds} $TERM"; + in gettyCmd "%I ${speeds} $TERM"; restartIfChanged = false; }; systemd.services."container-getty@" = { unitConfig.ConditionPathExists = "/dev/pts/%I"; # Work around being respawned when "machinectl login" exits. - serviceConfig.ExecStart = "@${pkgs.utillinux}/sbin/agetty agetty --noclear --login-program ${pkgs.shadow}/bin/login --keep-baud pts/%I 115200,38400,9600 $TERM"; + serviceConfig.ExecStart = gettyCmd "--noclear --keep-baud pts/%I 115200,38400,9600 $TERM"; restartIfChanged = false; }; systemd.services."console-getty" = - { serviceConfig.ExecStart = "@${pkgs.utillinux}/sbin/agetty agetty --noclear --login-program ${pkgs.shadow}/bin/login --keep-baud console 115200,38400,9600 $TERM"; + { serviceConfig.ExecStart = gettyCmd "--noclear --keep-baud console 115200,38400,9600 $TERM"; serviceConfig.Restart = "always"; restartIfChanged = false; enable = mkDefault config.boot.isContainer; diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix index 2b5cba68d457..2885fd396525 100644 --- a/nixos/modules/services/web-servers/apache-httpd/default.nix +++ b/nixos/modules/services/web-servers/apache-httpd/default.nix @@ -231,6 +231,9 @@ let ${if cfg.sslServerCert != null then '' SSLCertificateFile ${cfg.sslServerCert} SSLCertificateKeyFile ${cfg.sslServerKey} + ${if cfg.sslServerChain != null then '' + SSLCertificateChainFile ${cfg.sslServerChain} + '' else ""} '' else ""} ${if cfg.enableSSL then '' diff --git a/nixos/modules/services/web-servers/apache-httpd/moodle.nix b/nixos/modules/services/web-servers/apache-httpd/moodle.nix new file mode 100644 index 000000000000..84c8281ecd8d --- /dev/null +++ b/nixos/modules/services/web-servers/apache-httpd/moodle.nix @@ -0,0 +1,193 @@ +{ config, lib, pkgs, serverInfo, php, ... }: + +with lib; + +let + + httpd = serverInfo.serverConfig.package; + + version24 = !versionOlder httpd.version "2.4"; + + allGranted = if version24 then '' + Require all granted + '' else '' + Order allow,deny + Allow from all + ''; + + moodleConfig = pkgs.writeText "config.php" + '' + <?php + unset($CFG); + global $CFG; + $CFG = new stdClass(); + $CFG->dbtype = '${config.dbType}'; + $CFG->dblibrary = 'native'; + $CFG->dbhost = '${config.dbHost}'; + $CFG->dbname = '${config.dbName}'; + $CFG->dbuser = '${config.dbUser}'; + $CFG->dbpass = '${config.dbPassword}'; + $CFG->prefix = '${config.dbPrefix}'; + $CFG->dboptions = array( + 'dbpersist' => false, + 'dbsocket' => false, + 'dbport' => "${config.dbPort}", + ); + $CFG->wwwroot = '${config.wwwRoot}'; + $CFG->dataroot = '${config.dataRoot}'; + $CFG->directorypermissions = 02777; + $CFG->admin = 'admin'; + ${optionalString (config.debug.noEmailEver == true) '' + $CFG->noemailever = true; + ''} + + ${config.extraConfig} + require_once(dirname(__FILE__) . '/lib/setup.php'); // Do not edit + ''; + # Unpack Moodle and put the config file in its root directory. + moodleRoot = pkgs.stdenv.mkDerivation rec { + name= "moodle-2.8.5"; + + src = pkgs.fetchurl { + url = "https://download.moodle.org/stable28/${name}.tgz"; + sha256 = "1a159a193010cddedce10ee009184502e6f732e4d7c85167d8597fe5dff9e190"; + }; + + buildPhase = + '' + ''; + + installPhase = + '' + mkdir -p $out + cp -r * $out + cp ${moodleConfig} $out/config.php + ''; + }; + +in + +{ + + extraConfig = + '' + # this should be config.urlPrefix instead of / + Alias / ${moodleRoot}/ + <Directory ${moodleRoot}> + DirectoryIndex index.php + </Directory> + ''; + + documentRoot = moodleRoot; # TODO: fix this, should be config.urlPrefix + + enablePHP = true; + + options = { + + id = mkOption { + default = "main"; + description = '' + A unique identifier necessary to keep multiple Moodle server + instances on the same machine apart. + ''; + }; + + dbType = mkOption { + default = "postgres"; + example = "mysql"; + description = "Database type."; + }; + + dbName = mkOption { + default = "moodle"; + description = "Name of the database that holds the Moodle data."; + }; + + dbHost = mkOption { + default = "localhost"; + example = "10.0.2.2"; + description = '' + The location of the database server. + ''; + }; + + dbPort = mkOption { + default = ""; # use the default port + example = "12345"; + description = '' + The port that is used to connect to the database server. + ''; + }; + + dbUser = mkOption { + default = "moodle"; + description = "The user name for accessing the database."; + }; + + dbPassword = mkOption { + default = ""; + example = "password"; + description = '' + The password of the database user. Warning: this is stored in + cleartext in the Nix store! + ''; + }; + + dbPrefix = mkOption { + default = "mdl_"; + example = "my_other_mdl_"; + description = '' + A prefix for each table, if multiple moodles should run in a single database. + ''; + }; + + wwwRoot = mkOption { + type = types.string; + example = "http://my.machine.com/my-moodle"; + description = '' + The full web address where moodle has been installed. + ''; + }; + + dataRoot = mkOption { + default = "/var/lib/moodledata"; + example = "/var/lib/moodledata"; + description = '' + The data directory for moodle. Needs to be writable! + ''; + type = types.path; + }; + + + extraConfig = mkOption { + default = ""; + example = + '' + ''; + description = '' + Any additional text to be appended to Moodle's + configuration file. This is a PHP script. + ''; + }; + + debug = { + noEmailEver = mkOption { + default = false; + example = "true"; + description = '' + Set this to true to prevent Moodle from ever sending any email. + ''; + }; + }; + }; + + startupScript = pkgs.writeScript "moodle_startup.sh" '' + echo "Checking for existence of ${config.dataRoot}" + if [ ! -e "${config.dataRoot}" ] + then + mkdir -p "${config.dataRoot}" + chown ${serverInfo.serverConfig.user}.${serverInfo.serverConfig.group} "${config.dataRoot}" + fi + ''; + +} diff --git a/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix b/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix index 76f55a63e326..9fb25c37f5b1 100644 --- a/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix +++ b/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix @@ -56,6 +56,12 @@ with lib; description = "Path to server SSL certificate key."; }; + sslServerChain = mkOption { + type = types.path; + example = "/var/ca.pem"; + description = "Path to server SSL chain file."; + }; + adminAddr = mkOption ({ type = types.nullOr types.str; example = "admin@example.org"; diff --git a/nixos/modules/services/web-servers/apache-httpd/wordpress.nix b/nixos/modules/services/web-servers/apache-httpd/wordpress.nix new file mode 100644 index 000000000000..01b6cfc62afb --- /dev/null +++ b/nixos/modules/services/web-servers/apache-httpd/wordpress.nix @@ -0,0 +1,209 @@ +{ config, lib, pkgs, serverInfo, php, ... }: + +with lib; + +let + # https://wordpress.org/plugins/postgresql-for-wordpress/ + # Wordpress plugin 'postgresql-for-wordpress' installation example + postgresqlForWordpressPlugin = pkgs.stdenv.mkDerivation { + name = "postgresql-for-wordpress-plugin"; + # Download the theme from the wordpress site + src = pkgs.fetchurl { + url = https://downloads.wordpress.org/plugin/postgresql-for-wordpress.1.3.1.zip; + sha256 = "f11a5d76af884c7bec2bc653ed5bd29d3ede9a8657bd67ab7824e329e5d809e8"; + }; + # We need unzip to build this package + buildInputs = [ pkgs.unzip ]; + # Installing simply means copying all files to the output directory + installPhase = "mkdir -p $out; cp -R * $out/"; + }; + + # Our bare-bones wp-config.php file using the above settings + wordpressConfig = pkgs.writeText "wp-config.php" '' + <?php + define('DB_NAME', '${config.dbName}'); + define('DB_USER', '${config.dbUser}'); + define('DB_PASSWORD', '${config.dbPassword}'); + define('DB_HOST', '${config.dbHost}'); + define('DB_CHARSET', 'utf8'); + $table_prefix = '${config.tablePrefix}'; + if ( !defined('ABSPATH') ) + define('ABSPATH', dirname(__FILE__) . '/'); + require_once(ABSPATH . 'wp-settings.php'); + ${config.extraConfig} + ''; + + # .htaccess to support pretty URLs + htaccess = pkgs.writeText "htaccess" '' + <IfModule mod_rewrite.c> + RewriteEngine On + RewriteBase / + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule . /index.php [L] + </IfModule> + ''; + + # The wordpress package itself + wordpressRoot = pkgs.stdenv.mkDerivation rec { + name = "wordpress"; + # Fetch directly from the wordpress site, want to upgrade? + # Just change the version URL and update the hash + src = pkgs.fetchurl { + url = http://wordpress.org/wordpress-4.1.1.tar.gz; + sha256 = "1s9y0i9ms3m6dswb9gqrr95plnx6imahc07fyhvrp5g35f6c12k1"; + }; + installPhase = '' + mkdir -p $out + # Copy all the wordpress files we downloaded + cp -R * $out/ + # We'll symlink the wordpress config + ln -s ${wordpressConfig} $out/wp-config.php + # As well as our custom .htaccess + ln -s ${htaccess} $out/.htaccess + # And the uploads directory + ln -s ${config.wordpressUploads} $out/wp-content/uploads + # And the theme(s) + ${concatMapStrings (theme: "ln -s ${theme} $out/wp-content/themes/${theme.name}\n") config.themes} + # And the plugin(s) + # remove bundled plugin(s) coming with wordpress + rm -Rf $out/wp-content/plugins/akismet + # install plugins + ${concatMapStrings (plugin: "ln -s ${plugin} $out/wp-content/plugins/${plugin.name}\n") (config.plugins ++ [ postgresqlForWordpressPlugin]) } + ''; + }; + +in + +{ + + # And some httpd extraConfig to make things work nicely + extraConfig = '' + <Directory ${wordpressRoot}> + DirectoryIndex index.php + Allow from * + Options FollowSymLinks + AllowOverride All + </Directory> + ''; + + enablePHP = true; + + options = { + dbHost = mkOption { + default = "localhost"; + description = "The location of the database server."; + example = "localhost"; + }; + dbName = mkOption { + default = "wordpress"; + description = "Name of the database that holds the Wordpress data."; + example = "localhost"; + }; + dbUser = mkOption { + default = "wordpress"; + description = "The dbUser, read the username, for the database."; + example = "wordpress"; + }; + dbPassword = mkOption { + default = "wordpress"; + description = "The password to the respective dbUser."; + example = "wordpress"; + }; + tablePrefix = mkOption { + default = "wp_"; + description = '' + The $table_prefix is the value placed in the front of your database tables. Change the value if you want to use something other than wp_ for your database prefix. Typically this is changed if you are installing multiple WordPress blogs in the same database. See <link xlink:href='http://codex.wordpress.org/Editing_wp-config.php#table_prefix'/>. + ''; + }; + wordpressUploads = mkOption { + default = "/data/uploads"; + description = '' + This directory is used for uploads of pictures and must be accessible (read: owned) by the httpd running user. The directory passed here is automatically created and permissions are given to the httpd running user. + ''; + }; + plugins = mkOption { + default = []; + type = types.listOf types.path; + description = + '' + List of path(s) to respective plugin(s) which are symlinked from the 'plugins' directory. Note: These plugins need to be packaged before use. + ''; + example = '' + # Wordpress plugin 'akismet' installation example + akismetPlugin = pkgs.stdenv.mkDerivation { + name = "akismet-plugin"; + # Download the theme from the wordpress site + src = pkgs.fetchurl { + url = https://downloads.wordpress.org/plugin/akismet.3.1.zip; + sha256 = "1i4k7qyzna08822ncaz5l00wwxkwcdg4j9h3z2g0ay23q640pclg"; + }; + # We need unzip to build this package + buildInputs = [ pkgs.unzip ]; + # Installing simply means copying all files to the output directory + installPhase = "mkdir -p $out; cp -R * $out/"; + }; + + And then pass this theme to the themes list like this: + plugins = [ akismetPlugin ]; + ''; + }; + themes = mkOption { + default = []; + type = types.listOf types.path; + description = + '' + List of path(s) to respective theme(s) which are symlinked from the 'theme' directory. Note: These themes need to be packaged before use. + ''; + example = '' + # For shits and giggles, let's package the responsive theme + responsiveTheme = pkgs.stdenv.mkDerivation { + name = "responsive-theme"; + # Download the theme from the wordpress site + src = pkgs.fetchurl { + url = http://wordpress.org/themes/download/responsive.1.9.7.6.zip; + sha256 = "06i26xlc5kdnx903b1gfvnysx49fb4kh4pixn89qii3a30fgd8r8"; + }; + # We need unzip to build this package + buildInputs = [ pkgs.unzip ]; + # Installing simply means copying all files to the output directory + installPhase = "mkdir -p $out; cp -R * $out/"; + }; + + And then pass this theme to the themes list like this: + themes = [ responsiveTheme ]; + ''; + }; + extraConfig = mkOption { + default = ""; + example = + '' + define( 'AUTOSAVE_INTERVAL', 60 ); // Seconds + ''; + description = '' + Any additional text to be appended to Wordpress's wp-config.php + configuration file. This is a PHP script. For configuration + settings, see <link xlink:href='http://codex.wordpress.org/Editing_wp-config.php'/>. + ''; + }; + }; + + documentRoot = wordpressRoot; + + startupScript = pkgs.writeScript "init-wordpress.sh" '' + #!/bin/sh + mkdir -p ${config.wordpressUploads} + chown ${serverInfo.serverConfig.user} ${config.wordpressUploads} + + # we should use systemd dependencies here + #waitForUnit("network-interfaces.target"); + if [ ! -d ${serverInfo.fullConfig.services.mysql.dataDir}/${config.dbName} ]; then + # Wait until MySQL is up + while [ ! -e /var/run/mysql/mysqld.pid ]; do + sleep 1 + done + ${pkgs.mysql}/bin/mysql -e 'CREATE DATABASE ${config.dbName};' + ${pkgs.mysql}/bin/mysql -e 'GRANT ALL ON ${config.dbName}.* TO ${config.dbUser}@localhost IDENTIFIED BY "${config.dbPassword}";' + fi + ''; +} diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix index 139013cff50a..4aeaed8cd324 100644 --- a/nixos/modules/services/x11/display-managers/lightdm.nix +++ b/nixos/modules/services/x11/display-managers/lightdm.nix @@ -69,6 +69,7 @@ let xserver-command = ${xserverWrapper} session-wrapper = ${dmcfg.session.script} greeter-session = ${cfg.greeter.name} + ${cfg.extraSeatDefaults} ''; gtkGreeterConf = writeText "lightdm-gtk-greeter.conf" @@ -109,6 +110,15 @@ in ''; }; + extraSeatDefaults = mkOption { + type = types.lines; + default = ""; + example = '' + greeter-show-manual-login=true + ''; + description = "Extra lines to append to SeatDefaults section."; + }; + }; }; diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index 64e0d4d8050e..5198864ef6ef 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -41,16 +41,24 @@ let }; in imap mkHead cfg.xrandrHeads; - xrandrDeviceSection = flip concatMapStrings xrandrHeads (h: '' - Option "monitor-${h.output}" "${h.name}" - ''); + xrandrDeviceSection = let + monitors = flip map xrandrHeads (h: '' + Option "monitor-${h.output}" "${h.name}" + ''); + # First option is indented through the space in the config but any + # subsequent options aren't so we need to apply indentation to + # them here + monitorsIndented = if length monitors > 1 + then singleton (head monitors) ++ map (m: " " + m) (tail monitors) + else monitors; + in concatStrings monitorsIndented; # Here we chain every monitor from the left to right, so we have: # m4 right of m3 right of m2 right of m1 .----.----.----.----. # Which will end up in reverse ----------> | m1 | m2 | m3 | m4 | # `----^----^----^----' xrandrMonitorSections = let - mkMonitor = previous: current: previous ++ singleton { + mkMonitor = previous: current: singleton { inherit (current) name; value = '' Section "Monitor" @@ -60,8 +68,8 @@ let ''} EndSection ''; - }; - monitors = foldl mkMonitor [] xrandrHeads; + } ++ previous; + monitors = reverseList (foldl mkMonitor [] xrandrHeads); in concatMapStrings (getAttr "value") monitors; configFile = pkgs.stdenv.mkDerivation { @@ -147,6 +155,19 @@ in ''; }; + inputClassSections = mkOption { + type = types.listOf types.lines; + default = []; + example = [ '' + Identifier "Trackpoint Wheel Emulation" + MatchProduct "ThinkPad USB Keyboard with TrackPoint" + Option "EmulateWheel" "true + Option "EmulateWheelButton" "2" + Option "Emulate3Buttons" "false" + '' ]; + description = "Content of additional InputClass sections of the X server configuration file."; + }; + modules = mkOption { type = types.listOf types.path; default = []; @@ -522,6 +543,14 @@ in Option "XkbVariant" "${cfg.xkbVariant}" EndSection + # Additional "InputClass" sections + ${flip concatMapStrings cfg.inputClassSections (inputClassSection: '' + Section "InputClass" + ${inputClassSection} + EndSection + '')} + + Section "ServerLayout" Identifier "Layout[all]" ${cfg.serverLayoutSection} @@ -593,4 +622,3 @@ in }; } - |