diff options
Diffstat (limited to 'nixos/modules')
24 files changed, 1174 insertions, 74 deletions
diff --git a/nixos/modules/config/shells-environment.nix b/nixos/modules/config/shells-environment.nix index 9642981803bf..f458bc39adaa 100644 --- a/nixos/modules/config/shells-environment.nix +++ b/nixos/modules/config/shells-environment.nix @@ -1,7 +1,7 @@ # This module defines a global environment configuration and # a common configuration for all shells. -{ config, lib, pkgs, ... }: +{ config, lib, utils, pkgs, ... }: with lib; @@ -135,13 +135,13 @@ in environment.shells = mkOption { default = []; - example = [ "/run/current-system/sw/bin/zsh" ]; + example = literalExample "[ pkgs.bashInteractive pkgs.zsh ]"; description = '' A list of permissible login shells for user accounts. No need to mention <literal>/bin/sh</literal> here, it is placed into this list implicitly. ''; - type = types.listOf types.path; + type = types.listOf (types.either types.shellPackage types.path); }; }; @@ -158,7 +158,7 @@ in environment.etc."shells".text = '' - ${concatStringsSep "\n" cfg.shells} + ${concatStringsSep "\n" (map utils.toShellPath cfg.shells)} /bin/sh ''; diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index 8231907d7999..277a4264137b 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -1,9 +1,8 @@ -{ config, lib, pkgs, ... }: +{ config, lib, utils, pkgs, ... }: with lib; let - ids = config.ids; cfg = config.users; @@ -103,7 +102,7 @@ let }; home = mkOption { - type = types.str; + type = types.path; default = "/var/empty"; description = "The user's home directory."; }; @@ -118,8 +117,10 @@ let }; shell = mkOption { - type = types.str; - default = "/run/current-system/sw/bin/nologin"; + type = types.either types.shellPackage types.path; + default = pkgs.nologin; + defaultText = "pkgs.nologin"; + example = literalExample "pkgs.bashInteractive"; description = "The path to the user's shell."; }; @@ -359,11 +360,12 @@ let spec = pkgs.writeText "users-groups.json" (builtins.toJSON { inherit (cfg) mutableUsers; - users = mapAttrsToList (n: u: + users = mapAttrsToList (_: u: { inherit (u) - name uid group description home shell createHome isSystemUser + name uid group description home createHome isSystemUser password passwordFile hashedPassword initialPassword initialHashedPassword; + shell = utils.toShellPath u.shell; }) cfg.users; groups = mapAttrsToList (n: g: { inherit (g) name gid; @@ -373,6 +375,12 @@ let }) cfg.groups; }); + systemShells = + let + shells = mapAttrsToList (_: u: u.shell) cfg.users; + in + filter types.shellPackage.check shells; + in { ###### interface @@ -477,6 +485,9 @@ in { }; }; + # Install all the user shells + environment.systemPackages = systemShells; + users.groups = { root.gid = ids.gids.root; wheel.gid = ids.gids.wheel; diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh index c23d7e5b509d..7962be137875 100644 --- a/nixos/modules/installer/tools/nixos-install.sh +++ b/nixos/modules/installer/tools/nixos-install.sh @@ -91,12 +91,10 @@ ln -s /run $mountPoint/var/run rm -f $mountPoint/etc/{resolv.conf,hosts} cp -Lf /etc/resolv.conf /etc/hosts $mountPoint/etc/ -if [ -e "$SSL_CERT_FILE" ]; then - cp -Lf "$SSL_CERT_FILE" "$mountPoint/tmp/ca-cert.crt" - export SSL_CERT_FILE=/tmp/ca-cert.crt - # For Nix 1.7 - export CURL_CA_BUNDLE=/tmp/ca-cert.crt -fi +cp -Lf "@cacert@" "$mountPoint/tmp/ca-cert.crt" +export SSL_CERT_FILE=/tmp/ca-cert.crt +# For Nix 1.7 +export CURL_CA_BUNDLE=/tmp/ca-cert.crt if [ -n "$runChroot" ]; then if ! [ -L $mountPoint/nix/var/nix/profiles/system ]; then diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix index b8fd9deaf1e4..d8622b510522 100644 --- a/nixos/modules/installer/tools/tools.nix +++ b/nixos/modules/installer/tools/tools.nix @@ -23,6 +23,7 @@ let inherit (pkgs) perl pathsFromGraph; nix = config.nix.package.out; + cacert = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"; nixClosure = pkgs.runCommand "closure" { exportReferencesGraph = ["refs" config.nix.package.out]; } diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 61c49f07abbb..8da421447624 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -268,6 +268,8 @@ nzbget = 245; mosquitto = 246; toxvpn = 247; + squeezelite = 248; + turnserver = 249; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -506,6 +508,8 @@ nzbget = 245; mosquitto = 246; #toxvpn = 247; # unused + #squeezelite = 248; #unused + turnserver = 249; # When adding a gid, make sure it doesn't match an existing # uid. Users and groups with the same name should have equal diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 51c43b8c7c3b..be72c0ef29c0 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -110,6 +110,7 @@ ./services/audio/liquidsoap.nix ./services/audio/mpd.nix ./services/audio/mopidy.nix + ./services/audio/squeezelite.nix ./services/backup/almir.nix ./services/backup/bacula.nix ./services/backup/crashplan.nix @@ -316,6 +317,7 @@ ./services/networking/cntlm.nix ./services/networking/connman.nix ./services/networking/consul.nix + ./services/networking/coturn.nix ./services/networking/ddclient.nix ./services/networking/dhcpcd.nix ./services/networking/dhcpd.nix @@ -413,6 +415,7 @@ ./services/networking/wicd.nix ./services/networking/wpa_supplicant.nix ./services/networking/xinetd.nix + ./services/networking/xl2tpd.nix ./services/networking/zerobin.nix ./services/networking/zerotierone.nix ./services/networking/znc.nix @@ -459,6 +462,7 @@ ./services/web-servers/lighttpd/cgit.nix ./services/web-servers/lighttpd/default.nix ./services/web-servers/lighttpd/gitweb.nix + ./services/web-servers/lighttpd/inginious.nix ./services/web-servers/nginx/default.nix ./services/web-servers/phpfpm.nix ./services/web-servers/shellinabox.nix diff --git a/nixos/modules/programs/bash/bash.nix b/nixos/modules/programs/bash/bash.nix index e4e264ec0036..c09bcfb70e24 100644 --- a/nixos/modules/programs/bash/bash.nix +++ b/nixos/modules/programs/bash/bash.nix @@ -200,7 +200,7 @@ in # Configuration for readline in bash. environment.etc."inputrc".source = ./inputrc; - users.defaultUserShell = mkDefault "/run/current-system/sw/bin/bash"; + users.defaultUserShell = mkDefault pkgs.bashInteractive; environment.pathsToLink = optionals cfg.enableCompletion [ "/etc/bash_completion.d" diff --git a/nixos/modules/programs/shadow.nix b/nixos/modules/programs/shadow.nix index 566398d839fd..6398509357a6 100644 --- a/nixos/modules/programs/shadow.nix +++ b/nixos/modules/programs/shadow.nix @@ -1,6 +1,6 @@ # Configuration for the pwdutils suite of tools: passwd, useradd, etc. -{ config, lib, pkgs, ... }: +{ config, lib, utils, pkgs, ... }: with lib; @@ -43,13 +43,13 @@ in users.defaultUserShell = lib.mkOption { description = '' This option defines the default shell assigned to user - accounts. This must not be a store path, since the path is + accounts. This can be either a full system path or a shell package. + + This must not be a store path, since the path is used outside the store (in particular in /etc/passwd). - Rather, it should be the path of a symlink that points to the - actual shell in the Nix store. ''; - example = "/run/current-system/sw/bin/zsh"; - type = types.path; + example = literalExample "pkgs.zsh"; + type = types.either types.path types.shellPackage; }; }; @@ -60,7 +60,9 @@ in config = { environment.systemPackages = - lib.optional config.users.mutableUsers pkgs.shadow; + lib.optional config.users.mutableUsers pkgs.shadow ++ + lib.optional (types.shellPackage.check config.users.defaultUserShell) + config.users.defaultUserShell; environment.etc = [ { # /etc/login.defs: global configuration for pwdutils. You @@ -74,7 +76,7 @@ in '' GROUP=100 HOME=/home - SHELL=${config.users.defaultUserShell} + SHELL=${utils.toShellPath config.users.defaultUserShell} ''; target = "default/useradd"; } diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix index ef6da788e619..f646602221a4 100644 --- a/nixos/modules/security/acme.nix +++ b/nixos/modules/security/acme.nix @@ -187,7 +187,7 @@ in script = '' cd '${cpath}' set +e - simp_le ${concatMapStringsSep " " (arg: escapeShellArg (toString arg)) cmdline} + simp_le ${escapeShellArgs cmdline} EXITCODE=$? set -e echo "$EXITCODE" > /tmp/lastExitCode diff --git a/nixos/modules/services/audio/squeezelite.nix b/nixos/modules/services/audio/squeezelite.nix new file mode 100644 index 000000000000..f1a60be992d8 --- /dev/null +++ b/nixos/modules/services/audio/squeezelite.nix @@ -0,0 +1,67 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + uid = config.ids.uids.squeezelite; + cfg = config.services.squeezelite; + +in { + + ###### interface + + options = { + + services.squeezelite= { + + enable = mkEnableOption "Squeezelite, a software Squeezebox emulator"; + + dataDir = mkOption { + default = "/var/lib/squeezelite"; + type = types.str; + description = '' + The directory where Squeezelite stores its name file. + ''; + }; + + extraArguments = mkOption { + default = ""; + type = types.str; + description = '' + Additional command line arguments to pass to Squeezelite. + ''; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + systemd.services.squeezelite= { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" "sound.target" ]; + description = "Software Squeezebox emulator"; + preStart = "mkdir -p ${cfg.dataDir} && chown -R squeezelite ${cfg.dataDir}"; + serviceConfig = { + ExecStart = "${pkgs.squeezelite}/bin/squeezelite -N ${cfg.dataDir}/player-name ${cfg.extraArguments}"; + User = "squeezelite"; + PermissionsStartOnly = true; + }; + }; + + users.extraUsers.squeezelite= { + inherit uid; + group = "nogroup"; + extraGroups = [ "audio" ]; + description = "Squeezelite user"; + home = "${cfg.dataDir}"; + }; + + }; + +} diff --git a/nixos/modules/services/mail/opendkim.nix b/nixos/modules/services/mail/opendkim.nix index af996758f41f..f065208ddfc1 100644 --- a/nixos/modules/services/mail/opendkim.nix +++ b/nixos/modules/services/mail/opendkim.nix @@ -101,7 +101,7 @@ in { wantedBy = [ "multi-user.target" ]; serviceConfig = { - ExecStart = "${pkgs.opendkim}/bin/opendkim ${concatMapStringsSep " " escapeShellArg args}"; + ExecStart = "${pkgs.opendkim}/bin/opendkim ${escapeShellArgs args}"; User = cfg.user; Group = cfg.group; RuntimeDirectory = optional (cfg.socket == defaultSock) "opendkim"; diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix index 0ae0516769c0..1a95e2d9367d 100644 --- a/nixos/modules/services/misc/matrix-synapse.nix +++ b/nixos/modules/services/misc/matrix-synapse.nix @@ -5,17 +5,31 @@ with lib; let cfg = config.services.matrix-synapse; logConfigFile = pkgs.writeText "log_config.yaml" cfg.logConfig; + mkResource = r: ''{names: ${builtins.toJSON r.names}, compress: ${if r.compress then "true" else "false"}}''; + mkListener = l: ''{port: ${toString l.port}, bind_address: "${l.bind_address}", type: ${l.type}, tls: ${if l.tls then "true" else "false"}, x_forwarded: ${if l.x_forwarded then "true" else "false"}, resources: [${concatStringsSep "," (map mkResource l.resources)}]}''; configFile = pkgs.writeText "homeserver.yaml" '' tls_certificate_path: "${cfg.tls_certificate_path}" +${optionalString (cfg.tls_private_key_path != null) '' tls_private_key_path: "${cfg.tls_private_key_path}" +''} tls_dh_params_path: "${cfg.tls_dh_params_path}" no_tls: ${if cfg.no_tls then "true" else "false"} +${optionalString (cfg.bind_port != null) '' bind_port: ${toString cfg.bind_port} +''} +${optionalString (cfg.unsecure_port != null) '' unsecure_port: ${toString cfg.unsecure_port} +''} +${optionalString (cfg.bind_host != null) '' bind_host: "${cfg.bind_host}" +''} server_name: "${cfg.server_name}" pid_file: "/var/run/matrix-synapse.pid" web_client: ${if cfg.web_client then "true" else "false"} +${optionalString (cfg.public_baseurl != null) '' +public_baseurl: "${cfg.public_baseurl}" +''} +listeners: [${concatStringsSep "," (map mkListener cfg.listeners)}] database: { name: "${cfg.database_type}", args: { @@ -24,21 +38,41 @@ database: { )} } } +event_cache_size: "${cfg.event_cache_size}" +verbose: ${cfg.verbose} log_file: "/var/log/matrix-synapse/homeserver.log" log_config: "${logConfigFile}" +rc_messages_per_second: ${cfg.rc_messages_per_second} +rc_message_burst_count: ${cfg.rc_message_burst_count} +federation_rc_window_size: ${cfg.federation_rc_window_size} +federation_rc_sleep_limit: ${cfg.federation_rc_sleep_limit} +federation_rc_sleep_delay: ${cfg.federation_rc_sleep_delay} +federation_rc_reject_limit: ${cfg.federation_rc_reject_limit} +federation_rc_concurrent: ${cfg.federation_rc_concurrent} media_store_path: "/var/lib/matrix-synapse/media" +uploads_path: "/var/lib/matrix-synapse/uploads" +max_upload_size: "${cfg.max_upload_size}" +max_image_pixels: "${cfg.max_image_pixels}" +dynamic_thumbnails: ${if cfg.dynamic_thumbnails then "true" else "false"} +url_preview_enabled: False recaptcha_private_key: "${cfg.recaptcha_private_key}" recaptcha_public_key: "${cfg.recaptcha_public_key}" enable_registration_captcha: ${if cfg.enable_registration_captcha then "true" else "false"} -turn_uris: ${if (length cfg.turn_uris) == 0 then "[]" else ("\n" + (concatStringsSep "\n" (map (s: "- " + s) cfg.turn_uris)))} +turn_uris: ${builtins.toJSON cfg.turn_uris} turn_shared_secret: "${cfg.turn_shared_secret}" enable_registration: ${if cfg.enable_registration then "true" else "false"} -${optionalString (cfg.registration_shared_secret != "") '' +${optionalString (cfg.registration_shared_secret != null) '' registration_shared_secret: "${cfg.registration_shared_secret}" ''} +recaptcha_siteverify_api: "https://www.google.com/recaptcha/api/siteverify" +turn_user_lifetime: "${cfg.turn_user_lifetime}" +user_creation_max_duration: ${cfg.user_creation_max_duration} +bcrypt_rounds: ${cfg.bcrypt_rounds} +allow_guest_access: {if cfg.allow_guest_access then "true" else "false"} enable_metrics: ${if cfg.enable_metrics then "true" else "false"} report_stats: ${if cfg.report_stats then "true" else "false"} signing_key_path: "/var/lib/matrix-synapse/homeserver.signing.key" +key_refresh_interval: "${cfg.key_refresh_interval}" perspectives: servers: { ${concatStringsSep "},\n" (mapAttrsToList (n: v: '' @@ -52,6 +86,8 @@ perspectives: '') cfg.servers)} } } +app_service_config_files: ${builtins.toJSON cfg.app_service_config_files} + ${cfg.extraConfig} ''; in { @@ -73,53 +109,65 @@ in { Don't bind to the https port ''; }; - tls_certificate_path = mkOption { - type = types.path; - default = "/var/lib/matrix-synapse/homeserver.tls.crt"; + bind_port = mkOption { + type = types.nullOr types.int; + default = null; + example = 8448; description = '' - PEM encoded X509 certificate for TLS + DEPRECATED: Use listeners instead. + The port to listen for HTTPS requests on. + For when matrix traffic is sent directly to synapse. ''; }; - tls_private_key_path = mkOption { - type = types.path; - default = "/var/lib/matrix-synapse/homeserver.tls.key"; + unsecure_port = mkOption { + type = types.nullOr types.int; + default = null; + example = 8008; description = '' - PEM encoded private key for TLS + DEPRECATED: Use listeners instead. + The port to listen for HTTP requests on. + For when matrix traffic passes through loadbalancer that unwraps TLS. ''; }; - tls_dh_params_path = mkOption { - type = types.path; - default = "/var/lib/matrix-synapse/homeserver.tls.dh"; + bind_host = mkOption { + type = types.nullOr types.str; + default = null; description = '' - PEM dh parameters for ephemeral keys + DEPRECATED: Use listeners instead. + Local interface to listen on. + The empty string will cause synapse to listen on all interfaces. ''; }; - bind_port = mkOption { - type = types.int; - default = 8448; + tls_certificate_path = mkOption { + type = types.str; + default = "/var/lib/matrix-synapse/homeserver.tls.crt"; description = '' - The port to listen for HTTPS requests on. - For when matrix traffic is sent directly to synapse. + PEM encoded X509 certificate for TLS. + You can replace the self-signed certificate that synapse + autogenerates on launch with your own SSL certificate + key pair + if you like. Any required intermediary certificates can be + appended after the primary certificate in hierarchical order. ''; }; - unsecure_port = mkOption { - type = types.int; - default = 8008; + tls_private_key_path = mkOption { + type = types.nullOr types.str; + default = "/var/lib/matrix-synapse/homeserver.tls.key"; + example = null; description = '' - The port to listen for HTTP requests on. - For when matrix traffic passes through loadbalancer that unwraps TLS. + PEM encoded private key for TLS. Specify null if synapse is not + speaking TLS directly. ''; }; - bind_host = mkOption { + tls_dh_params_path = mkOption { type = types.str; - default = ""; + default = "/var/lib/matrix-synapse/homeserver.tls.dh"; description = '' - Local interface to listen on. - The empty string will cause synapse to listen on all interfaces. + PEM dh parameters for ephemeral keys ''; }; server_name = mkOption { type = types.str; + example = "example.com"; description = '' The domain name of the server, with optional explicit port. This is used by remote servers to connect to this server, @@ -134,6 +182,145 @@ in { Whether to serve a web client from the HTTP/HTTPS root resource. ''; }; + public_baseurl = mkOption { + type = types.nullOr types.str; + default = null; + example = "https://example.com:8448/"; + description = '' + The public-facing base URL for the client API (not including _matrix/...) + ''; + }; + listeners = mkOption { + type = types.listOf (types.submodule { + options = { + port = mkOption { + type = types.int; + example = 8448; + description = '' + The port to listen for HTTP(S) requests on. + ''; + }; + bind_address = mkOption { + type = types.str; + default = ""; + example = "203.0.113.42"; + description = '' + Local interface to listen on. + The empty string will cause synapse to listen on all interfaces. + ''; + }; + type = mkOption { + type = types.str; + default = "http"; + description = '' + Type of listener. + ''; + }; + tls = mkOption { + type = types.bool; + default = true; + description = '' + Whether to listen for HTTPS connections rather than HTTP. + ''; + }; + x_forwarded = mkOption { + type = types.bool; + default = false; + description = '' + Use the X-Forwarded-For (XFF) header as the client IP and not the + actual client IP. + ''; + }; + resources = mkOption { + type = types.listOf (types.submodule { + options = { + names = mkOption { + type = types.listOf types.str; + description = '' + List of resources to host on this listener. + ''; + example = ["client" "webclient" "federation"]; + }; + compress = mkOption { + type = types.bool; + description = '' + Should synapse compress HTTP responses to clients that support it? + This should be disabled if running synapse behind a load balancer + that can do automatic compression. + ''; + }; + }; + }); + description = '' + List of HTTP resources to serve on this listener. + ''; + }; + }; + }); + default = [{ + port = 8448; + bind_address = ""; + type = "http"; + tls = true; + x_forwarded = false; + resources = [ + { names = ["client" "webclient"]; compress = true; } + { names = ["federation"]; compress = false; } + ]; + }]; + description = '' + List of ports that Synapse should listen on, their purpose and their configuration. + ''; + }; + verbose = mkOption { + type = types.str; + default = "0"; + description = "Logging verbosity level."; + }; + rc_messages_per_second = mkOption { + type = types.str; + default = "0.2"; + description = "Number of messages a client can send per second"; + }; + rc_message_burst_count = mkOption { + type = types.str; + default = "10.0"; + description = "Number of message a client can send before being throttled"; + }; + federation_rc_window_size = mkOption { + type = types.str; + default = "1000"; + description = "The federation window size in milliseconds"; + }; + federation_rc_sleep_limit = mkOption { + type = types.str; + default = "10"; + description = '' + The number of federation requests from a single server in a window + before the server will delay processing the request. + ''; + }; + federation_rc_sleep_delay = mkOption { + type = types.str; + default = "500"; + description = '' + The duration in milliseconds to delay processing events from + remote servers by if they go over the sleep limit. + ''; + }; + federation_rc_reject_limit = mkOption { + type = types.str; + default = "50"; + description = '' + The maximum number of concurrent federation requests allowed + from a single server + ''; + }; + federation_rc_concurrent = mkOption { + type = types.str; + default = "3"; + description = "The number of federation requests to concurrently process from a single server"; + }; database_type = mkOption { type = types.enum [ "sqlite3" "psycopg2" ]; default = "sqlite3"; @@ -150,6 +337,11 @@ in { Arguments to pass to the engine. ''; }; + event_cache_size = mkOption { + type = types.str; + default = "10K"; + description = "Number of events to cache in memory."; + }; recaptcha_private_key = mkOption { type = types.str; default = ""; @@ -187,6 +379,11 @@ in { The shared secret used to compute passwords for the TURN server ''; }; + turn_user_lifetime = mkOption { + type = types.str; + default = "1h"; + description = "How long generated TURN credentials last"; + }; enable_registration = mkOption { type = types.bool; default = false; @@ -195,8 +392,8 @@ in { ''; }; registration_shared_secret = mkOption { - type = types.str; - default = ""; + type = types.nullOr types.str; + default = null; description = '' If set, allows registration by anyone who also has the shared secret, even if registration is otherwise disabled. @@ -216,7 +413,7 @@ in { ''; }; servers = mkOption { - type = types.attrs; + type = types.attrsOf (types.attrsOf types.str); default = { "matrix.org" = { "ed25519:auto" = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw"; @@ -226,6 +423,69 @@ in { The trusted servers to download signing keys from. ''; }; + max_upload_size = mkOption { + type = types.str; + default = "10M"; + description = "The largest allowed upload size in bytes"; + }; + max_image_pixels = mkOption { + type = types.str; + default = "32M"; + description = "Maximum number of pixels that will be thumbnailed"; + }; + dynamic_thumbnails = mkOption { + type = types.bool; + default = false; + description = '' + Whether to generate new thumbnails on the fly to precisely match + the resolution requested by the client. If true then whenever + a new resolution is requested by the client the server will + generate a new thumbnail. If false the server will pick a thumbnail + from a precalculated list. + ''; + }; + user_creation_max_duration = mkOption { + type = types.str; + default = "1209600000"; + description = '' + Sets the expiry for the short term user creation in + milliseconds. The default value is two weeks. + ''; + }; + bcrypt_rounds = mkOption { + type = types.str; + default = "12"; + description = '' + Set the number of bcrypt rounds used to generate password hash. + Larger numbers increase the work factor needed to generate the hash. + ''; + }; + allow_guest_access = mkOption { + type = types.bool; + default = false; + description = '' + Allows users to register as guests without a password/email/etc, and + participate in rooms hosted on this server which have been made + accessible to anonymous users. + ''; + }; + key_refresh_interval = mkOption { + type = types.str; + default = "1d"; + description = '' + How long key response published by this server is valid for. + Used to set the valid_until_ts in /key/v2 APIs. + Determines how quickly servers will query to check which keys + are still valid. + ''; + }; + app_service_config_files = mkOption { + type = types.listOf types.path; + default = [ ]; + description = '' + A list of application service config file to use + ''; + }; extraConfig = mkOption { type = types.lines; default = ""; @@ -265,7 +525,7 @@ in { mkdir -p /var/lib/matrix-synapse chmod 700 /var/lib/matrix-synapse chown -R matrix-synapse:matrix-synapse /var/lib/matrix-synapse - ${cfg.package}/bin/homeserver --config-path ${configFile} --generate-keys + ${cfg.package}/bin/homeserver --config-path ${configFile} --keys-directory /var/lib/matrix-synapse/ --generate-keys ''; serviceConfig = { Type = "simple"; diff --git a/nixos/modules/services/misc/taskserver/default.nix b/nixos/modules/services/misc/taskserver/default.nix index b7d14e90a2b7..c846ffd04551 100644 --- a/nixos/modules/services/misc/taskserver/default.nix +++ b/nixos/modules/services/misc/taskserver/default.nix @@ -152,8 +152,6 @@ let }; }; - mkShellStr = val: "'${replaceStrings ["'"] ["'\\''"] val}'"; - certtool = "${pkgs.gnutls.bin}/bin/certtool"; nixos-taskserver = pkgs.buildPythonPackage { diff --git a/nixos/modules/services/networking/coturn.nix b/nixos/modules/services/networking/coturn.nix new file mode 100644 index 000000000000..14e6932d868b --- /dev/null +++ b/nixos/modules/services/networking/coturn.nix @@ -0,0 +1,327 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.services.coturn; + pidfile = "/run/turnserver/turnserver.pid"; + configFile = pkgs.writeText "turnserver.conf" '' +listening-port=${toString cfg.listening-port} +tls-listening-port=${toString cfg.tls-listening-port} +alt-listening-port=${toString cfg.alt-listening-port} +alt-tls-listening-port=${toString cfg.alt-tls-listening-port} +${concatStringsSep "\n" (map (x: "listening-ip=${x}") cfg.listening-ips)} +${concatStringsSep "\n" (map (x: "relay-ip=${x}") cfg.relay-ips)} +min-port=${toString cfg.min-port} +max-port=${toString cfg.max-port} +${lib.optionalString cfg.lt-cred-mech "lt-cred-mech"} +${lib.optionalString cfg.no-auth "no-auth"} +${lib.optionalString cfg.use-auth-secret "use-auth-secret"} +${lib.optionalString (cfg.static-auth-secret != null) ("static-auth-secret=${cfg.static-auth-secret}")} +realm=${cfg.realm} +${lib.optionalString cfg.no-udp "no-udp"} +${lib.optionalString cfg.no-tcp "no-tcp"} +${lib.optionalString cfg.no-tls "no-tls"} +${lib.optionalString cfg.no-dtls "no-dtls"} +${lib.optionalString cfg.no-udp-relay "no-udp-relay"} +${lib.optionalString cfg.no-tcp-relay "no-tcp-relay"} +${lib.optionalString (cfg.cert != null) "cert=${cfg.cert}"} +${lib.optionalString (cfg.pkey != null) "pkey=${cfg.pkey}"} +${lib.optionalString (cfg.dh-file != null) ("dh-file=${cfg.dh-file}")} +no-stdout-log +syslog +pidfile=${pidfile} +${lib.optionalString cfg.secure-stun "secure-stun"} +${lib.optionalString cfg.no-cli "no-cli"} +cli-ip=${cfg.cli-ip} +cli-port=${toString cfg.cli-port} +${lib.optionalString (cfg.cli-password != null) ("cli-password=${cfg.cli-password}")} +${cfg.extraConfig} +''; +in { + options = { + services.coturn = { + enable = mkEnableOption "coturn TURN server"; + listening-port = mkOption { + type = types.int; + default = 3478; + description = '' + TURN listener port for UDP and TCP. + Note: actually, TLS and DTLS sessions can connect to the + "plain" TCP and UDP port(s), too - if allowed by configuration. + ''; + }; + tls-listening-port = mkOption { + type = types.int; + default = 5349; + description = '' + TURN listener port for TLS. + Note: actually, "plain" TCP and UDP sessions can connect to the TLS and + DTLS port(s), too - if allowed by configuration. The TURN server + "automatically" recognizes the type of traffic. Actually, two listening + endpoints (the "plain" one and the "tls" one) are equivalent in terms of + functionality; but we keep both endpoints to satisfy the RFC 5766 specs. + For secure TCP connections, we currently support SSL version 3 and + TLS version 1.0, 1.1 and 1.2. + For secure UDP connections, we support DTLS version 1. + ''; + }; + alt-listening-port = mkOption { + type = types.int; + default = cfg.listening-port + 1; + defaultText = "listening-port + 1"; + description = '' + Alternative listening port for UDP and TCP listeners; + default (or zero) value means "listening port plus one". + This is needed for RFC 5780 support + (STUN extension specs, NAT behavior discovery). The TURN Server + supports RFC 5780 only if it is started with more than one + listening IP address of the same family (IPv4 or IPv6). + RFC 5780 is supported only by UDP protocol, other protocols + are listening to that endpoint only for "symmetry". + ''; + }; + alt-tls-listening-port = mkOption { + type = types.int; + default = cfg.tls-listening-port + 1; + defaultText = "tls-listening-port + 1"; + description = '' + Alternative listening port for TLS and DTLS protocols. + ''; + }; + listening-ips = mkOption { + type = types.listOf types.str; + default = []; + example = [ "203.0.113.42" "2001:DB8::42" ]; + description = '' + Listener IP addresses of relay server. + If no IP(s) specified in the config file or in the command line options, + then all IPv4 and IPv6 system IPs will be used for listening. + ''; + }; + relay-ips = mkOption { + type = types.listOf types.str; + default = []; + example = [ "203.0.113.42" "2001:DB8::42" ]; + description = '' + Relay address (the local IP address that will be used to relay the + packets to the peer). + Multiple relay addresses may be used. + The same IP(s) can be used as both listening IP(s) and relay IP(s). + + If no relay IP(s) specified, then the turnserver will apply the default + policy: it will decide itself which relay addresses to be used, and it + will always be using the client socket IP address as the relay IP address + of the TURN session (if the requested relay address family is the same + as the family of the client socket). + ''; + }; + min-port = mkOption { + type = types.int; + default = 49152; + description = '' + Lower bound of UDP relay endpoints + ''; + }; + max-port = mkOption { + type = types.int; + default = 65535; + description = '' + Upper bound of UDP relay endpoints + ''; + }; + lt-cred-mech = mkOption { + type = types.bool; + default = false; + description = '' + Use long-term credential mechanism. + ''; + }; + no-auth = mkOption { + type = types.bool; + default = false; + description = '' + This option is opposite to lt-cred-mech. + (TURN Server with no-auth option allows anonymous access). + If neither option is defined, and no users are defined, + then no-auth is default. If at least one user is defined, + in this file or in command line or in usersdb file, then + lt-cred-mech is default. + ''; + }; + use-auth-secret = mkOption { + type = types.bool; + default = false; + description = '' + TURN REST API flag. + Flag that sets a special authorization option that is based upon authentication secret. + This feature can be used with the long-term authentication mechanism, only. + This feature purpose is to support "TURN Server REST API", see + "TURN REST API" link in the project's page + https://github.com/coturn/coturn/ + + This option is used with timestamp: + + usercombo -> "timestamp:userid" + turn user -> usercombo + turn password -> base64(hmac(secret key, usercombo)) + + This allows TURN credentials to be accounted for a specific user id. + If you don't have a suitable id, the timestamp alone can be used. + This option is just turning on secret-based authentication. + The actual value of the secret is defined either by option static-auth-secret, + or can be found in the turn_secret table in the database. + ''; + }; + static-auth-secret = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + 'Static' authentication secret value (a string) for TURN REST API only. + If not set, then the turn server + will try to use the 'dynamic' value in turn_secret table + in user database (if present). The database-stored value can be changed on-the-fly + by a separate program, so this is why that other mode is 'dynamic'. + ''; + }; + realm = mkOption { + type = types.str; + default = config.networking.hostName; + example = "example.com"; + description = '' + The default realm to be used for the users when no explicit + origin/realm relationship was found in the database, or if the TURN + server is not using any database (just the commands-line settings + and the userdb file). Must be used with long-term credentials + mechanism or with TURN REST API. + ''; + }; + cert = mkOption { + type = types.nullOr types.str; + default = null; + example = "/var/lib/acme/example.com/fullchain.pem"; + description = '' + Certificate file in PEM format. + ''; + }; + pkey = mkOption { + type = types.nullOr types.str; + default = null; + example = "/var/lib/acme/example.com/key.pem"; + description = '' + Private key file in PEM format. + ''; + }; + dh-file = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Use custom DH TLS key, stored in PEM format in the file. + ''; + }; + secure-stun = mkOption { + type = types.bool; + default = false; + description = '' + Require authentication of the STUN Binding request. + By default, the clients are allowed anonymous access to the STUN Binding functionality. + ''; + }; + no-cli = mkOption { + type = types.bool; + default = false; + description = '' + Turn OFF the CLI support. + ''; + }; + cli-ip = mkOption { + type = types.str; + default = "127.0.0.1"; + description = '' + Local system IP address to be used for CLI server endpoint. + ''; + }; + cli-port = mkOption { + type = types.int; + default = 5766; + description = '' + CLI server port. + ''; + }; + cli-password = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + CLI access password. + For the security reasons, it is recommended to use the encrypted + for of the password (see the -P command in the turnadmin utility). + ''; + }; + no-udp = mkOption { + type = types.bool; + default = false; + description = "Disable UDP client listener"; + }; + no-tcp = mkOption { + type = types.bool; + default = false; + description = "Disable TCP client listener"; + }; + no-tls = mkOption { + type = types.bool; + default = false; + description = "Disable TLS client listener"; + }; + no-dtls = mkOption { + type = types.bool; + default = false; + description = "Disable DTLS client listener"; + }; + no-udp-relay = mkOption { + type = types.bool; + default = false; + description = "Disable UDP relay endpoints"; + }; + no-tcp-relay = mkOption { + type = types.bool; + default = false; + description = "Disable TCP relay endpoints"; + }; + extraConfig = mkOption { + type = types.lines; + default = ""; + description = "Additional configuration options"; + }; + }; + }; + + config = mkIf cfg.enable { + users.extraUsers = [ + { name = "turnserver"; + uid = config.ids.uids.turnserver; + description = "coturn TURN server user"; + } ]; + users.extraGroups = [ + { name = "turnserver"; + gid = config.ids.gids.turnserver; + members = [ "turnserver" ]; + } ]; + + systemd.services.coturn = { + description = "coturn TURN server"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + unitConfig = { + Documentation = "man:coturn(1) man:turnadmin(1) man:turnserver(1)"; + }; + + serviceConfig = { + Type = "simple"; + ExecStart = "${pkgs.coturn}/bin/turnserver -c ${configFile}"; + RuntimeDirectory = "turnserver"; + User = "turnserver"; + Group = "turnserver"; + Restart = "on-abort"; + }; + }; + }; +} diff --git a/nixos/modules/services/networking/ejabberd.nix b/nixos/modules/services/networking/ejabberd.nix index 9868f303ab2b..8ecc16257db8 100644 --- a/nixos/modules/services/networking/ejabberd.nix +++ b/nixos/modules/services/networking/ejabberd.nix @@ -13,7 +13,7 @@ let ectl = ''${cfg.package}/bin/ejabberdctl ${if cfg.configFile == null then "" else "--config ${cfg.configFile}"} --ctl-config "${ctlcfg}" --spool "${cfg.spoolDir}" --logs "${cfg.logsDir}"''; - dumps = lib.concatMapStringsSep " " lib.escapeShellArg cfg.loadDumps; + dumps = lib.escapeShellArgs cfg.loadDumps; in { diff --git a/nixos/modules/services/networking/pptpd.nix b/nixos/modules/services/networking/pptpd.nix index efed604d3dda..513e6174752c 100644 --- a/nixos/modules/services/networking/pptpd.nix +++ b/nixos/modules/services/networking/pptpd.nix @@ -16,7 +16,7 @@ with lib; clientIpRange = mkOption { type = types.string; description = "The range from which client IPs are drawn."; - default = "10.124.142.2-11"; + default = "10.124.124.2-11"; }; maxClients = mkOption { diff --git a/nixos/modules/services/networking/xl2tpd.nix b/nixos/modules/services/networking/xl2tpd.nix new file mode 100644 index 000000000000..5e006c13f0d0 --- /dev/null +++ b/nixos/modules/services/networking/xl2tpd.nix @@ -0,0 +1,143 @@ +{ config, stdenv, pkgs, lib, ... }: + +with lib; + +{ + options = { + services.xl2tpd = { + enable = mkEnableOption "Whether xl2tpd should be run on startup."; + + serverIp = mkOption { + type = types.string; + description = "The server-side IP address."; + default = "10.125.125.1"; + }; + + clientIpRange = mkOption { + type = types.string; + description = "The range from which client IPs are drawn."; + default = "10.125.125.2-11"; + }; + + extraXl2tpOptions = mkOption { + type = types.lines; + description = "Adds extra lines to the xl2tpd configuration file."; + default = ""; + }; + + extraPppdOptions = mkOption { + type = types.lines; + description = "Adds extra lines to the pppd options file."; + default = ""; + example = '' + ms-dns 8.8.8.8 + ms-dns 8.8.4.4 + ''; + }; + }; + }; + + config = mkIf config.services.xl2tpd.enable { + systemd.services.xl2tpd = let + cfg = config.services.xl2tpd; + + # Config files from https://help.ubuntu.com/community/L2TPServer + xl2tpd-conf = pkgs.writeText "xl2tpd.conf" '' + [global] + ipsec saref = no + + [lns default] + local ip = ${cfg.serverIp} + ip range = ${cfg.clientIpRange} + pppoptfile = ${pppd-options} + length bit = yes + + ; Extra + ${cfg.extraXl2tpOptions} + ''; + + pppd-options = pkgs.writeText "ppp-options-xl2tpd.conf" '' + refuse-pap + refuse-chap + refuse-mschap + require-mschap-v2 + # require-mppe-128 + asyncmap 0 + auth + crtscts + idle 1800 + mtu 1200 + mru 1200 + lock + hide-password + local + # debug + name xl2tpd + # proxyarp + lcp-echo-interval 30 + lcp-echo-failure 4 + + # Extra: + ${cfg.extraPppdOptions} + ''; + + xl2tpd-ppp-wrapped = pkgs.stdenv.mkDerivation { + name = "xl2tpd-ppp-wrapped"; + phases = [ "installPhase" ]; + buildInputs = with pkgs; [ makeWrapper ]; + installPhase = '' + mkdir -p $out/bin + + makeWrapper ${pkgs.ppp}/sbin/pppd $out/bin/pppd \ + --set LD_PRELOAD "${pkgs.libredirect}/lib/libredirect.so" \ + --set NIX_REDIRECTS "/etc/ppp=/etc/xl2tpd/ppp" + + makeWrapper ${pkgs.xl2tpd}/bin/xl2tpd $out/bin/xl2tpd \ + --set LD_PRELOAD "${pkgs.libredirect}/lib/libredirect.so" \ + --set NIX_REDIRECTS "${pkgs.ppp}/sbin/pppd=$out/bin/pppd" + ''; + }; + in { + description = "xl2tpd server"; + + requires = [ "network-online.target" ]; + wantedBy = [ "multi-user.target" ]; + + preStart = '' + mkdir -p -m 700 /etc/xl2tpd + + pushd /etc/xl2tpd > /dev/null + + mkdir -p -m 700 ppp + + [ -f ppp/chap-secrets ] || cat > ppp/chap-secrets << EOF + # Secrets for authentication using CHAP + # client server secret IP addresses + #username xl2tpd password * + EOF + + chown root.root ppp/chap-secrets + chmod 600 ppp/chap-secrets + + # The documentation says this file should be present but doesn't explain why and things work even if not there: + [ -f l2tp-secrets ] || (echo -n "* * "; ${pkgs.apg}/bin/apg -n 1 -m 32 -x 32 -a 1 -M LCN) > l2tp-secrets + chown root.root l2tp-secrets + chmod 600 l2tp-secrets + + popd > /dev/null + + mkdir -p /run/xl2tpd + chown root.root /run/xl2tpd + chmod 700 /run/xl2tpd + ''; + + serviceConfig = { + ExecStart = "${xl2tpd-ppp-wrapped}/bin/xl2tpd -D -c ${xl2tpd-conf} -s /etc/xl2tpd/l2tp-secrets -p /run/xl2tpd/pid -C /run/xl2tpd/control"; + KillMode = "process"; + Restart = "on-success"; + Type = "simple"; + PIDFile = "/run/xl2tpd/pid"; + }; + }; + }; +} diff --git a/nixos/modules/services/web-servers/lighttpd/inginious.nix b/nixos/modules/services/web-servers/lighttpd/inginious.nix new file mode 100644 index 000000000000..43deccb6aef8 --- /dev/null +++ b/nixos/modules/services/web-servers/lighttpd/inginious.nix @@ -0,0 +1,262 @@ +{ config, lib, pkgs, ... }: +with lib; + +let + cfg = config.services.lighttpd.inginious; + inginious = pkgs.inginious; + execName = "inginious-${if cfg.useLTI then "lti" else "webapp"}"; + + inginiousConfigFile = if cfg.configFile != null then cfg.configFile else pkgs.writeText "inginious.yaml" '' + # Backend; can be: + # - "local" (run containers on the same machine) + # - "remote" (connect to distant docker daemon and auto start agents) (choose this if you use boot2docker) + # - "remote_manual" (connect to distant and manually installed agents) + backend: "${cfg.backendType}" + + ## TODO (maybe): Add an option for the "remote" backend in this NixOS module. + # List of remote docker daemon to which the backend will try + # to connect (backend: remote only) + #docker_daemons: + # - # Host of the docker daemon *from the webapp* + # remote_host: "some.remote.server" + # # Port of the distant docker daemon *from the webapp* + # remote_docker_port: "2375" + # # A mandatory port used by the backend and the agent that will be automatically started. + # # Needs to be available on the remote host, and to be open in the firewall. + # remote_agent_port: "63456" + # # Does the remote docker requires tls? Defaults to false. + # # Parameter can be set to true or path to the certificates + # #use_tls: false + # # Link to the docker daemon *from the host that runs the docker daemon*. Defaults to: + # #local_location: "unix:///var/run/docker.sock" + # # Path to the cgroups "mount" *from the host that runs the docker daemon*. Defaults to: + # #cgroups_location: "/sys/fs/cgroup" + # # Name that will be used to reference the agent + # #"agent_name": "inginious-agent" + + # List of remote agents to which the backend will try + # to connect (backend: remote_manual only) + # Example: + #agents: + # - host: "192.168.59.103" + # port: 5001 + agents: + ${lib.concatMapStrings (agent: + " - host: \"${agent.host}\"\n" + + " port: ${agent.port}\n" + ) cfg.remoteAgents} + + # Location of the task directory + tasks_directory: "${cfg.tasksDirectory}" + + # Super admins: list of user names that can do everything in the backend + superadmins: + ${lib.concatMapStrings (x: " - \"${x}\"\n") cfg.superadmins} + + # Aliases for containers + # Only containers listed here can be used by tasks + containers: + ${lib.concatStrings (lib.mapAttrsToList (name: fullname: + " ${name}: \"${fullname}\"\n" + ) cfg.containers)} + + # Use single minified javascript file (production) or multiple files (dev) ? + use_minified_js: true + + ## TODO (maybe): Add NixOS options for these parameters. + + # MongoDB options + #mongo_opt: + # host: localhost + # database: INGInious + + # Disable INGInious? + #maintenance: false + + #smtp: + # sendername: 'INGInious <no-reply@inginious.org>' + # host: 'smtp.gmail.com' + # port: 587 + # username: 'configme@gmail.com' + # password: 'secret' + # starttls: True + + ## NixOS extra config + + ${cfg.extraConfig} + ''; +in +{ + options.services.lighttpd.inginious = { + enable = mkEnableOption "INGInious, an automated code testing and grading system."; + + configFile = mkOption { + type = types.nullOr types.path; + default = null; + example = literalExample ''pkgs.writeText "configuration.yaml" "# custom config options ...";''; + description = ''The path to an INGInious configuration file.''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + # Load the dummy auth plugin. + plugins: + - plugin_module: inginious.frontend.webapp.plugins.auth.demo_auth + users: + # register the user "test" with the password "someverycomplexpassword" + test: someverycomplexpassword + ''; + description = ''Extra option in YaML format, to be appended to the config file.''; + }; + + tasksDirectory = mkOption { + type = types.path; + default = "${inginious}/lib/python2.7/site-packages/inginious/tasks"; + example = "/var/lib/INGInious/tasks"; + description = '' + Path to the tasks folder. + Defaults to the provided test tasks folder (readonly). + ''; + }; + + useLTI = mkOption { + type = types.bool; + default = false; + description = ''Whether to start the LTI frontend in place of the webapp.''; + }; + + superadmins = mkOption { + type = types.uniq (types.listOf types.str); + default = [ "admin" ]; + example = [ "john" "pepe" "emilia" ]; + description = ''List of user logins allowed to administrate the whole server.''; + }; + + containers = mkOption { + type = types.attrsOf types.str; + default = { + default = "ingi/inginious-c-default"; + }; + example = { + default = "ingi/inginious-c-default"; + sekexe = "ingi/inginious-c-sekexe"; + java = "ingi/inginious-c-java"; + oz = "ingi/inginious-c-oz"; + pythia1compat = "ingi/inginious-c-pythia1compat"; + }; + description = '' + An attrset describing the required containers + These containers will be available in INGInious using their short name (key) + and will be automatically downloaded before INGInious starts. + ''; + }; + + hostPattern = mkOption { + type = types.str; + default = "^inginious."; + example = "^inginious.mydomain.xyz$"; + description = '' + The domain that serves INGInious. + INGInious uses absolute paths which makes it difficult to relocate in its own subdir. + The default configuration will serve INGInious when the server is accessed with a hostname starting with "inginious.". + If left blank, INGInious will take the precedence over all the other lighttpd sites, which is probably not what you want. + ''; + }; + + backendType = mkOption { + type = types.enum [ "local" "remote_manual" ]; # TODO: support backend "remote" + default = "local"; + description = '' + Select how INGINious accesses to grading containers. + The default "local" option ensures that Docker is started and provisioned. + Fore more information, see http://inginious.readthedocs.io/en/latest/install_doc/config_reference.html + Not all backends are supported. Use services.inginious.configFile for full flexibility. + ''; + }; + + remoteAgents = mkOption { + type = types.listOf (types.attrsOf types.str); + default = []; + example = [ { host = "192.0.2.25"; port = "1345"; } ]; + description = ''A list of remote agents, used only when services.inginious.backendType is "remote_manual".''; + }; + }; + + config = mkIf cfg.enable ( + mkMerge [ + # For a local install, we need docker. + (mkIf (cfg.backendType == "local") { + virtualisation.docker = { + enable = true; + # We need docker to listen on port 2375. + extraOptions = "-H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock"; + storageDriver = mkDefault "overlay"; + socketActivation = false; + }; + + users.extraUsers."lighttpd".extraGroups = [ "docker" ]; + + # Ensure that docker has pulled the required images. + systemd.services.inginious-prefetch = { + script = let + images = lib.unique ( + [ "centos" "ingi/inginious-agent" ] + ++ lib.mapAttrsToList (_: image: image) cfg.containers + ); + in lib.concatMapStrings (image: '' + ${pkgs.docker}/bin/docker pull ${image} + '') images; + + serviceConfig.Type = "oneshot"; + wants = [ "docker.service" ]; + after = [ "docker.service" ]; + wantedBy = [ "lighttpd.service" ]; + before = [ "lighttpd.service" ]; + }; + }) + + # Common + { + # To access inginous tools (like inginious-test-task) + environment.systemPackages = [ inginious ]; + + services.mongodb.enable = true; + + services.lighttpd.enable = true; + services.lighttpd.enableModules = [ "mod_access" "mod_alias" "mod_fastcgi" "mod_redirect" "mod_rewrite" ]; + services.lighttpd.extraConfig = '' + $HTTP["host"] =~ "${cfg.hostPattern}" { + fastcgi.server = ( "/${execName}" => + (( + "socket" => "/run/lighttpd/inginious-fastcgi.socket", + "bin-path" => "${inginious}/bin/${execName} --config=${inginiousConfigFile}", + "max-procs" => 1, + "bin-environment" => ( "REAL_SCRIPT_NAME" => "" ), + "check-local" => "disable" + )) + ) + url.rewrite-once = ( + "^/.well-known/.*" => "$0", + "^/static/.*" => "$0", + "^/.*$" => "/${execName}$0", + "^/favicon.ico$" => "/static/common/favicon.ico", + ) + alias.url += ( + "/static/webapp/" => "${inginious}/lib/python2.7/site-packages/inginious/frontend/webapp/static/", + "/static/common/" => "${inginious}/lib/python2.7/site-packages/inginious/frontend/common/static/" + ) + } + ''; + + systemd.services.lighttpd.preStart = '' + mkdir -p /run/lighttpd + chown lighttpd.lighttpd /run/lighttpd + ''; + + systemd.services.lighttpd.wants = [ "mongodb.service" "docker.service" ]; + systemd.services.lighttpd.after = [ "mongodb.service" "docker.service" ]; + } + ]); +} diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix index 700faad0c695..68579a1af836 100644 --- a/nixos/modules/services/x11/desktop-managers/gnome3.nix +++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix @@ -119,6 +119,7 @@ in { services.telepathy.enable = mkDefault true; networking.networkmanager.enable = mkDefault true; services.upower.enable = config.powerManagement.enable; + services.dbus.packages = mkIf config.services.printing.enable [ pkgs.system-config-printer ]; hardware.bluetooth.enable = mkDefault true; fonts.fonts = [ pkgs.dejavu_fonts pkgs.cantarell_fonts ]; diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix index 4c4e3d967988..634d2a39576a 100644 --- a/nixos/modules/services/x11/desktop-managers/xfce.nix +++ b/nixos/modules/services/x11/desktop-managers/xfce.nix @@ -33,6 +33,14 @@ in default = false; description = "Don't install XFCE desktop components (xfdesktop, panel and notification daemon)."; }; + + extraSessionCommands = mkOption { + default = ""; + type = types.lines; + description = '' + Shell commands executed just before XFCE is started. + ''; + }; }; }; @@ -45,6 +53,8 @@ in bgSupport = true; start = '' + ${cfg.extraSessionCommands} + # Set GTK_PATH so that GTK+ can find the theme engines. export GTK_PATH="${config.system.path}/lib/gtk-2.0:${config.system.path}/lib/gtk-3.0" diff --git a/nixos/modules/services/x11/window-managers/i3.nix b/nixos/modules/services/x11/window-managers/i3.nix index aea0a8986786..cfe9439b688c 100644 --- a/nixos/modules/services/x11/window-managers/i3.nix +++ b/nixos/modules/services/x11/window-managers/i3.nix @@ -15,12 +15,21 @@ let If left at the default value, $HOME/.i3/config will be used. ''; }; + extraSessionCommands = mkOption { + default = ""; + type = types.lines; + description = '' + Shell commands executed just before i3 is started. + ''; + }; }; i3config = name: pkg: cfg: { services.xserver.windowManager.session = [{ inherit name; start = '' + ${cfg.extraSessionCommands} + ${pkg}/bin/i3 ${optionalString (cfg.configFile != null) "-c \"${cfg.configFile}\"" } & diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index 076bbca850d9..3d8f29c80f95 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -669,6 +669,7 @@ in "systemd/logind.conf".text = '' [Login] + KillUserProcesses=no ${config.services.logind.extraConfig} ''; diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix index dd351306cb63..cf8232c36154 100644 --- a/nixos/modules/tasks/filesystems.nix +++ b/nixos/modules/tasks/filesystems.nix @@ -111,15 +111,17 @@ in fileSystems = mkOption { default = {}; - example = { - "/".device = "/dev/hda1"; - "/data" = { - device = "/dev/hda2"; - fsType = "ext3"; - options = [ "data=journal" ]; - }; - "/bigdisk".label = "bigdisk"; - }; + example = literalExample '' + { + "/".device = "/dev/hda1"; + "/data" = { + device = "/dev/hda2"; + fsType = "ext3"; + options = [ "data=journal" ]; + }; + "/bigdisk".label = "bigdisk"; + } + ''; type = types.loaOf types.optionSet; options = [ fileSystemOpts ]; description = '' diff --git a/nixos/modules/virtualisation/lxd.nix b/nixos/modules/virtualisation/lxd.nix index 845f14352f3d..9d76b890872a 100644 --- a/nixos/modules/virtualisation/lxd.nix +++ b/nixos/modules/virtualisation/lxd.nix @@ -47,7 +47,7 @@ in # TODO(wkennington): Add lvm2 and thin-provisioning-tools path = with pkgs; [ acl rsync gnutar xz btrfs-progs ]; - serviceConfig.ExecStart = "@${pkgs.lxd}/bin/lxd lxd --syslog --group lxd"; + serviceConfig.ExecStart = "@${pkgs.lxd.bin}/bin/lxd lxd --syslog --group lxd"; serviceConfig.Type = "simple"; serviceConfig.KillMode = "process"; # when stopping, leave the containers alone }; |