diff options
Diffstat (limited to 'nixos')
39 files changed, 1315 insertions, 277 deletions
diff --git a/nixos/doc/manual/installation/installing-virtualbox-guest.xml b/nixos/doc/manual/installation/installing-virtualbox-guest.xml new file mode 100644 index 000000000000..8fe61a5fdfdf --- /dev/null +++ b/nixos/doc/manual/installation/installing-virtualbox-guest.xml @@ -0,0 +1,89 @@ +<section xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xi="http://www.w3.org/2001/XInclude" + version="5.0" + xml:id="sec-instaling-virtualbox-guest"> + +<title>Installing in a Virtualbox guest</title> +<para> + Installing NixOS into a Virtualbox guest is convenient for users who want to + try NixOS without installing it on bare metal. If you want to use a pre-made + Virtualbox appliance, it is available at <link + xlink:href="https://nixos.org/nixos/download.html">the downloads page</link>. + If you want to set up a Virtualbox guest manually, follow these instructions: +</para> + +<orderedlist> + + <listitem><para>Add a New Machine in Virtualbox with OS Type "Linux / Other + Linux"</para></listitem> + + <listitem><para>Base Memory Size: 768 MB or higher.</para></listitem> + + <listitem><para>New Hard Disk of 8 GB or higher.</para></listitem> + + <listitem><para>Mount the CD-ROM with the NixOS ISO (by clicking on + CD/DVD-ROM)</para></listitem> + + <listitem><para>Click on Settings / System / Processor and enable + PAE/NX</para></listitem> + + <listitem><para>Click on Settings / System / Acceleration and enable + "VT-x/AMD-V" acceleration</para></listitem> + + <listitem><para>Save the settings, start the virtual machine, and continue + installation like normal</para></listitem> + +</orderedlist> + +<para> + There are a few modifications you should make in configuration.nix. Enable + the virtualbox guest service in the main block: +</para> + +<programlisting> +virtualisation.virtualbox.guest.enable = true; +</programlisting> + +<para> + Enable booting: +</para> + +<programlisting> +boot.loader.grub.device = "/dev/sda"; +</programlisting> + +<para> + Also remove the fsck that runs at startup. It will always fail to run, + stopping your boot until you press <literal>*</literal>. +</para> + +<programlisting> +boot.initrd.checkJournalingFS = false; +</programlisting> + +<para> + Shared folders can be given a name and a path in the host system in the + VirtualBox settings (Machine / Settings / Shared Folders, then click on the + "Add" icon). Add the following to the + <literal>/etc/nixos/configuration.nix</literal> to auto-mount them: +</para> + +<programlisting> +{ config, pkgs, ...} : +{ + ... + + fileSystems."/virtualboxshare" = { + fsType = "vboxsf"; + device = "nameofthesharedfolder"; + options = [ "rw" ]; + }; +} +</programlisting> + +<para> + The folder will be available directly under the root directory. +</para> + +</section> diff --git a/nixos/doc/manual/installation/installing.xml b/nixos/doc/manual/installation/installing.xml index 073f7ca34620..04a186a1bca6 100644 --- a/nixos/doc/manual/installation/installing.xml +++ b/nixos/doc/manual/installation/installing.xml @@ -271,5 +271,6 @@ drive (here <filename>/dev/sda</filename>). <xref linkend="ex-config" <xi:include href="installing-uefi.xml" /> <xi:include href="installing-usb.xml" /> <xi:include href="installing-pxe.xml" /> +<xi:include href="installing-virtualbox-guest.xml" /> </chapter> diff --git a/nixos/doc/manual/man-nixos-install.xml b/nixos/doc/manual/man-nixos-install.xml index 7ad1be1ec105..15c603256ca7 100644 --- a/nixos/doc/manual/man-nixos-install.xml +++ b/nixos/doc/manual/man-nixos-install.xml @@ -26,6 +26,19 @@ <replaceable>root</replaceable> </arg> <arg> + <arg choice='plain'><option>--closure</option></arg> + <replaceable>closure</replaceable> + </arg> + <arg> + <arg choice='plain'><option>--no-channel-copy</option></arg> + </arg> + <arg> + <arg choice='plain'><option>--no-root-passwd</option></arg> + </arg> + <arg> + <arg choice='plain'><option>--no-bootloader</option></arg> + </arg> + <arg> <group choice='req'> <arg choice='plain'><option>--max-jobs</option></arg> <arg choice='plain'><option>-j</option></arg> @@ -71,12 +84,13 @@ the following steps: <filename>/mnt/etc/nixos/configuration.nix</filename>.</para></listitem> <listitem><para>It installs the GRUB boot loader on the device - specified in the option <option>boot.loader.grub.device</option>, + specified in the option <option>boot.loader.grub.device</option> + (unless <option>--no-bootloader</option> is specified), and generates a GRUB configuration file that boots into the NixOS configuration just installed.</para></listitem> - <listitem><para>It prompts you for a password for the root - account.</para></listitem> + <listitem><para>It prompts you for a password for the root account + (unless <option>--no-root-passwd</option> is specified).</para></listitem> </itemizedlist> @@ -104,6 +118,19 @@ it.</para> </varlistentry> <varlistentry> + <term><option>--closure</option></term> + <listitem> + <para>If this option is provided, <command>nixos-install</command> will install the specified closure + rather than attempt to build one from <filename>/mnt/etc/nixos/configuration.nix</filename>.</para> + + <para>The closure must be an appropriately configured NixOS system, with boot loader and partition + configuration that fits the target host. Such a closure is typically obtained with a command such as + <command>nix-build -I nixos-config=./configuration.nix '<nixos>' -A system --no-out-link</command> + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><option>-I</option></term> <listitem> <para>Add a path to the Nix expression search path. This option may be given multiple times. diff --git a/nixos/doc/manual/release-notes/rl-1609.xml b/nixos/doc/manual/release-notes/rl-1609.xml index 8dbf03ee42b4..8dd4e1a9f642 100644 --- a/nixos/doc/manual/release-notes/rl-1609.xml +++ b/nixos/doc/manual/release-notes/rl-1609.xml @@ -42,10 +42,22 @@ following incompatible changes:</para> </listitem> <listitem> - <para>Redis now binds to 127.0.0.1 only instead of listening to all network interfaces. This is the default + <para>Redis now binds to 127.0.0.1 only instead of listening to all network interfaces. This is the default behavior of Redis 3.2</para> </listitem> + <listitem> + <para>Gitlab's maintainence script gitlab-runner was removed and split up into the more clearer + gitlab-run and gitlab-rake scripts because gitlab-runner is a component of Gitlab CI.</para> + </listitem> + + <listitem> + <para><literal>services.xserver.libinput.accelProfile</literal> default + changed from <literal>flat</literal> to <literal>adaptive</literal>, + as per <link xlink:href="https://wayland.freedesktop.org/libinput/doc/latest/group__config.html#gad63796972347f318b180e322e35cee79"> + official documentation</link>.</para> + </listitem> + </itemizedlist> diff --git a/nixos/modules/config/system-path.nix b/nixos/modules/config/system-path.nix index 3054439da655..9708b5d9fe33 100644 --- a/nixos/modules/config/system-path.nix +++ b/nixos/modules/config/system-path.nix @@ -34,7 +34,6 @@ let config.programs.ssh.package pkgs.perl pkgs.procps - pkgs.rsync pkgs.strace pkgs.su pkgs.time diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh index 7962be137875..0247925f4144 100644 --- a/nixos/modules/installer/tools/nixos-install.sh +++ b/nixos/modules/installer/tools/nixos-install.sh @@ -24,6 +24,7 @@ fi # Parse the command line for the -I flag extraBuildFlags=() chrootCommand=(/run/current-system/sw/bin/bash) +bootLoader=1 while [ "$#" -gt 0 ]; do i="$1"; shift 1 @@ -40,6 +41,18 @@ while [ "$#" -gt 0 ]; do --root) mountPoint="$1"; shift 1 ;; + --closure) + closure="$1"; shift 1 + ;; + --no-channel-copy) + noChannelCopy=1 + ;; + --no-root-passwd) + noRootPasswd=1 + ;; + --no-bootloader) + bootLoader=0 + ;; --show-trace) extraBuildFlags+=("$i") ;; @@ -111,7 +124,7 @@ if test -z "$NIXOS_CONFIG"; then NIXOS_CONFIG=/etc/nixos/configuration.nix fi -if ! test -e "$mountPoint/$NIXOS_CONFIG"; then +if [ ! -e "$mountPoint/$NIXOS_CONFIG" ] && [ -z "$closure" ]; then echo "configuration file $mountPoint/$NIXOS_CONFIG doesn't exist" exit 1 fi @@ -162,7 +175,7 @@ if ! NIX_DB_DIR=$mountPoint/nix/var/nix/db nix-store --check-validity @nix@ 2> / for i in $(@perl@/bin/perl @pathsFromGraph@ @nixClosure@); do echo " $i" chattr -R -i $mountPoint/$i 2> /dev/null || true # clear immutable bit - rsync -a $i $mountPoint/nix/store/ + @rsync@/bin/rsync -a $i $mountPoint/nix/store/ done # Register the paths in the Nix closure as valid. This is necessary @@ -200,16 +213,22 @@ for i in /nix/var/nix/manifests/*.nixmanifest; do done -# Get the absolute path to the NixOS/Nixpkgs sources. -nixpkgs="$(readlink -f $(nix-instantiate --find-file nixpkgs))" +if [ -z "$closure" ]; then + # Get the absolute path to the NixOS/Nixpkgs sources. + nixpkgs="$(readlink -f $(nix-instantiate --find-file nixpkgs))" + nixEnvAction="-f <nixpkgs/nixos> --set -A system" +else + nixpkgs="" + nixEnvAction="--set $closure" +fi # Build the specified Nix expression in the target store and install # it into the system configuration profile. echo "building the system configuration..." NIX_PATH="nixpkgs=/tmp/root/$nixpkgs:nixos-config=$NIXOS_CONFIG" NIXOS_CONFIG= \ chroot $mountPoint @nix@/bin/nix-env \ - "${extraBuildFlags[@]}" -p /nix/var/nix/profiles/system -f '<nixpkgs/nixos>' --set -A system + "${extraBuildFlags[@]}" -p /nix/var/nix/profiles/system $nixEnvAction # Copy the NixOS/Nixpkgs sources to the target as the initial contents @@ -218,7 +237,7 @@ mkdir -m 0755 -p $mountPoint/nix/var/nix/profiles mkdir -m 1777 -p $mountPoint/nix/var/nix/profiles/per-user mkdir -m 0755 -p $mountPoint/nix/var/nix/profiles/per-user/root srcs=$(nix-env "${extraBuildFlags[@]}" -p /nix/var/nix/profiles/per-user/root/channels -q nixos --no-name --out-path 2>/dev/null || echo -n "") -if test -n "$srcs"; then +if [ -z "$noChannelCopy" ] && [ -n "$srcs" ]; then echo "copying NixOS/Nixpkgs sources..." chroot $mountPoint @nix@/bin/nix-env \ "${extraBuildFlags[@]}" -p /nix/var/nix/profiles/per-user/root/channels -i "$srcs" --quiet @@ -244,7 +263,7 @@ touch $mountPoint/etc/NIXOS # a menu default pointing at the kernel/initrd/etc of the new # configuration. echo "finalising the installation..." -NIXOS_INSTALL_GRUB=1 chroot $mountPoint \ +NIXOS_INSTALL_GRUB="$bootLoader" chroot $mountPoint \ /nix/var/nix/profiles/system/bin/switch-to-configuration boot @@ -253,7 +272,7 @@ chroot $mountPoint /nix/var/nix/profiles/system/activate # Ask the user to set a root password. -if [ "$(chroot $mountPoint /run/current-system/sw/bin/sh -l -c "nix-instantiate --eval '<nixpkgs/nixos>' -A config.users.mutableUsers")" = true ] && [ -t 0 ] ; then +if [ -z "$noRootPasswd" ] && [ "$(chroot $mountPoint /run/current-system/sw/bin/sh -l -c "nix-instantiate --eval '<nixpkgs/nixos>' -A config.users.mutableUsers")" = true ] && [ -t 0 ] ; then echo "setting root password..." chroot $mountPoint /var/setuid-wrappers/passwd fi diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh index 5ecdcdb3cdb5..e26a9f6cf635 100644 --- a/nixos/modules/installer/tools/nixos-rebuild.sh +++ b/nixos/modules/installer/tools/nixos-rebuild.sh @@ -214,9 +214,9 @@ fi # Re-execute nixos-rebuild from the Nixpkgs tree. if [ -z "$_NIXOS_REBUILD_REEXEC" -a -n "$canRun" ]; then - if p=$(nix-instantiate --find-file nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh "${extraBuildFlags[@]}"); then + if p=$(nix-build --no-out-link --expr 'with import <nixpkgs/nixos> {}; config.system.build.nixos-rebuild' "${extraBuildFlags[@]}"); then export _NIXOS_REBUILD_REEXEC=1 - exec $SHELL -e $p "${origArgs[@]}" + exec $p/bin/nixos-rebuild "${origArgs[@]}" exit 1 fi fi diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix index d8622b510522..a55c03bd9528 100644 --- a/nixos/modules/installer/tools/tools.nix +++ b/nixos/modules/installer/tools/tools.nix @@ -21,7 +21,7 @@ let name = "nixos-install"; src = ./nixos-install.sh; - inherit (pkgs) perl pathsFromGraph; + inherit (pkgs) perl pathsFromGraph rsync; nix = config.nix.package.out; cacert = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"; diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 3ba279f597da..83b47728639c 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -273,6 +273,7 @@ smokeping = 250; gocd-agent = 251; gocd-server = 252; + terraria = 253; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -516,6 +517,7 @@ smokeping = 250; gocd-agent = 251; gocd-server = 252; + terraria = 253; # 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/misc/version.nix b/nixos/modules/misc/version.nix index 6af310a9d877..2ecdbdbf3925 100644 --- a/nixos/modules/misc/version.nix +++ b/nixos/modules/misc/version.nix @@ -63,7 +63,9 @@ in nixosRevision = mkOption { internal = true; type = types.str; - default = if pathExists revisionFile then fileContents revisionFile else "master"; + default = if pathIsDirectory gitRepo then commitIdFromGitRepo gitRepo + else if pathExists revisionFile then fileContents revisionFile + else "master"; description = "The Git revision from which this NixOS configuration was built."; }; diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 9f1ca0f69232..044838161f05 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -62,8 +62,7 @@ ./programs/bash/bash.nix ./programs/blcr.nix ./programs/cdemu.nix - # see https://github.com/NixOS/nixos-channel-scripts/issues/4 - #./programs/command-not-found/command-not-found.nix + ./programs/command-not-found/command-not-found.nix ./programs/dconf.nix ./programs/environment.nix ./programs/freetds.nix @@ -80,7 +79,6 @@ ./programs/ssh.nix ./programs/ssmtp.nix ./programs/tmux.nix - ./programs/unity3d.nix ./programs/venus.nix ./programs/wvdial.nix ./programs/xfs_quota.nix @@ -92,6 +90,7 @@ ./security/apparmor-suid.nix ./security/audit.nix ./security/ca.nix + ./security/chromium-suid-sandbox.nix ./security/duosec.nix ./security/grsecurity.nix ./security/hidepid.nix @@ -137,6 +136,7 @@ ./services/continuous-integration/jenkins/slave.nix ./services/databases/4store-endpoint.nix ./services/databases/4store.nix + ./services/databases/cassandra.nix ./services/databases/couchdb.nix ./services/databases/firebird.nix ./services/databases/hbase.nix @@ -173,6 +173,7 @@ ./services/games/ghost-one.nix ./services/games/minecraft-server.nix ./services/games/minetest-server.nix + ./services/games/terraria.nix ./services/hardware/acpid.nix ./services/hardware/actkbd.nix ./services/hardware/amd-hybrid-graphics.nix @@ -473,7 +474,7 @@ ./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/phpfpm/default.nix ./services/web-servers/shellinabox.nix ./services/web-servers/tomcat.nix ./services/web-servers/uwsgi.nix diff --git a/nixos/modules/programs/unity3d.nix b/nixos/modules/programs/unity3d.nix deleted file mode 100644 index 3c0ea26d9d56..000000000000 --- a/nixos/modules/programs/unity3d.nix +++ /dev/null @@ -1,25 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let cfg = config.programs.unity3d; -in { - - options = { - programs.unity3d.enable = mkEnableOption "Unity3D, a game development tool"; - }; - - config = mkIf cfg.enable { - security.setuidOwners = [{ - program = "unity-chrome-sandbox"; - source = "${pkgs.unity3d.sandbox}/bin/unity-chrome-sandbox"; - owner = "root"; - #group = "root"; - setuid = true; - #setgid = true; - }]; - - environment.systemPackages = [ pkgs.unity3d ]; - }; - -} diff --git a/nixos/modules/programs/zsh/zsh.nix b/nixos/modules/programs/zsh/zsh.nix index b51104c16fa9..1b8b7a79593e 100644 --- a/nixos/modules/programs/zsh/zsh.nix +++ b/nixos/modules/programs/zsh/zsh.nix @@ -116,6 +116,8 @@ in done ${if cfg.enableCompletion then "autoload -U compinit && compinit" else ""} + + HELPDIR="${pkgs.zsh}/share/zsh/$ZSH_VERSION/help" ''; }; diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index 634f91a275d3..3f8a770cbce7 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -134,6 +134,9 @@ with lib; (mkRemovedOptionModule [ "security" "grsecurity" "config" "verboseVersion" ]) (mkRemovedOptionModule [ "security" "grsecurity" "config" "kernelExtraConfig" ]) + # Unity3D + (mkRenamedOptionModule [ "programs" "unity3d" "enable" ] [ "security" "chromiumSuidSandbox" "enable" ]) + # Options that are obsolete and have no replacement. (mkRemovedOptionModule [ "boot" "initrd" "luks" "enable" ]) (mkRemovedOptionModule [ "programs" "bash" "enable" ]) diff --git a/nixos/modules/security/chromium-suid-sandbox.nix b/nixos/modules/security/chromium-suid-sandbox.nix new file mode 100644 index 000000000000..88fbe518c2de --- /dev/null +++ b/nixos/modules/security/chromium-suid-sandbox.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.security.chromiumSuidSandbox; + sandbox = pkgs.chromium.sandbox; +in +{ + options.security.chromiumSuidSandbox.enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to install the Chromium SUID sandbox which is an executable that + Chromium may use in order to achieve sandboxing. + + If you get the error "The SUID sandbox helper binary was found, but is not + configured correctly.", turning this on might help. + + Also, if the URL chrome://sandbox tells you that "You are not adequately + sandboxed!", turning this on might resolve the issue. + + Finally, if you have <option>security.grsecurity</option> enabled and you + use Chromium, you probably need this. + ''; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ sandbox ]; + security.setuidPrograms = [ sandbox.passthru.sandboxExecutableName ]; + }; +} diff --git a/nixos/modules/services/continuous-integration/gocd-agent/default.nix b/nixos/modules/services/continuous-integration/gocd-agent/default.nix index 36f6527ee47b..21f319f7fcf6 100644 --- a/nixos/modules/services/continuous-integration/gocd-agent/default.nix +++ b/nixos/modules/services/continuous-integration/gocd-agent/default.nix @@ -36,7 +36,7 @@ in { }; packages = mkOption { - default = [ pkgs.stdenv pkgs.jre config.programs.ssh.package pkgs.nix ]; + default = [ pkgs.stdenv pkgs.jre pkgs.git config.programs.ssh.package pkgs.nix ]; type = types.listOf types.package; description = '' Packages to add to PATH for the Go.CD agent process. @@ -57,18 +57,10 @@ in { }; goServer = mkOption { - default = "127.0.0.1"; + default = "https://127.0.0.1:8154/go"; type = types.str; description = '' - Address of GoCD Server to attach the Go.CD Agent to. - ''; - }; - - goServerPort = mkOption { - default = 8153; - type = types.int; - description = '' - Port that Go.CD Server is Listening on. + URL of the GoCD Server to attach the Go.CD Agent to. ''; }; @@ -80,26 +72,26 @@ in { ''; }; - heapSize = mkOption { + initialJavaHeapSize = mkOption { default = "128m"; type = types.str; description = '' - Specifies the java heap memory size for the Go.CD agent java process. + Specifies the initial java heap memory size for the Go.CD agent java process. ''; }; - maxMemory = mkOption { + maxJavaHeapMemory = mkOption { default = "256m"; type = types.str; description = '' - Specifies the java maximum memory size for the Go.CD agent java process. + Specifies the java maximum heap memory size for the Go.CD agent java process. ''; }; startupOptions = mkOption { default = [ - "-Xms${cfg.heapSize}" - "-Xmx${cfg.maxMemory}" + "-Xms${cfg.initialJavaHeapSize}" + "-Xmx${cfg.maxJavaHeapMemory}" "-Djava.io.tmpdir=/tmp" "-Dcruise.console.publish.interval=10" "-Djava.security.egd=file:/dev/./urandom" @@ -112,8 +104,8 @@ in { extraOptions = mkOption { default = [ ]; - example = [ - "-X debug" + example = [ + "-X debug" "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006" "-verbose:gc" "-Xloggc:go-agent-gc.log" @@ -170,7 +162,7 @@ in { config.environment.sessionVariables; in selectedSessionVars // - { + { NIX_REMOTE = "daemon"; AGENT_WORK_DIR = cfg.workDir; AGENT_STARTUP_ARGS = ''${concatStringsSep " " cfg.startupOptions}''; @@ -199,13 +191,14 @@ in { ${pkgs.jre}/bin/java ${concatStringsSep " " cfg.startupOptions} \ ${concatStringsSep " " cfg.extraOptions} \ -jar ${pkgs.gocd-agent}/go-agent/agent-bootstrapper.jar \ - ${cfg.goServer} \ - ${toString cfg.goServerPort} + -serverUrl ${cfg.goServer} ''; serviceConfig = { User = cfg.user; WorkingDirectory = cfg.workDir; + RestartSec = 30; + Restart = "on-failure"; }; }; }; diff --git a/nixos/modules/services/databases/cassandra.nix b/nixos/modules/services/databases/cassandra.nix new file mode 100644 index 000000000000..c98af617587d --- /dev/null +++ b/nixos/modules/services/databases/cassandra.nix @@ -0,0 +1,449 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.cassandra; + cassandraPackage = cfg.package.override { + jre = cfg.jre; + }; + cassandraUser = { + name = cfg.user; + home = "/var/lib/cassandra"; + description = "Cassandra role user"; + }; + + cassandraRackDcProperties = '' + dc=${cfg.dc} + rack=${cfg.rack} + ''; + + cassandraConf = '' + cluster_name: ${cfg.clusterName} + num_tokens: 256 + auto_bootstrap: ${if cfg.autoBootstrap then "true" else "false"} + hinted_handoff_enabled: ${if cfg.hintedHandOff then "true" else "false"} + hinted_handoff_throttle_in_kb: ${builtins.toString cfg.hintedHandOffThrottle} + max_hints_delivery_threads: 2 + max_hint_window_in_ms: 10800000 # 3 hours + authenticator: ${cfg.authenticator} + authorizer: ${cfg.authorizer} + permissions_validity_in_ms: 2000 + partitioner: org.apache.cassandra.dht.Murmur3Partitioner + data_file_directories: + ${builtins.concatStringsSep "\n" (map (v: " - "+v) cfg.dataDirs)} + commitlog_directory: ${cfg.commitLogDirectory} + disk_failure_policy: stop + key_cache_size_in_mb: + key_cache_save_period: 14400 + row_cache_size_in_mb: 0 + row_cache_save_period: 0 + saved_caches_directory: ${cfg.savedCachesDirectory} + commitlog_sync: ${cfg.commitLogSync} + commitlog_sync_period_in_ms: ${builtins.toString cfg.commitLogSyncPeriod} + commitlog_segment_size_in_mb: 32 + seed_provider: + - class_name: org.apache.cassandra.locator.SimpleSeedProvider + parameters: + - seeds: "${builtins.concatStringsSep "," cfg.seeds}" + concurrent_reads: ${builtins.toString cfg.concurrentReads} + concurrent_writes: ${builtins.toString cfg.concurrentWrites} + memtable_flush_queue_size: 4 + trickle_fsync: false + trickle_fsync_interval_in_kb: 10240 + storage_port: 7000 + ssl_storage_port: 7001 + listen_address: ${cfg.listenAddress} + start_native_transport: true + native_transport_port: 9042 + start_rpc: true + rpc_address: ${cfg.rpcAddress} + rpc_port: 9160 + rpc_keepalive: true + rpc_server_type: sync + thrift_framed_transport_size_in_mb: 15 + incremental_backups: ${if cfg.incrementalBackups then "true" else "false"} + snapshot_before_compaction: false + auto_snapshot: true + column_index_size_in_kb: 64 + in_memory_compaction_limit_in_mb: 64 + multithreaded_compaction: false + compaction_throughput_mb_per_sec: 16 + compaction_preheat_key_cache: true + read_request_timeout_in_ms: 10000 + range_request_timeout_in_ms: 10000 + write_request_timeout_in_ms: 10000 + cas_contention_timeout_in_ms: 1000 + truncate_request_timeout_in_ms: 60000 + request_timeout_in_ms: 10000 + cross_node_timeout: false + endpoint_snitch: ${cfg.snitch} + dynamic_snitch_update_interval_in_ms: 100 + dynamic_snitch_reset_interval_in_ms: 600000 + dynamic_snitch_badness_threshold: 0.1 + request_scheduler: org.apache.cassandra.scheduler.NoScheduler + server_encryption_options: + internode_encryption: ${cfg.internodeEncryption} + keystore: ${cfg.keyStorePath} + keystore_password: ${cfg.keyStorePassword} + truststore: ${cfg.trustStorePath} + truststore_password: ${cfg.trustStorePassword} + client_encryption_options: + enabled: ${if cfg.clientEncryption then "true" else "false"} + keystore: ${cfg.keyStorePath} + keystore_password: ${cfg.keyStorePassword} + internode_compression: all + inter_dc_tcp_nodelay: false + preheat_kernel_page_cache: false + streaming_socket_timeout_in_ms: ${toString cfg.streamingSocketTimoutInMS} + ''; + + cassandraLog = '' + log4j.rootLogger=${cfg.logLevel},stdout + log4j.appender.stdout=org.apache.log4j.ConsoleAppender + log4j.appender.stdout.layout=org.apache.log4j.PatternLayout + log4j.appender.stdout.layout.ConversionPattern=%5p [%t] %d{HH:mm:ss,SSS} %m%n + ''; + + cassandraConfFile = pkgs.writeText "cassandra.yaml" cassandraConf; + cassandraLogFile = pkgs.writeText "log4j-server.properties" cassandraLog; + cassandraRackFile = pkgs.writeText "cassandra-rackdc.properties" cassandraRackDcProperties; + + cassandraEnvironment = { + CASSANDRA_HOME = cassandraPackage; + JAVA_HOME = cfg.jre; + CASSANDRA_CONF = "/etc/cassandra"; + }; + +in { + + ###### interface + + options.services.cassandra = { + enable = mkOption { + description = "Whether to enable cassandra."; + default = false; + type = types.bool; + }; + package = mkOption { + description = "Cassandra package to use."; + default = pkgs.cassandra; + defaultText = "pkgs.cassandra"; + type = types.package; + }; + jre = mkOption { + description = "JRE package to run cassandra service."; + default = pkgs.jre; + defaultText = "pkgs.jre"; + type = types.package; + }; + user = mkOption { + description = "User that runs cassandra service."; + default = "cassandra"; + type = types.string; + }; + group = mkOption { + description = "Group that runs cassandra service."; + default = "cassandra"; + type = types.string; + }; + envFile = mkOption { + description = "path to cassandra-env.sh"; + default = "${cassandraPackage}/conf/cassandra-env.sh"; + defaultText = "\${cassandraPackage}/conf/cassandra-env.sh"; + type = types.path; + }; + clusterName = mkOption { + description = "set cluster name"; + default = "cassandra"; + example = "prod-cluster0"; + type = types.string; + }; + commitLogDirectory = mkOption { + description = "directory for commit logs"; + default = "/var/lib/cassandra/commit_log"; + type = types.string; + }; + savedCachesDirectory = mkOption { + description = "directory for saved caches"; + default = "/var/lib/cassandra/saved_caches"; + type = types.string; + }; + hintedHandOff = mkOption { + description = "enable hinted handoff"; + default = true; + type = types.bool; + }; + hintedHandOffThrottle = mkOption { + description = "hinted hand off throttle rate in kb"; + default = 1024; + type = types.int; + }; + commitLogSync = mkOption { + description = "commitlog sync method"; + default = "periodic"; + type = types.str; + example = "batch"; + }; + commitLogSyncPeriod = mkOption { + description = "commitlog sync period in ms "; + default = 10000; + type = types.int; + }; + envScript = mkOption { + default = "${cassandraPackage}/conf/cassandra-env.sh"; + defaultText = "\${cassandraPackage}/conf/cassandra-env.sh"; + type = types.path; + description = "Supply your own cassandra-env.sh rather than using the default"; + }; + extraParams = mkOption { + description = "add additional lines to cassandra-env.sh"; + default = []; + example = [''JVM_OPTS="$JVM_OPTS -Dcassandra.available_processors=1"'']; + type = types.listOf types.str; + }; + dataDirs = mkOption { + type = types.listOf types.path; + default = [ "/var/lib/cassandra/data" ]; + description = "Data directories for cassandra"; + }; + logLevel = mkOption { + type = types.str; + default = "INFO"; + description = "default logging level for log4j"; + }; + internodeEncryption = mkOption { + description = "enable internode encryption"; + default = "none"; + example = "all"; + type = types.str; + }; + clientEncryption = mkOption { + description = "enable client encryption"; + default = false; + type = types.bool; + }; + trustStorePath = mkOption { + description = "path to truststore"; + default = ".conf/truststore"; + type = types.str; + }; + keyStorePath = mkOption { + description = "path to keystore"; + default = ".conf/keystore"; + type = types.str; + }; + keyStorePassword = mkOption { + description = "password to keystore"; + default = "cassandra"; + type = types.str; + }; + trustStorePassword = mkOption { + description = "password to truststore"; + default = "cassandra"; + type = types.str; + }; + seeds = mkOption { + description = "password to truststore"; + default = [ "127.0.0.1" ]; + type = types.listOf types.str; + }; + concurrentWrites = mkOption { + description = "number of concurrent writes allowed"; + default = 32; + type = types.int; + }; + concurrentReads = mkOption { + description = "number of concurrent reads allowed"; + default = 32; + type = types.int; + }; + listenAddress = mkOption { + description = "listen address"; + default = "localhost"; + type = types.str; + }; + rpcAddress = mkOption { + description = "rpc listener address"; + default = "localhost"; + type = types.str; + }; + incrementalBackups = mkOption { + description = "enable incremental backups"; + default = false; + type = types.bool; + }; + snitch = mkOption { + description = "snitch to use for topology discovery"; + default = "GossipingPropertyFileSnitch"; + example = "Ec2Snitch"; + type = types.str; + }; + dc = mkOption { + description = "datacenter for use in topology configuration"; + default = "DC1"; + example = "DC1"; + type = types.str; + }; + rack = mkOption { + description = "rack for use in topology configuration"; + default = "RAC1"; + example = "RAC1"; + type = types.str; + }; + authorizer = mkOption { + description = " + Authorization backend, implementing IAuthorizer; used to limit access/provide permissions + "; + default = "AllowAllAuthorizer"; + example = "CassandraAuthorizer"; + type = types.str; + }; + authenticator = mkOption { + description = " + Authentication backend, implementing IAuthenticator; used to identify users + "; + default = "AllowAllAuthenticator"; + example = "PasswordAuthenticator"; + type = types.str; + }; + autoBootstrap = mkOption { + description = "It makes new (non-seed) nodes automatically migrate the right data to themselves."; + default = true; + example = true; + type = types.bool; + }; + streamingSocketTimoutInMS = mkOption { + description = "Enable or disable socket timeout for streaming operations"; + default = 3600000; #CASSANDRA-8611 + example = 120; + type = types.int; + }; + repairStartAt = mkOption { + default = "Sun"; + type = types.string; + description = '' + Defines realtime (i.e. wallclock) timers with calendar event + expressions. For more details re: systemd OnCalendar at + https://www.freedesktop.org/software/systemd/man/systemd.time.html#Displaying%20Time%20Spans + ''; + example = ["weekly" "daily" "08:05:40" "mon,fri *-1/2-1,3 *:30:45"]; + }; + repairRandomizedDelayInSec = mkOption { + default = 0; + type = types.int; + description = ''Delay the timer by a randomly selected, evenly distributed + amount of time between 0 and the specified time value. re: systemd timer + RandomizedDelaySec for more details + ''; + }; + repairPostStop = mkOption { + default = null; + type = types.nullOr types.string; + description = '' + Run a script when repair is over. One can use it to send statsd events, email, etc. + ''; + }; + repairPostStart = mkOption { + default = null; + type = types.nullOr types.string; + description = '' + Run a script when repair starts. One can use it to send statsd events, email, etc. + It has same semantics as systemd ExecStopPost; So, if it fails, unit is consisdered + failed. + ''; + }; + }; + + ###### implementation + + config = mkIf cfg.enable { + + environment.etc."cassandra/cassandra-rackdc.properties" = { + source = cassandraRackFile; + }; + environment.etc."cassandra/cassandra.yaml" = { + source = cassandraConfFile; + }; + environment.etc."cassandra/log4j-server.properties" = { + source = cassandraLogFile; + }; + environment.etc."cassandra/cassandra-env.sh" = { + text = '' + ${builtins.readFile cfg.envFile} + ${concatStringsSep "\n" cfg.extraParams} + ''; + }; + systemd.services.cassandra = { + description = "Cassandra Daemon"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-interfaces.target" ]; + environment = cassandraEnvironment; + restartTriggers = [ cassandraConfFile cassandraLogFile cassandraRackFile ]; + serviceConfig = { + + User = cfg.user; + PermissionsStartOnly = true; + LimitAS = "infinity"; + LimitNOFILE = "100000"; + LimitNPROC = "32768"; + LimitMEMLOCK = "infinity"; + + }; + script = '' + ${cassandraPackage}/bin/cassandra -f + ''; + path = [ + cfg.jre + cassandraPackage + pkgs.coreutils + ]; + preStart = '' + mkdir -m 0700 -p /etc/cassandra/triggers + mkdir -m 0700 -p /var/lib/cassandra /var/log/cassandra + chown ${cfg.user} /var/lib/cassandra /var/log/cassandra /etc/cassandra/triggers + ''; + postStart = '' + sleep 2 + while ! nodetool status >/dev/null 2>&1; do + sleep 2 + done + nodetool status + ''; + }; + + environment.systemPackages = [ cassandraPackage ]; + + networking.firewall.allowedTCPPorts = [ + 7000 + 7001 + 9042 + 9160 + ]; + + users.extraUsers.cassandra = + if config.ids.uids ? "cassandra" + then { uid = config.ids.uids.cassandra; } // cassandraUser + else cassandraUser ; + + boot.kernel.sysctl."vm.swappiness" = pkgs.lib.mkOptionDefault 0; + + systemd.timers."cassandra-repair" = { + timerConfig = { + OnCalendar = "${toString cfg.repairStartAt}"; + RandomizedDelaySec = cfg.repairRandomizedDelayInSec; + }; + }; + + systemd.services."cassandra-repair" = { + description = "Cassandra repair daemon"; + environment = cassandraEnvironment; + script = "${cassandraPackage}/bin/nodetool repair -pr"; + postStop = mkIf (cfg.repairPostStop != null) cfg.repairPostStop; + postStart = mkIf (cfg.repairPostStart != null) cfg.repairPostStart; + serviceConfig = { + User = cfg.user; + }; + }; + }; +} diff --git a/nixos/modules/services/games/factorio.nix b/nixos/modules/services/games/factorio.nix index 90834c5b2605..0369752997a7 100644 --- a/nixos/modules/services/games/factorio.nix +++ b/nixos/modules/services/games/factorio.nix @@ -4,14 +4,17 @@ with lib; let cfg = config.services.factorio; + factorio = pkgs.factorio-headless; name = "Factorio"; stateDir = "/var/lib/factorio"; + mkSavePath = name: "${stateDir}/saves/${name}.zip"; configFile = pkgs.writeText "factorio.conf" '' use-system-read-write-data-directories=true [path] - read-data=${pkgs.factorio-headless}/share/factorio/data + read-data=${factorio}/share/factorio/data write-data=${stateDir} ''; + modDir = pkgs.factorio-mkModDirDrv cfg.mods; in { options = { @@ -32,7 +35,8 @@ in description = '' The name of the savegame that will be used by the server. - When not present in ${stateDir}/saves, it will be generated before starting the service. + When not present in ${stateDir}/saves, a new map with default + settings will be generated before starting the service. ''; }; # TODO Add more individual settings as nixos-options? @@ -51,6 +55,26 @@ in customizations. ''; }; + mods = mkOption { + type = types.listOf types.package; + default = []; + description = '' + Mods the server should install and activate. + + The derivations in this list must "build" the mod by simply copying + the .zip, named correctly, into the output directory. Eventually, + there will be a way to pull in the most up-to-date list of + derivations via nixos-channel. Until then, this is for experts only. + ''; + }; + autosave-interval = mkOption { + type = types.nullOr types.int; + default = null; + example = 2; + description = '' + The time, in minutes, between autosaves. + ''; + }; }; }; @@ -74,12 +98,14 @@ in wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; - preStart = '' - test -e ${stateDir}/saves/${cfg.saveName}.zip || \ - ${pkgs.factorio-headless}/bin/factorio \ - --config=${cfg.configFile} \ - --create=${stateDir}/saves/${cfg.saveName}.zip - ''; + preStart = toString [ + "test -e ${stateDir}/saves/${cfg.saveName}.zip" + "||" + "${factorio}/bin/factorio" + "--config=${cfg.configFile}" + "--create=${mkSavePath cfg.saveName}" + (optionalString (cfg.mods != []) "--mod-directory=${modDir}") + ]; serviceConfig = { User = "factorio"; @@ -90,10 +116,12 @@ in PrivateTmp = true; UMask = "0007"; ExecStart = toString [ - "${pkgs.factorio-headless}/bin/factorio" + "${factorio}/bin/factorio" "--config=${cfg.configFile}" "--port=${toString cfg.port}" - "--start-server=${stateDir}/saves/${cfg.saveName}.zip" + "--start-server=${mkSavePath cfg.saveName}" + (optionalString (cfg.mods != []) "--mod-directory=${modDir}") + (optionalString (cfg.autosave-interval != null) "--autosave-interval ${toString cfg.autosave-interval}") ]; }; }; diff --git a/nixos/modules/services/games/terraria.nix b/nixos/modules/services/games/terraria.nix new file mode 100644 index 000000000000..57ac37bb1bd3 --- /dev/null +++ b/nixos/modules/services/games/terraria.nix @@ -0,0 +1,139 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.terraria; + worldSizeMap = { "small" = 1; "medium" = 2; "large" = 3; }; + valFlag = name: val: optionalString (val != null) "-${name} \"${escape ["\\" "\""] (toString val)}\""; + boolFlag = name: val: optionalString val "-${name}"; + flags = [ + (valFlag "port" cfg.port) + (valFlag "maxPlayers" cfg.maxPlayers) + (valFlag "password" cfg.password) + (valFlag "motd" cfg.messageOfTheDay) + (valFlag "world" cfg.worldPath) + (valFlag "autocreate" (builtins.getAttr cfg.autoCreatedWorldSize worldSizeMap)) + (valFlag "banlist" cfg.banListPath) + (boolFlag "secure" cfg.secure) + (boolFlag "noupnp" cfg.noUPnP) + ]; +in +{ + options = { + services.terraria = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + If enabled, starts a Terraria server. The server can be connected to via <literal>tmux -S /var/lib/terraria/terraria.sock attach</literal> + for administration by users who are a part of the <literal>terraria</literal> group (use <literal>C-b d</literal> shortcut to detach again). + ''; + }; + + port = mkOption { + type = types.int; + default = 7777; + description = '' + Specifies the port to listen on. + ''; + }; + + maxPlayers = mkOption { + type = types.int; + default = 255; + description = '' + Sets the max number of players (between 1 and 255). + ''; + }; + + password = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Sets the server password. Leave <literal>null</literal> for no password. + ''; + }; + + messageOfTheDay = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Set the server message of the day text. + ''; + }; + + worldPath = mkOption { + type = types.path; + default = null; + description = '' + The path to the world file (<literal>.wld</literal>) which should be loaded. + If no world exists at this path, one will be created with the size + specified by <literal>autoCreatedWorldSize</literal>. + ''; + }; + + autoCreatedWorldSize = mkOption { + type = types.enum [ "small" "medium" "large" ]; + default = "medium"; + description = '' + Specifies the size of the auto-created world if <literal>worldPath</literal> does not + point to an existing world. + ''; + }; + + banListPath = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + The path to the ban list. + ''; + }; + + secure = mkOption { + type = types.bool; + default = false; + description = "Adds additional cheat protection to the server."; + }; + + noUPnP = mkOption { + type = types.bool; + default = false; + description = "Disables automatic Universal Plug and Play."; + }; + }; + }; + + config = mkIf cfg.enable { + users.extraUsers.terraria = { + description = "Terraria server service user"; + home = "/var/lib/terraria"; + createHome = true; + uid = config.ids.uids.terraria; + }; + + users.extraGroups.terraria = { + gid = config.ids.gids.terraria; + members = [ "terraria" ]; + }; + + systemd.services.terraria = { + description = "Terraria Server Service"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + User = "terraria"; + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${pkgs.tmux.bin}/bin/tmux -S /var/lib/terraria/terraria.sock new -d ${pkgs.terraria-server}/bin/TerrariaServer ${concatStringsSep " " flags}"; + ExecStop = "${pkgs.tmux.bin}/bin/tmux -S /var/lib/terraria/terraria.sock send-keys Enter \"exit\" Enter"; + }; + + postStart = '' + ${pkgs.coreutils}/bin/chmod 660 /var/lib/terraria/terraria.sock + ${pkgs.coreutils}/bin/chgrp terraria /var/lib/terraria/terraria.sock + ''; + }; + }; +} diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix index 267442bd1f8b..ac2e94c25c33 100644 --- a/nixos/modules/services/misc/gitlab.nix +++ b/nixos/modules/services/misc/gitlab.nix @@ -57,42 +57,23 @@ let issues = true; merge_requests = true; wiki = true; - snippets = false; + snippets = true; builds = true; + container_registry = true; }; }; - artifacts = { - enabled = true; - }; - lfs = { - enabled = true; - }; - gravatar = { - enabled = true; - }; - cron_jobs = { - stuck_ci_builds_worker = { - cron = "0 0 * * *"; - }; - }; - gitlab_ci = { - builds_path = "${cfg.statePath}/builds"; - }; - ldap = { - enabled = false; - }; - omniauth = { - enabled = false; - }; - shared = { - path = "${cfg.statePath}/shared"; - }; - backup = { - path = "${cfg.backupPath}"; - }; + repositories.storages.default = "${cfg.statePath}/repositories"; + artifacts.enabled = true; + lfs.enabled = true; + gravatar.enabled = true; + cron_jobs = { }; + gitlab_ci.builds_path = "${cfg.statePath}/builds"; + ldap.enabled = false; + omniauth.enabled = false; + shared.path = "${cfg.statePath}/shared"; + backup.path = "${cfg.backupPath}"; gitlab_shell = { path = "${cfg.packages.gitlab-shell}"; - repos_path = "${cfg.statePath}/repositories"; hooks_path = "${cfg.statePath}/shell/hooks"; secret_file = "${cfg.statePath}/config/gitlab_shell_secret"; upload_pack = true; @@ -125,21 +106,42 @@ let unicornConfig = builtins.readFile ./defaultUnicornConfig.rb; - gitlab-runner = pkgs.stdenv.mkDerivation rec { - name = "gitlab-runner"; - buildInputs = [ cfg.packages.gitlab bundler pkgs.makeWrapper ]; + gitlab-rake = pkgs.stdenv.mkDerivation rec { + name = "gitlab-rake"; + buildInputs = [ cfg.packages.gitlab cfg.packages.gitlab.env pkgs.makeWrapper ]; phases = "installPhase fixupPhase"; buildPhase = ""; installPhase = '' mkdir -p $out/bin - makeWrapper ${bundler}/bin/bundle $out/bin/gitlab-runner \ - ${concatStrings (mapAttrsToList (name: value: "--set ${name} '\"${value}\"' ") gitlabEnv)} \ - --set GITLAB_CONFIG_PATH '"${cfg.statePath}/config"' \ - --set PATH '"${pkgs.nodejs}/bin:${pkgs.gzip}/bin:${config.services.postgresql.package}/bin:$PATH"' \ - --set RAKEOPT '"-f ${cfg.packages.gitlab}/share/gitlab/Rakefile"' - ''; + makeWrapper ${cfg.packages.gitlab.env}/bin/bundle $out/bin/gitlab-bundle \ + ${concatStrings (mapAttrsToList (name: value: "--set ${name} '${value}' ") gitlabEnv)} \ + --set GITLAB_CONFIG_PATH '${cfg.statePath}/config' \ + --set PATH '${pkgs.nodejs}/bin:${pkgs.gzip}/bin:${config.services.postgresql.package}/bin:$PATH' \ + --set RAKEOPT '-f ${cfg.packages.gitlab}/share/gitlab/Rakefile' \ + --run 'cd ${cfg.packages.gitlab}/share/gitlab' + makeWrapper $out/bin/gitlab-bundle $out/bin/gitlab-rake \ + --add-flags "exec rake" + ''; }; + smtpSettings = pkgs.writeText "gitlab-smtp-settings.rb" '' + if Rails.env.production? + Rails.application.config.action_mailer.delivery_method = :smtp + + ActionMailer::Base.delivery_method = :smtp + ActionMailer::Base.smtp_settings = { + address: "${cfg.smtp.address}", + port: ${toString cfg.smtp.port}, + ${optionalString (cfg.smtp.username != null) ''user_name: "${cfg.smtp.username}",''} + ${optionalString (cfg.smtp.password != null) ''password: "${cfg.smtp.password}",''} + domain: "${cfg.smtp.domain}", + ${optionalString (cfg.smtp.authentication != null) "authentication: :${cfg.smtp.authentication},"} + enable_starttls_auto: ${toString cfg.smtp.enableStartTLSAuto}, + openssl_verify_mode: '${cfg.smtp.opensslVerifyMode}' + } + end + ''; + in { options = { @@ -255,6 +257,62 @@ in { ''; }; + smtp = { + enable = mkOption { + type = types.bool; + default = false; + description = "Enable gitlab mail delivery over SMTP."; + }; + + address = mkOption { + type = types.str; + default = "localhost"; + description = "Address of the SMTP server for Gitlab."; + }; + + port = mkOption { + type = types.int; + default = 465; + description = "Port of the SMTP server for Gitlab."; + }; + + username = mkOption { + type = types.nullOr types.str; + default = null; + description = "Username of the SMTP server for Gitlab."; + }; + + password = mkOption { + type = types.nullOr types.str; + default = null; + description = "Password of the SMTP server for Gitlab."; + }; + + domain = mkOption { + type = types.str; + default = "localhost"; + description = "HELO domain to use for outgoing mail."; + }; + + authentication = mkOption { + type = types.nullOr types.str; + default = null; + description = "Authentitcation type to use, see http://api.rubyonrails.org/classes/ActionMailer/Base.html"; + }; + + enableStartTLSAuto = mkOption { + type = types.bool; + default = true; + description = "Whether to try to use StartTLS."; + }; + + opensslVerifyMode = mkOption { + type = types.str; + default = "peer"; + description = "How OpenSSL checks the certificate, see http://api.rubyonrails.org/classes/ActionMailer/Base.html"; + }; + }; + extraConfig = mkOption { type = types.attrs; default = {}; @@ -275,7 +333,7 @@ in { config = mkIf cfg.enable { - environment.systemPackages = [ pkgs.git gitlab-runner cfg.packages.gitlab-shell ]; + environment.systemPackages = [ pkgs.git gitlab-rake cfg.packages.gitlab-shell ]; assertions = [ { assertion = cfg.databasePassword != ""; @@ -308,6 +366,7 @@ in { systemd.services.gitlab-sidekiq = { after = [ "network.target" "redis.service" ]; wantedBy = [ "multi-user.target" ]; + partOf = [ "gitlab.service" ]; environment = gitlabEnv; path = with pkgs; [ config.services.postgresql.package @@ -322,7 +381,7 @@ in { Group = cfg.group; TimeoutSec = "300"; WorkingDirectory = "${cfg.packages.gitlab}/share/gitlab"; - ExecStart="${bundler}/bin/bundle exec \"sidekiq -q post_receive -q mailers -q system_hook -q project_web_hook -q gitlab_shell -q common -q default -e production -P ${cfg.statePath}/tmp/sidekiq.pid\""; + ExecStart="${cfg.packages.gitlab.env}/bin/bundle exec \"sidekiq -q post_receive -q mailers -q system_hook -q project_web_hook -q gitlab_shell -q common -q default -e production -P ${cfg.statePath}/tmp/sidekiq.pid\""; }; }; @@ -397,6 +456,9 @@ in { chmod -R u+rwX,go-rwx+X ${gitlabEnv.HOME}/ cp -rf ${cfg.packages.gitlab}/share/gitlab/config.dist/* ${cfg.statePath}/config + ${optionalString cfg.smtp.enable '' + ln -sf ${smtpSettings} ${cfg.statePath}/config/initializers/smtp_settings.rb + ''} ln -sf ${cfg.statePath}/config /run/gitlab/config cp ${cfg.packages.gitlab}/share/gitlab/VERSION ${cfg.statePath}/VERSION @@ -420,14 +482,14 @@ in { touch "${cfg.statePath}/db-created" # The gitlab:setup task is horribly broken somehow, these two tasks will do the same for setting up the initial database - ${gitlab-runner}/bin/gitlab-runner exec rake db:migrate RAILS_ENV=production - ${gitlab-runner}/bin/gitlab-runner exec rake db:seed_fu RAILS_ENV=production \ + ${gitlab-rake}/bin/gitlab-rake db:migrate RAILS_ENV=production + ${gitlab-rake}/bin/gitlab-rake db:seed_fu RAILS_ENV=production \ GITLAB_ROOT_PASSWORD="${cfg.initialRootPassword}" GITLAB_ROOT_EMAIL="${cfg.initialRootEmail}"; fi fi # Always do the db migrations just to be sure the database is up-to-date - ${gitlab-runner}/bin/gitlab-runner exec rake db:migrate RAILS_ENV=production + ${gitlab-rake}/bin/gitlab-rake db:migrate RAILS_ENV=production # Change permissions in the last step because some of the # intermediary scripts like to create directories as root. @@ -441,8 +503,9 @@ in { User = cfg.user; Group = cfg.group; TimeoutSec = "300"; + Restart = "on-failure"; WorkingDirectory = "${cfg.packages.gitlab}/share/gitlab"; - ExecStart="${bundler}/bin/bundle exec \"unicorn -c ${cfg.statePath}/config/unicorn.rb -E production\""; + ExecStart = "${cfg.packages.gitlab.env}/bin/bundle exec \"unicorn -c ${cfg.statePath}/config/unicorn.rb -E production\""; }; }; diff --git a/nixos/modules/services/misc/gitlab.xml b/nixos/modules/services/misc/gitlab.xml index b630fe421130..a8147b3a74f9 100644 --- a/nixos/modules/services/misc/gitlab.xml +++ b/nixos/modules/services/misc/gitlab.xml @@ -14,29 +14,22 @@ <literal>/run/gitlab/gitlab-workhorse.socket</literal>. You need to configure a webserver to proxy HTTP requests to the socket.</para> -<para>For instance, this could be used for Nginx: +<para>For instance, the following configuration could be used to use nginx as + frontend proxy: <programlisting> -services.nginx.httpConfig = '' - server { - server_name git.example.com; - listen 443 ssl spdy; - listen [::]:443 ssl spdy; - - ssl_certificate /var/lib/acme/git.example.com/fullchain.pem; - ssl_certificate_key /var/lib/acme/git.example.com/key.pem; - - location / { - proxy_http_version 1.1; - proxy_set_header Host $http_host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Ssl on; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - - proxy_pass http://unix:/run/gitlab/gitlab-workhorse.socket; - } - } + services.nginx = { + enable = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + virtualHosts."git.example.com" = { + enableACME = true; + forceSSL = true; + locations."/".proxyPass = "http://unix:/run/gitlab/gitlab-workhorse.socket"; + }; + }; ''; </programlisting> </para> @@ -49,10 +42,10 @@ services.nginx.httpConfig = '' both services. In the case of PostgreSQL, a database and a role will be created. </para> -<para>The default state dir is /var/gitlab/state. This is where all data like -the repositories and uploads will be stored.</para> +<para>The default state dir is <literal>/var/gitlab/state</literal>. This is where +all data like the repositories and uploads will be stored.</para> -<para>A basic configuration could look like this: +<para>A basic configuration with some custom settings could look like this: <programlisting> services.gitlab = { @@ -64,8 +57,16 @@ services.gitlab = { port = 443; user = "git"; group = "git"; + smtp = { + enable = true; + address = "localhost"; + port = 25; + }; extraConfig = { gitlab = { + email_from = "gitlab-no-reply@example.com"; + email_display_name = "Example GitLab"; + email_reply_to = "gitlab-no-reply@example.com"; default_projects_features = { builds = false; }; }; }; @@ -80,21 +81,21 @@ options for the <literal>services.gitlab</literal> module.</para> <section><title>Maintenance</title> -<para>You can run all Gitlab related commands like rake tasks with -<literal>gitlab-runner</literal> which will be available on the system -when gitlab is enabled. You will have to run the commands as the user that -you configured to run gitlab.</para> +<para>You can run Gitlab's rake tasks with <literal>gitlab-rake</literal> +which will be available on the system when gitlab is enabled. You will +have to run the command as the user that you configured to run gitlab +with.</para> -<para>For instance, to backup a Gitlab instance: +<para>For example, to backup a Gitlab instance: <programlisting> -$ sudo -u git -H gitlab-runner exec rake gitlab:backup:create +$ sudo -u git -H gitlab-rake gitlab:backup:create </programlisting> A list of all availabe rake tasks can be obtained by running: <programlisting> -$ sudo -u git -H gitlab-runner exec rake -T +$ sudo -u git -H gitlab-rake -T </programlisting> </para> diff --git a/nixos/modules/services/networking/offlineimap.nix b/nixos/modules/services/networking/offlineimap.nix index 31ce9280f319..daf6196d3706 100644 --- a/nixos/modules/services/networking/offlineimap.nix +++ b/nixos/modules/services/networking/offlineimap.nix @@ -54,7 +54,7 @@ in { description = "Offlineimap: a software to dispose your mailbox(es) as a local Maildir(s)"; serviceConfig = { Type = "oneshot"; - ExecStart = "${cfg.package}/bin/offlineimap -u basic -o -1"; + ExecStart = "${cfg.package}/bin/offlineimap -u syslog -o -1"; TimeoutStartSec = cfg.timeoutStartSec; }; path = cfg.path; diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix index a464733a6a03..f900ef494abf 100644 --- a/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixos/modules/services/networking/ssh/sshd.nix @@ -263,6 +263,7 @@ in serviceConfig = { ExecStart = + (optionalString cfg.startWhenNeeded "-") + "${cfgc.package}/bin/sshd " + (optionalString cfg.startWhenNeeded "-i ") + "-f ${pkgs.writeText "sshd_config" cfg.extraConfig}"; KillMode = "process"; diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix index b44b03dc0bf3..8a430734319b 100644 --- a/nixos/modules/services/networking/syncthing.nix +++ b/nixos/modules/services/networking/syncthing.nix @@ -23,6 +23,18 @@ let RestartForceExitStatus="3 4"; }; + iNotifyHeader = { + description = "Syncthing Inotify File Watcher service"; + after = [ "network.target" "syncthing.service" ]; + requires = [ "syncthing.service" ]; + }; + + iNotifyService = { + SuccessExitStatus = "2"; + RestartForceExitStatus = "3"; + Restart = "on-failure"; + }; + in { @@ -39,6 +51,12 @@ in available on http://127.0.0.1:8384/. ''; + useInotify = mkOption { + type = types.bool; + default = false; + description = "Provide syncthing-inotify as a service."; + }; + systemService = mkOption { type = types.bool; default = true; @@ -112,27 +130,40 @@ in config.ids.gids.syncthing; }; - environment.systemPackages = [ cfg.package ]; - - systemd.services = mkIf cfg.systemService { - syncthing = header // { + systemd.services = { + syncthing = mkIf cfg.systemService (header // { + wants = mkIf cfg.useInotify [ "syncthing-inotify.service" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = service // { + User = cfg.user; + Group = cfg.group; + PermissionsStartOnly = true; + ExecStart = "${cfg.package}/bin/syncthing -no-browser -home=${cfg.dataDir}"; + }; + }); + + syncthing-inotify = mkIf (cfg.systemService && cfg.useInotify) (iNotifyHeader // { wantedBy = [ "multi-user.target" ]; - serviceConfig = service // { + serviceConfig = iNotifyService // { User = cfg.user; - Group = cfg.group; - PermissionsStartOnly = true; - ExecStart = "${cfg.package}/bin/syncthing -no-browser -home=${cfg.dataDir}"; + ExecStart = "${pkgs.syncthing-inotify.bin}/bin/syncthing-inotify -home=${cfg.dataDir} -logflags=0"; }; - }; + }); }; - systemd.user.services.syncthing = - header // { - wantedBy = [ "default.target" ]; + systemd.user.services = { + syncthing = header // { serviceConfig = service // { ExecStart = "${cfg.package}/bin/syncthing -no-browser"; }; }; + syncthing-inotify = mkIf cfg.useInotify (iNotifyHeader // { + serviceConfig = iNotifyService // { + ExecStart = "${pkgs.syncthing-inotify.bin}/bin/syncthing-inotify -logflags=0"; + }; + }); + }; + }; } diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 8385d8e60266..af7753470de6 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -18,7 +18,9 @@ let ${cfg.config} - ${optionalString (cfg.httpConfig == "") '' + ${optionalString (cfg.httpConfig == "" && cfg.config == "") '' + events {} + http { include ${cfg.package}/conf/mime.types; include ${cfg.package}/conf/fastcgi.conf; @@ -96,6 +98,7 @@ let }''} ${optionalString (cfg.httpConfig != "") '' + events {} http { include ${cfg.package}/conf/mime.types; include ${cfg.package}/conf/fastcgi.conf; @@ -233,9 +236,12 @@ in }; config = mkOption { - default = "events {}"; + default = ""; description = " Verbatim nginx.conf configuration. + This is mutually exclusive with the structured configuration + via virtualHosts and the recommendedXyzSettings configuration + options. See appendConfig for appending to the generated http block. "; }; @@ -268,8 +274,8 @@ in default = ""; description = " Configuration lines to be appended to the generated http block. - This is mutually exclusive with using httpConfig for specifying the whole - http block verbatim. + This is mutually exclusive with using config and httpConfig for + specifying the whole http block verbatim. "; }; diff --git a/nixos/modules/services/web-servers/phpfpm.nix b/nixos/modules/services/web-servers/phpfpm/default.nix index 2658d7117e37..819d0c251bf3 100644 --- a/nixos/modules/services/web-servers/phpfpm.nix +++ b/nixos/modules/services/web-servers/phpfpm/default.nix @@ -9,6 +9,12 @@ let pidFile = "${stateDir}/phpfpm.pid"; + mkPool = n: p: '' + [${n}] + listen = ${p.listen} + ${p.extraConfig} + ''; + cfgFile = pkgs.writeText "phpfpm.conf" '' [global] pid = ${pidFile} @@ -16,6 +22,8 @@ let daemonize = yes ${cfg.extraConfig} + ${concatStringsSep "\n" (mapAttrsToList mkPool cfg.pools)} + ${concatStringsSep "\n" (mapAttrsToList (n: v: "[${n}]\n${v}") cfg.poolConfigs)} ''; @@ -62,8 +70,8 @@ in { }; poolConfigs = mkOption { - type = types.attrsOf types.lines; default = {}; + type = types.attrsOf types.lines; example = literalExample '' { mypool = ''' listen = /run/phpfpm/mypool @@ -84,10 +92,20 @@ in { the phpfpm service is disabled. ''; }; + + pools = mkOption { + type = types.attrsOf (types.submodule (import ./pool-options.nix { + inherit lib; + })); + default = {}; + description = '' + If no pools are defined, the phpfpm service is disabled. + ''; + }; }; }; - config = mkIf (cfg.poolConfigs != {}) { + config = mkIf (cfg.pools != {}) { systemd.services.phpfpm = { wantedBy = [ "multi-user.target" ]; diff --git a/nixos/modules/services/web-servers/phpfpm/pool-options.nix b/nixos/modules/services/web-servers/phpfpm/pool-options.nix new file mode 100644 index 000000000000..cc688c2c48a2 --- /dev/null +++ b/nixos/modules/services/web-servers/phpfpm/pool-options.nix @@ -0,0 +1,35 @@ +{ lib }: + +with lib; { + + options = { + + listen = mkOption { + type = types.str; + example = "/path/to/unix/socket"; + description = '' + The address on which to accept FastCGI requests. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + example = '' + user = nobody + pm = dynamic + pm.max_children = 75 + pm.start_servers = 10 + pm.min_spare_servers = 5 + pm.max_spare_servers = 20 + pm.max_requests = 500 + ''; + + description = '' + Extra lines that go into the pool configuration. + See the documentation on <literal>php-fpm.conf</literal> for + details on configuration directives. + ''; + }; + }; +} + diff --git a/nixos/modules/services/web-servers/varnish/default.nix b/nixos/modules/services/web-servers/varnish/default.nix index 364f6c68faca..61df43ec2352 100644 --- a/nixos/modules/services/web-servers/varnish/default.nix +++ b/nixos/modules/services/web-servers/varnish/default.nix @@ -28,7 +28,7 @@ with lib; }; stateDir = mkOption { - default = "/var/spool/varnish"; + default = "/var/spool/varnish/${config.networking.hostName}"; description = " Directory holding all state for Varnish to run. "; @@ -46,6 +46,9 @@ with lib; mkdir -p ${cfg.stateDir} chown -R varnish:varnish ${cfg.stateDir} ''; + postStop = '' + rm -rf ${cfg.stateDir} + ''; path = [ pkgs.gcc ]; serviceConfig.ExecStart = "${pkgs.varnish}/sbin/varnishd -a ${cfg.http_address} -f ${pkgs.writeText "default.vcl" cfg.config} -n ${cfg.stateDir} -u varnish"; serviceConfig.Type = "forking"; diff --git a/nixos/modules/services/x11/hardware/libinput.nix b/nixos/modules/services/x11/hardware/libinput.nix index 14c7131e611c..b358550ba41d 100644 --- a/nixos/modules/services/x11/hardware/libinput.nix +++ b/nixos/modules/services/x11/hardware/libinput.nix @@ -25,16 +25,21 @@ in { accelProfile = mkOption { type = types.enum [ "flat" "adaptive" ]; - default = "flat"; - example = "adaptive"; + default = "adaptive"; + example = "flat"; description = '' - Sets the pointer acceleration profile to the given profile. Permitted values are adaptive, flat. - Not all devices support this option or all profiles. If a profile is unsupported, the default profile - for this is used. For a description on the profiles and their behavior, see the libinput documentation. + Sets the pointer acceleration profile to the given profile. + Permitted values are adaptive, flat. + Not all devices support this option or all profiles. + If a profile is unsupported, the default profile for this is used. + <literal>flat</literal>: Pointer motion is accelerated by a constant + (device-specific) factor, depending on the current speed. + <literal>adaptive</literal>: Pointer acceleration depends on the input speed. + This is the default profile for most devices. ''; - }; - + }; + accelSpeed = mkOption { type = types.nullOr types.string; default = null; @@ -216,7 +221,7 @@ in { Option "LeftHanded" "${xorgBool cfg.leftHanded}" Option "MiddleEmulation" "${xorgBool cfg.middleEmulation}" Option "NaturalScrolling" "${xorgBool cfg.naturalScrolling}" - ${optionalString (cfg.scrollButton != null) ''Option "ScrollButton" "${cfg.scrollButton}"''} + ${optionalString (cfg.scrollButton != null) ''Option "ScrollButton" "${toString cfg.scrollButton}"''} Option "ScrollMethod" "${cfg.scrollMethod}" Option "HorizontalScrolling" "${xorgBool cfg.horizontalScrolling}" Option "SendEventsMode" "${cfg.sendEventsMode}" @@ -227,6 +232,14 @@ in { EndSection ''; + assertions = [ + # already present in synaptics.nix + /* { + assertion = !config.services.xserver.synaptics.enable; + message = "Synaptics and libinput are incompatible, you cannot enable both (in services.xserver)."; + } */ + ]; + }; } diff --git a/nixos/modules/services/x11/hardware/synaptics.nix b/nixos/modules/services/x11/hardware/synaptics.nix index e74b19c8e710..5c068e89dd71 100644 --- a/nixos/modules/services/x11/hardware/synaptics.nix +++ b/nixos/modules/services/x11/hardware/synaptics.nix @@ -205,6 +205,13 @@ in { EndSection ''; + assertions = [ + { + assertion = !config.services.xserver.libinput.enable; + message = "Synaptics and libinput are incompatible, you cannot enable both (in services.xserver)."; + } + ]; + }; } diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index e7df2e6b4690..b03f70385b1f 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -14,6 +14,9 @@ let # Map video driver names to driver packages. FIXME: move into card-specific modules. knownVideoDrivers = { virtualbox = { modules = [ kernelPackages.virtualboxGuestAdditions ]; driverName = "vboxvideo"; }; + + # modesetting does not have a xf86videomodesetting package as it is included in xorgserver + modesetting = {}; }; fontsForXServer = @@ -443,7 +446,7 @@ in then { modules = [xorg.${"xf86video" + name}]; } else null) knownVideoDrivers; - in optional (driver != null) ({ inherit name; driverName = name; } // driver)); + in optional (driver != null) ({ inherit name; modules = []; driverName = name; } // driver)); assertions = [ { assertion = config.security.polkit.enable; diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix index 8dad09c89207..f2755b49f88d 100644 --- a/nixos/modules/system/boot/luksroot.nix +++ b/nixos/modules/system/boot/luksroot.nix @@ -443,7 +443,7 @@ in copy_bin_and_libs pbkdf2-sha512 mkdir -p $out/etc/ssl - cp -pdv ${pkgs.openssl}/etc/ssl/openssl.cnf $out/etc/ssl + cp -pdv ${pkgs.openssl.out}/etc/ssl/openssl.cnf $out/etc/ssl cat > $out/bin/openssl-wrap <<EOF #!$out/bin/sh diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh index 82995d5bab11..fbb32901f64e 100644 --- a/nixos/modules/system/boot/stage-1-init.sh +++ b/nixos/modules/system/boot/stage-1-init.sh @@ -185,39 +185,6 @@ if test -n "$debug1devices"; then fail; fi @postDeviceCommands@ -# Try to resume - all modules are loaded now, and devices exist -if test -e /sys/power/tuxonice/resume; then - if test -n "$(cat /sys/power/tuxonice/resume)"; then - echo 0 > /sys/power/tuxonice/user_interface/enabled - echo 1 > /sys/power/tuxonice/do_resume || echo "failed to resume..." - fi -fi - -if test -e /sys/power/resume -a -e /sys/power/disk; then - if test -n "@resumeDevice@"; then - resumeDev="@resumeDevice@" - resumeInfo="$(udevadm info -q property "$resumeDev" )" - else - for sd in @resumeDevices@; do - # Try to detect resume device. According to Ubuntu bug: - # https://bugs.launchpad.net/ubuntu/+source/pm-utils/+bug/923326/comments/1 - # when there are multiple swap devices, we can't know where the hibernate - # image will reside. We can check all of them for swsuspend blkid. - resumeInfo="$(test -e "$sd" && udevadm info -q property "$sd")" - if [ "$(echo "$resumeInfo" | sed -n 's/^ID_FS_TYPE=//p')" = "swsuspend" ]; then - resumeDev="$sd" - break - fi - done - fi - if test -e "$resumeDev"; then - resumeMajor="$(echo "$resumeInfo" | sed -n 's/^MAJOR=//p')" - resumeMinor="$(echo "$resumeInfo" | sed -n 's/^MINOR=//p')" - echo "$resumeMajor:$resumeMinor" > /sys/power/resume 2> /dev/null || echo "failed to resume..." - fi -fi - - # Return true if the machine is on AC power, or if we can't determine # whether it's on AC power. onACPower() { @@ -348,6 +315,68 @@ mountFS() { } +# Function for waiting a device to appear. +waitDevice() { + local device="$1" + + # USB storage devices tend to appear with some delay. It would be + # great if we had a way to synchronously wait for them, but + # alas... So just wait for a few seconds for the device to + # appear. + if test ! -e $device; then + echo -n "waiting for device $device to appear..." + try=20 + while [ $try -gt 0 ]; do + sleep 1 + # also re-try lvm activation now that new block devices might have appeared + lvm vgchange -ay + # and tell udev to create nodes for the new LVs + udevadm trigger --action=add + if test -e $device; then break; fi + echo -n "." + try=$((try - 1)) + done + echo + [ $try -ne 0 ] + fi +} + + +# Try to resume - all modules are loaded now. +if test -e /sys/power/tuxonice/resume; then + if test -n "$(cat /sys/power/tuxonice/resume)"; then + echo 0 > /sys/power/tuxonice/user_interface/enabled + echo 1 > /sys/power/tuxonice/do_resume || echo "failed to resume..." + fi +fi + +if test -e /sys/power/resume -a -e /sys/power/disk; then + if test -n "@resumeDevice@" && waitDevice "@resumeDevice@"; then + resumeDev="@resumeDevice@" + resumeInfo="$(udevadm info -q property "$resumeDev" )" + else + for sd in @resumeDevices@; do + # Try to detect resume device. According to Ubuntu bug: + # https://bugs.launchpad.net/ubuntu/+source/pm-utils/+bug/923326/comments/1 + # when there are multiple swap devices, we can't know where the hibernate + # image will reside. We can check all of them for swsuspend blkid. + if waitDevice "$sd"; then + resumeInfo="$(udevadm info -q property "$sd")" + if [ "$(echo "$resumeInfo" | sed -n 's/^ID_FS_TYPE=//p')" = "swsuspend" ]; then + resumeDev="$sd" + break + fi + fi + done + fi + if test -n "$resumeDev"; then + resumeMajor="$(echo "$resumeInfo" | sed -n 's/^MAJOR=//p')" + resumeMinor="$(echo "$resumeInfo" | sed -n 's/^MINOR=//p')" + echo "$resumeMajor:$resumeMinor" > /sys/power/resume 2> /dev/null || echo "failed to resume..." + fi +fi + + # Try to find and mount the root device. mkdir -p $targetRoot @@ -380,29 +409,11 @@ while read -u 3 mountPoint; do ;; esac - # USB storage devices tend to appear with some delay. It would be - # great if we had a way to synchronously wait for them, but - # alas... So just wait for a few seconds for the device to - # appear. If it doesn't appear, try to mount it anyway (and - # probably fail). This is a fallback for non-device "devices" - # that we don't properly recognise. - if test -z "$pseudoDevice" -a ! -e $device; then - echo -n "waiting for device $device to appear..." - try=20 - while [ $try -gt 0 ]; do - sleep 1 - # also re-try lvm activation now that new block devices might have appeared - lvm vgchange -ay - # and tell udev to create nodes for the new LVs - udevadm trigger --action=add - if test -e $device; then break; fi - echo -n "." - try=$((try - 1)) - done - echo - if [ $try -eq 0 ]; then - echo "Timed out waiting for device $device, trying to mount anyway." - fi + if test -z "$pseudoDevice" && ! waitDevice "$device"; then + # If it doesn't appear, try to mount it anyway (and + # probably fail). This is a fallback for non-device "devices" + # that we don't properly recognise. + echo "Timed out waiting for device $device, trying to mount anyway." fi # Wait once more for the udev queue to empty, just in case it's diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix index 21a49d45789e..70429e9c0a22 100644 --- a/nixos/modules/system/boot/stage-1.nix +++ b/nixos/modules/system/boot/stage-1.nix @@ -87,15 +87,11 @@ let LDD="$(ldd $BIN)" || continue LIBS="$(echo "$LDD" | awk '{print $3}' | sed '/^$/d')" for LIB in $LIBS; do - [ ! -f "$out/lib/$(basename $LIB)" ] && cp -pdv $LIB $out/lib - while [ "$(readlink $LIB)" != "" ]; do - LINK="$(readlink $LIB)" - if [ "${LINK:0:1}" != "/" ]; then - LINK="$(dirname $LIB)/$LINK" - fi - LIB="$LINK" - [ ! -f "$out/lib/$(basename $LIB)" ] && cp -pdv $LIB $out/lib - done + TGT="$out/lib/$(basename $LIB)" + if [ ! -f "$TGT" ]; then + SRC="$(readlink -e $LIB)" + cp -pdv "$SRC" "$TGT" + fi done done diff --git a/nixos/release.nix b/nixos/release.nix index 4647a02afb1c..b67cd198d2eb 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -211,6 +211,7 @@ in rec { tests.boot = callSubTests tests/boot.nix {}; tests.boot-stage1 = callTest tests/boot-stage1.nix {}; tests.cadvisor = hydraJob (import tests/cadvisor.nix { system = "x86_64-linux"; }); + tests.cassandra = callTest tests/cassandra.nix {}; tests.chromium = (callSubTests tests/chromium.nix { system = "x86_64-linux"; }).stable; tests.cjdns = callTest tests/cjdns.nix {}; tests.containers-ipv4 = callTest tests/containers-ipv4.nix {}; diff --git a/nixos/tests/cassandra.nix b/nixos/tests/cassandra.nix new file mode 100644 index 000000000000..b729e6b158bc --- /dev/null +++ b/nixos/tests/cassandra.nix @@ -0,0 +1,68 @@ +import ./make-test.nix ({ pkgs, ...}: +let + user = "cassandra"; + nodeCfg = nodes: selfIP: cassandraOpts: + { + services.cassandra = { + enable = true; + listenAddress = selfIP; + rpcAddress = "0.0.0.0"; + seeds = [ "192.168.1.1" ]; + package = pkgs.cassandra_2_0; + jre = pkgs.openjdk; + clusterName = "ci ahoy"; + authenticator = "PasswordAuthenticator"; + authorizer = "CassandraAuthorizer"; + user = user; + } // cassandraOpts; + nixpkgs.config.allowUnfree = true; + virtualisation.memorySize = 1024; + }; + +in +{ + name = "cassandra-ci"; + + nodes = { + cass0 = {pkgs, config, nodes, ...}: nodeCfg nodes "192.168.1.1" {}; + cass1 = {pkgs, config, nodes, ...}: nodeCfg nodes "192.168.1.2" {}; + cass2 = {pkgs, config, nodes, ...}: nodeCfg nodes "192.168.1.3" { + extraParams = [ + ''JVM_OPTS="$JVM_OPTS -Dcassandra.replace_address=192.168.1.2"'' + ]; + listenAddress = "192.168.1.3"; + }; + }; + + testScript = '' + subtest "start seed", sub { + $cass0->waitForUnit("cassandra.service"); + $cass0->waitForOpenPort(9160); + $cass0->execute("echo show version | cqlsh localhost -u cassandra -p cassandra"); + sleep 2; + $cass0->succeed("echo show version | cqlsh localhost -u cassandra -p cassandra"); + $cass1->start; + }; + subtest "cassandra user/group", sub { + $cass0->succeed("id \"${user}\" >/dev/null"); + $cass1->succeed("id \"${user}\" >/dev/null"); + }; + subtest "bring up cassandra cluster", sub { + $cass1->waitForUnit("cassandra.service"); + $cass0->waitUntilSucceeds("nodetool status | grep -c UN | grep 2"); + }; + subtest "break and fix node", sub { + $cass0->block; + $cass0->waitUntilSucceeds("nodetool status | grep -c DN | grep 1"); + $cass0->unblock; + $cass0->waitUntilSucceeds("nodetool status | grep -c UN | grep 2"); + }; + subtest "replace crashed node", sub { + $cass1->crash; + $cass2->start; + $cass2->waitForUnit("cassandra.service"); + $cass0->waitUntilFails("nodetool status | grep UN | grep 192.168.1.2"); + $cass0->waitUntilSucceeds("nodetool status | grep UN | grep 192.168.1.3"); + }; + ''; +}) diff --git a/nixos/tests/gocd-agent.nix b/nixos/tests/gocd-agent.nix index d5ed0f65ab01..5cadff089950 100644 --- a/nixos/tests/gocd-agent.nix +++ b/nixos/tests/gocd-agent.nix @@ -4,31 +4,37 @@ # 3. GoCD agent is available on GoCD server using GoCD API # 3.1. https://api.go.cd/current/#get-all-agents +let + serverUrl = "localhost:8153/go/api/agents"; + header = "Accept: application/vnd.go.cd.v2+json"; +in + import ./make-test.nix ({ pkgs, ...} : { name = "gocd-agent"; meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ swarren83 ]; + maintainers = [ grahamc swarren83 ]; }; -nodes = { - gocd_agent = - { config, pkgs, ... }: - { - virtualisation.memorySize = 2048; - services.gocd-agent = { - enable = true; - }; - services.gocd-server = { - enable = true; + nodes = { + gocd_agent = + { config, pkgs, ... }: + { + virtualisation.memorySize = 2046; + services.gocd-agent = { + enable = true; + }; + services.gocd-server = { + enable = true; + }; }; - }; -}; + }; testScript = '' startAll; $gocd_agent->waitForUnit("gocd-server"); $gocd_agent->waitForOpenPort("8153"); $gocd_agent->waitForUnit("gocd-agent"); - $gocd_agent->waitUntilSucceeds("curl -s -f localhost:8153/go/api/agents -H 'Accept: application/vnd.go.cd.v2+json'"); + $gocd_agent->waitUntilSucceeds("curl ${serverUrl} -H '${header}' | ${pkgs.jq}/bin/jq -e ._embedded.agents[0].uuid"); + $gocd_agent->succeed("curl ${serverUrl} -H '${header}' | ${pkgs.jq}/bin/jq -e ._embedded.agents[0].agent_state | grep -q Idle"); ''; }) diff --git a/nixos/tests/gocd-server.nix b/nixos/tests/gocd-server.nix index 6ec5bfb4dbb9..b473d4ad61c7 100644 --- a/nixos/tests/gocd-server.nix +++ b/nixos/tests/gocd-server.nix @@ -2,7 +2,7 @@ # 1. GoCD server starts # 2. GoCD server responds -import ./make-test.nix ({ pkgs, ...} : +import ./make-test.nix ({ pkgs, ...} : { name = "gocd-server"; @@ -13,8 +13,8 @@ import ./make-test.nix ({ pkgs, ...} : nodes = { gocd_server = { config, pkgs, ... }: - { - virtualisation.memorySize = 2048; + { + virtualisation.memorySize = 2046; services.gocd-server.enable = true; }; }; diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix index e71168a73660..1df2c651f9bc 100644 --- a/nixos/tests/installer.nix +++ b/nixos/tests/installer.nix @@ -201,19 +201,21 @@ let # The test cannot access the network, so any packages we # need must be included in the VM. - system.extraDependencies = - [ pkgs.sudo - pkgs.docbook5 - pkgs.docbook5_xsl - pkgs.unionfs-fuse - pkgs.ntp - pkgs.nixos-artwork - pkgs.perlPackages.XMLLibXML - pkgs.perlPackages.ListCompare + system.extraDependencies = with pkgs; + [ sudo + libxml2.bin + libxslt.bin + docbook5 + docbook5_xsl + unionfs-fuse + ntp + nixos-artwork + perlPackages.XMLLibXML + perlPackages.ListCompare # add curl so that rather than seeing the test attempt to download # curl's tarball, we see what it's trying to download - pkgs.curl + curl ] ++ optional (bootLoader == "grub" && grubVersion == 1) pkgs.grub ++ optionals (bootLoader == "grub" && grubVersion == 2) [ pkgs.grub2 pkgs.grub2_efi ]; |