diff options
author | Nicolas B. Pierron <nicolas.b.pierron@gmail.com> | 2014-12-14 14:17:56 +0100 |
---|---|---|
committer | Nicolas B. Pierron <nicolas.b.pierron@gmail.com> | 2014-12-14 14:17:56 +0100 |
commit | 42c3c205c4b0047f7dd3e39b43f5e5bd0f0b9502 (patch) | |
tree | 120fc5aa29603144f280cf1a6956da4089a113b9 /nixos | |
parent | 28f4ef2a5fda5d65e3567a0ab48ff17656cf9eac (diff) | |
parent | 3d74b3810104878527f0fde8aad65908579a504e (diff) | |
download | nixpkgs-42c3c205c4b0047f7dd3e39b43f5e5bd0f0b9502.tar nixpkgs-42c3c205c4b0047f7dd3e39b43f5e5bd0f0b9502.tar.gz nixpkgs-42c3c205c4b0047f7dd3e39b43f5e5bd0f0b9502.tar.bz2 nixpkgs-42c3c205c4b0047f7dd3e39b43f5e5bd0f0b9502.tar.lz nixpkgs-42c3c205c4b0047f7dd3e39b43f5e5bd0f0b9502.tar.xz nixpkgs-42c3c205c4b0047f7dd3e39b43f5e5bd0f0b9502.tar.zst nixpkgs-42c3c205c4b0047f7dd3e39b43f5e5bd0f0b9502.zip |
Merge remote-tracking branch 'origin/master' into syncserver
Diffstat (limited to 'nixos')
21 files changed, 969 insertions, 37 deletions
diff --git a/nixos/doc/manual/development/sources.xml b/nixos/doc/manual/development/sources.xml index 992a07af981..f9fadd6bf5e 100644 --- a/nixos/doc/manual/development/sources.xml +++ b/nixos/doc/manual/development/sources.xml @@ -50,8 +50,8 @@ Or, to base your local branch on the latest version available in the NixOS channel: <screen> -$ curl -sI http://nixos.org/channels/nixos-unstable/ | grep Location -Location: http://releases.nixos.org/nixos/unstable/nixos-14.10pre43986.acaf4a6/ +$ curl -sI https://nixos.org/channels/nixos-unstable/ | grep Location +Location: https://releases.nixos.org/nixos/unstable/nixos-14.10pre43986.acaf4a6/ $ git checkout -b local acaf4a6 </screen> @@ -92,4 +92,4 @@ to <command>nix-env</command>, as it will break after interpreting expressions in <filename>nixos/</filename> as packages.</para> --> -</chapter> \ No newline at end of file +</chapter> diff --git a/nixos/doc/manual/installation/upgrading.xml b/nixos/doc/manual/installation/upgrading.xml index e4e21603329..46d3af56b57 100644 --- a/nixos/doc/manual/installation/upgrading.xml +++ b/nixos/doc/manual/installation/upgrading.xml @@ -15,7 +15,7 @@ been built. These channels are: <itemizedlist> <listitem> <para>Stable channels, such as <literal - xlink:href="http://nixos.org/channels/nixos-14.04">nixos-14.04</literal>. + xlink:href="https://nixos.org/channels/nixos-14.04">nixos-14.04</literal>. These only get conservative bug fixes and package upgrades. For instance, a channel update may cause the Linux kernel on your system to be upgraded from 3.4.66 to 3.4.67 (a minor bug fix), but @@ -26,7 +26,7 @@ been built. These channels are: </listitem> <listitem> <para>The unstable channel, <literal - xlink:href="http://nixos.org/channels/nixos-unstable">nixos-unstable</literal>. + xlink:href="https://nixos.org/channels/nixos-unstable">nixos-unstable</literal>. This corresponds to NixOS’s main development branch, and may thus see radical changes between channel updates. It’s not recommended for production systems.</para> @@ -34,7 +34,7 @@ been built. These channels are: </itemizedlist> To see what channels are available, go to <link -xlink:href="http://nixos.org/channels"/>. (Note that the URIs of the +xlink:href="https://nixos.org/channels"/>. (Note that the URIs of the various channels redirect to a directory that contains the channel’s latest version and includes ISO images and VirtualBox appliances.)</para> @@ -53,20 +53,20 @@ nixos https://nixos.org/channels/nixos-unstable To switch to a different NixOS channel, do <screen> -$ nix-channel --add http://nixos.org/channels/<replaceable>channel-name</replaceable> nixos +$ nix-channel --add https://nixos.org/channels/<replaceable>channel-name</replaceable> nixos </screen> (Be sure to include the <literal>nixos</literal> parameter at the end.) For instance, to use the NixOS 14.04 stable channel: <screen> -$ nix-channel --add http://nixos.org/channels/nixos-14.04 nixos +$ nix-channel --add https://nixos.org/channels/nixos-14.04 nixos </screen> But if you want to live on the bleeding edge: <screen> -$ nix-channel --add http://nixos.org/channels/nixos-unstable nixos +$ nix-channel --add https://nixos.org/channels/nixos-unstable nixos </screen> </para> diff --git a/nixos/maintainers/scripts/ec2/create-ebs-amis.py b/nixos/maintainers/scripts/ec2/create-ebs-amis.py index 62525651ae0..6c91aa68694 100755 --- a/nixos/maintainers/scripts/ec2/create-ebs-amis.py +++ b/nixos/maintainers/scripts/ec2/create-ebs-amis.py @@ -75,7 +75,7 @@ m.run_command("mount {0} /mnt".format(device)) m.run_command("touch /mnt/.ebs") m.run_command("mkdir -p /mnt/etc/nixos") -m.run_command("nix-channel --add http://nixos.org/channels/nixos-{} nixos".format(args.channel)) +m.run_command("nix-channel --add https://nixos.org/channels/nixos-{} nixos".format(args.channel)) m.run_command("nix-channel --update") version = m.run_command("nix-instantiate --eval-only -A lib.nixpkgsVersion '<nixpkgs>'", capture_stdout=True).split(' ')[0].replace('"','').strip() diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix index 77e55fddf69..f99cea7d17b 100644 --- a/nixos/modules/config/networking.nix +++ b/nixos/modules/config/networking.nix @@ -140,7 +140,7 @@ in '' + optionalString config.services.nscd.enable '' # Invalidate the nscd cache whenever resolv.conf is # regenerated. - libc_restart='${pkgs.systemd}/bin/systemctl try-restart --no-block nscd.service' + libc_restart='${pkgs.systemd}/bin/systemctl try-restart --no-block nscd.service 2> /dev/null' '' + optionalString cfg.dnsSingleRequest '' # only send one DNS request at a time resolv_conf_options='single-request' diff --git a/nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt b/nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt index 8f0a8d355c6..84252f292c5 100644 --- a/nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt +++ b/nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt @@ -80,7 +80,7 @@ had booted this nixos. Run: * `grep local-cmds run/current-system/init` Then you can proceed normally subscribing to a nixos channel: - nix-channel --add http://nixos.org/channels/nixos-unstable + nix-channel --add https://nixos.org/channels/nixos-unstable nix-channel --update Testing: diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh index bd334c2a3cb..a7333fbd541 100644 --- a/nixos/modules/installer/tools/nixos-install.sh +++ b/nixos/modules/installer/tools/nixos-install.sh @@ -89,6 +89,12 @@ 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 if [ -n "$runChroot" ]; then if ! [ -L $mountPoint/nix/var/nix/profiles/system ]; then diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index bdaf85a03ce..3bb7fdb9b2d 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -172,6 +172,7 @@ kubernetes = 162; peerflix = 163; chronos = 164; + gitlab = 165; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -308,6 +309,7 @@ bosun = 157; kubernetes = 158; fleet = 159; + gitlab = 160; # When adding a gid, make sure it doesn't match an existing uid. And don't use gids above 399! diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index cbd5ac6a7ef..caf81de2af2 100755 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -137,6 +137,7 @@ ./services/desktops/gnome3/seahorse.nix ./services/desktops/gnome3/sushi.nix ./services/desktops/gnome3/tracker.nix + ./services/desktops/profile-sync-daemon.nix ./services/desktops/telepathy.nix ./services/games/ghost-one.nix ./services/games/minecraft-server.nix @@ -176,6 +177,7 @@ ./services/misc/etcd.nix ./services/misc/felix.nix ./services/misc/folding-at-home.nix + ./services/misc/gitlab.nix ./services/misc/gitolite.nix ./services/misc/gpsd.nix ./services/misc/mesos-master.nix diff --git a/nixos/modules/profiles/container.nix b/nixos/modules/profiles/container.nix index 5b531e5c3df..dd2e6579a93 100644 --- a/nixos/modules/profiles/container.nix +++ b/nixos/modules/profiles/container.nix @@ -20,17 +20,18 @@ in { contents = []; extraArgs = "--owner=0"; - # Some container managers like lxc need these - extraCommands = "mkdir -p proc sys dev"; - # Add init script to image storeContents = [ { object = config.system.build.toplevel + "/init"; symlink = "/init"; } ] ++ (pkgs2storeContents [ pkgs.stdenv ]); + + # Some container managers like lxc need these + extraCommands = "mkdir -p proc sys dev"; }; + boot.isContainer = true; boot.postBootCommands = '' # After booting, register the contents of the Nix store in the Nix @@ -40,18 +41,16 @@ in { rm /nix-path-registration fi - # nixos-rebuild also requires a "system" profile and an - # /etc/NIXOS tag. - touch /etc/NIXOS + # nixos-rebuild also requires a "system" profile ${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system ''; - boot.isContainer = true; - # Disable some features that are not useful in a container. sound.enable = mkDefault false; services.udisks2.enable = mkDefault false; - # Shut up warnings about not having a boot loader. - system.build.installBootLoader = "${pkgs.coreutils}/bin/true"; + # Install new init script + system.activationScripts.installInitScript = '' + ln -fs $systemConfig/init /init + ''; } diff --git a/nixos/modules/programs/virtualbox-host.nix b/nixos/modules/programs/virtualbox-host.nix index ea962d5d6ce..603b25e3cfc 100644 --- a/nixos/modules/programs/virtualbox-host.nix +++ b/nixos/modules/programs/virtualbox-host.nix @@ -9,9 +9,14 @@ in { options = { services.virtualboxHost.enable = mkEnableOption "VirtualBox Host support"; + services.virtualboxHost.addNetworkInterface = mkOption { + type = types.bool; + default = true; + description = "Automatically set up a vboxnet0 host-only network interface."; + }; }; - config = mkIf config.services.virtualboxHost.enable { + config = mkIf config.services.virtualboxHost.enable (mkMerge [{ boot.kernelModules = [ "vboxdrv" "vboxnetadp" "vboxnetflt" ]; boot.extraModulePackages = [ virtualbox ]; environment.systemPackages = [ virtualbox ]; @@ -24,10 +29,7 @@ in setuid = true; }; in map mkVboxStub [ - "VBoxBFE" - "VBoxBalloonCtrl" "VBoxHeadless" - "VBoxManage" "VBoxSDL" "VirtualBox" ]; @@ -46,7 +48,7 @@ in ''; # Since we lack the right setuid binaries, set up a host-only network by default. - + } (mkIf config.services.virtualboxHost.addNetworkInterface { systemd.services."vboxnet0" = { description = "VirtualBox vboxnet0 Interface"; requires = [ "dev-vboxnetctl.device" ]; @@ -68,5 +70,5 @@ in }; networking.interfaces.vboxnet0.ip4 = [ { address = "192.168.56.1"; prefixLength = 24; } ]; - }; + })]); } diff --git a/nixos/modules/services/desktops/profile-sync-daemon.nix b/nixos/modules/services/desktops/profile-sync-daemon.nix new file mode 100644 index 00000000000..c662c5d0fa6 --- /dev/null +++ b/nixos/modules/services/desktops/profile-sync-daemon.nix @@ -0,0 +1,139 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.psd; + + configFile = '' + ${if cfg.users != [ ] then '' + USERS="${concatStringsSep " " cfg.users}" + '' else ""} + + ${if cfg.browsers != [ ] then '' + BROWSERS="${concatStringsSep " " cfg.browsers}" + '' else ""} + + ${optionalString (cfg.volatile != "") "VOLATILE=${cfg.volatile}"} + ${optionalString (cfg.daemonFile != "") "DAEMON_FILE=${cfg.daemonFile}"} + ''; +in { + options.services.psd = with types; { + enable = mkOption { + type = bool; + default = false; + description = '' + Whether to enable the Profile Sync daemon. + ''; + }; + + users = mkOption { + type = listOf str; + default = [ ]; + example = [ "demo" ]; + description = '' + A list of users whose browser profiles should be sync'd to tmpfs. + ''; + }; + + browsers = mkOption { + type = listOf str; + default = [ ]; + example = [ "chromium" "firefox" ]; + description = '' + A list of browsers to sync. Available choices are: + + chromium chromium-dev conkeror.mozdev.org epiphany firefox + firefox-trunk google-chrome google-chrome-beta google-chrome-unstable + heftig-aurora icecat luakit midori opera opera-developer opera-beta + qupzilla palemoon rekonq seamonkey + + An empty list will enable all browsers. + ''; + }; + + resyncTimer = mkOption { + type = str; + default = "1h"; + example = "1h 30min"; + description = '' + The amount of time to wait before syncing browser profiles back to the + disk. + + Takes a systemd.unit time span. The time unit defaults to seconds if + omitted. + ''; + }; + + volatile = mkOption { + type = str; + default = "/run/psd-profiles"; + description = '' + The directory where browser profiles should reside(this should be + mounted as a tmpfs). Do not include a trailing backslash. + ''; + }; + + daemonFile = mkOption { + type = str; + default = "/run/psd"; + description = '' + Where the pid and backup configuration files will be stored. + ''; + }; + }; + + config = mkIf cfg.enable { + + systemd = { + services = { + psd = { + description = "Profile Sync daemon"; + wants = [ "psd-resync.service" "local-fs.target" ]; + wantedBy = [ "multi-user.target" ]; + preStart = "mkdir -p ${cfg.volatile}"; + + path = with pkgs; [ glibc rsync gawk ]; + + unitConfig = { + RequiresMountsFor = [ "/home/" ]; + }; + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = "yes"; + ExecStart = "${pkgs.profile-sync-daemon}/bin/profile-sync-daemon sync"; + + ExecStop = "${pkgs.profile-sync-daemon}/bin/profile-sync-daemon unsync"; + }; + }; + + psd-resync = { + description = "Timed profile resync"; + after = [ "psd.service" ]; + wants = [ "psd-resync.timer" ]; + partOf = [ "psd.service" ]; + + path = with pkgs; [ glibc rsync gawk ]; + + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.profile-sync-daemon}/bin/profile-sync-daemon resync"; + }; + }; + }; + + timers.psd-resync = { + description = "Timer for profile sync daemon - 1 Hour"; + partOf = [ "psd-resync.service" "psd.service" ]; + + timerConfig = { + OnUnitActiveSec = "${cfg.resyncTimer}"; + }; + }; + }; + + environment.etc."psd.conf".text = configFile; + + }; +} diff --git a/nixos/modules/services/misc/defaultUnicornConfig.rb b/nixos/modules/services/misc/defaultUnicornConfig.rb new file mode 100644 index 00000000000..81abaf336dc --- /dev/null +++ b/nixos/modules/services/misc/defaultUnicornConfig.rb @@ -0,0 +1,206 @@ +# The following was taken from github.com/crohr/syslogger and is BSD +# licensed. +require 'syslog' +require 'logger' +require 'thread' + +class Syslogger + + VERSION = "1.6.0" + + attr_reader :level, :ident, :options, :facility, :max_octets + attr_accessor :formatter + + MAPPING = { + Logger::DEBUG => Syslog::LOG_DEBUG, + Logger::INFO => Syslog::LOG_INFO, + Logger::WARN => Syslog::LOG_WARNING, + Logger::ERROR => Syslog::LOG_ERR, + Logger::FATAL => Syslog::LOG_CRIT, + Logger::UNKNOWN => Syslog::LOG_ALERT + } + + # + # Initializes default options for the logger + # <tt>ident</tt>:: the name of your program [default=$0]. + # <tt>options</tt>:: syslog options [default=<tt>Syslog::LOG_PID | Syslog::LOG_CONS</tt>]. + # Correct values are: + # LOG_CONS : writes the message on the console if an error occurs when sending the message; + # LOG_NDELAY : no delay before sending the message; + # LOG_PERROR : messages will also be written on STDERR; + # LOG_PID : adds the process number to the message (just after the program name) + # <tt>facility</tt>:: the syslog facility [default=nil] Correct values include: + # Syslog::LOG_DAEMON + # Syslog::LOG_USER + # Syslog::LOG_SYSLOG + # Syslog::LOG_LOCAL2 + # Syslog::LOG_NEWS + # etc. + # + # Usage: + # logger = Syslogger.new("my_app", Syslog::LOG_PID | Syslog::LOG_CONS, Syslog::LOG_LOCAL0) + # logger.level = Logger::INFO # use Logger levels + # logger.warn "warning message" + # logger.debug "debug message" + # + def initialize(ident = $0, options = Syslog::LOG_PID | Syslog::LOG_CONS, facility = nil) + @ident = ident + @options = options || (Syslog::LOG_PID | Syslog::LOG_CONS) + @facility = facility + @level = Logger::INFO + @mutex = Mutex.new + @formatter = Logger::Formatter.new + end + + %w{debug info warn error fatal unknown}.each do |logger_method| + # Accepting *args as message could be nil. + # Default params not supported in ruby 1.8.7 + define_method logger_method.to_sym do |*args, &block| + return true if @level > Logger.const_get(logger_method.upcase) + message = args.first || block && block.call + add(Logger.const_get(logger_method.upcase), message) + end + + unless logger_method == 'unknown' + define_method "#{logger_method}?".to_sym do + @level <= Logger.const_get(logger_method.upcase) + end + end + end + + # Log a message at the Logger::INFO level. Useful for use with Rack::CommonLogger + def write(msg) + add(Logger::INFO, msg) + end + + # Logs a message at the Logger::INFO level. + def <<(msg) + add(Logger::INFO, msg) + end + + # Low level method to add a message. + # +severity+:: the level of the message. One of Logger::DEBUG, Logger::INFO, Logger::WARN, Logger::ERROR, Logger::FATAL, Logger::UNKNOWN + # +message+:: the message string. + # If nil, the method will call the block and use the result as the message string. + # If both are nil or no block is given, it will use the progname as per the behaviour of both the standard Ruby logger, and the Rails BufferedLogger. + # +progname+:: optionally, overwrite the program name that appears in the log message. + def add(severity, message = nil, progname = nil, &block) + if message.nil? && block.nil? && !progname.nil? + message, progname = progname, nil + end + progname ||= @ident + + @mutex.synchronize do + Syslog.open(progname, @options, @facility) do |s| + s.mask = Syslog::LOG_UPTO(MAPPING[@level]) + communication = clean(message || block && block.call) + if self.max_octets + buffer = "#{tags_text}" + communication.bytes do |byte| + buffer.concat(byte) + # if the last byte we added is potentially part of an escape, we'll go ahead and add another byte + if buffer.bytesize >= self.max_octets && !['%'.ord,'\\'.ord].include?(byte) + s.log(MAPPING[severity],buffer) + buffer = "" + end + end + s.log(MAPPING[severity],buffer) unless buffer.empty? + else + s.log(MAPPING[severity],"#{tags_text}#{communication}") + end + end + end + end + + # Set the max octets of the messages written to the log + def max_octets=(max_octets) + @max_octets = max_octets + end + + # Sets the minimum level for messages to be written in the log. + # +level+:: one of <tt>Logger::DEBUG</tt>, <tt>Logger::INFO</tt>, <tt>Logger::WARN</tt>, <tt>Logger::ERROR</tt>, <tt>Logger::FATAL</tt>, <tt>Logger::UNKNOWN</tt> + def level=(level) + level = Logger.const_get(level.to_s.upcase) if level.is_a?(Symbol) + + unless level.is_a?(Fixnum) + raise ArgumentError.new("Invalid logger level `#{level.inspect}`") + end + + @level = level + end + + # Sets the ident string passed along to Syslog + def ident=(ident) + @ident = ident + end + + # Tagging code borrowed from ActiveSupport gem + def tagged(*tags) + new_tags = push_tags(*tags) + yield self + ensure + pop_tags(new_tags.size) + end + + def push_tags(*tags) + tags.flatten.reject{ |i| i.respond_to?(:empty?) ? i.empty? : !i }.tap do |new_tags| + current_tags.concat new_tags + end + end + + def pop_tags(size = 1) + current_tags.pop size + end + + def clear_tags! + current_tags.clear + end + + protected + + # Borrowed from SyslogLogger. + def clean(message) + message = message.to_s.dup + message.strip! # remove whitespace + message.gsub!(/\n/, '\\n') # escape newlines + message.gsub!(/%/, '%%') # syslog(3) freaks on % (printf) + message.gsub!(/\e\[[^m]*m/, '') # remove useless ansi color codes + message + end + + private + + def tags_text + tags = current_tags + if tags.any? + tags.collect { |tag| "[#{tag}] " }.join + end + end + + def current_tags + Thread.current[:syslogger_tagged_logging_tags] ||= [] + end +end + +worker_processes 2 +working_directory ENV["GITLAB_PATH"] +pid ENV["UNICORN_PATH"] + "/tmp/pids/unicorn.pid" + +listen ENV["UNICORN_PATH"] + "/tmp/sockets/gitlab.socket", :backlog => 1024 +listen "127.0.0.1:8080", :tcp_nopush => true + +timeout 60 + +logger Syslogger.new + +preload_app true + +GC.respond_to?(:copy_on_write_friendly=) and + GC.copy_on_write_friendly = true + +check_client_connection false + +after_fork do |server, worker| + defined?(ActiveRecord::Base) and + ActiveRecord::Base.establish_connection +end diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix new file mode 100644 index 00000000000..efa139c8dfd --- /dev/null +++ b/nixos/modules/services/misc/gitlab.nix @@ -0,0 +1,295 @@ +{ config, lib, pkgs, ... }: + +# TODO: support non-postgresql + +with lib; + +let + cfg = config.services.gitlab; + + ruby = pkgs.ruby; + rubyLibs = pkgs.rubyLibs; + + databaseYml = '' + production: + adapter: postgresql + database: ${cfg.databaseName} + host: ${cfg.databaseHost} + password: ${cfg.databasePassword} + username: ${cfg.databaseUsername} + encoding: utf8 + ''; + gitlabShellYml = '' + user: gitlab + gitlab_url: "http://${cfg.host}:${toString cfg.port}/" + http_settings: + self_signed_cert: false + repos_path: "${cfg.stateDir}/repositories" + log_file: "${cfg.stateDir}/log/gitlab-shell.log" + redis: + bin: ${pkgs.redis}/bin/redis-cli + host: 127.0.0.1 + port: 6379 + database: 0 + namespace: resque:gitlab + ''; + + unicornConfig = builtins.readFile ./defaultUnicornConfig.rb; + + gitlab-runner = pkgs.stdenv.mkDerivation rec { + name = "gitlab-runner"; + buildInputs = [ pkgs.gitlab pkgs.rubyLibs.bundler pkgs.makeWrapper ]; + phases = "installPhase fixupPhase"; + buildPhase = ""; + installPhase = '' + mkdir -p $out/bin + makeWrapper ${rubyLibs.bundler}/bin/bundle $out/bin/gitlab-runner\ + --set RAKEOPT '"-f ${pkgs.gitlab}/share/gitlab/Rakefile"'\ + --set UNICORN_PATH "${cfg.stateDir}/"\ + --set GITLAB_PATH "${pkgs.gitlab}/share/gitlab/"\ + --set GITLAB_APPLICATION_LOG_PATH "${cfg.stateDir}/log/application.log"\ + --set GITLAB_SATELLITES_PATH "${cfg.stateDir}/satellites"\ + --set GITLAB_SHELL_PATH "${pkgs.gitlab-shell}"\ + --set GITLAB_REPOSITORIES_PATH "${cfg.stateDir}/repositories"\ + --set GITLAB_SHELL_HOOKS_PATH "${cfg.stateDir}/shell/hooks"\ + --set BUNDLE_GEMFILE "${pkgs.gitlab}/share/gitlab/Gemfile"\ + --set GITLAB_EMAIL_FROM "${cfg.emailFrom}"\ + --set GITLAB_SHELL_CONFIG_PATH "${cfg.stateDir}/shell/config.yml"\ + --set GITLAB_SHELL_SECRET_PATH "${cfg.stateDir}/config/gitlab_shell_secret"\ + --set GITLAB_HOST "${cfg.host}"\ + --set GITLAB_PORT "${toString cfg.port}"\ + --set GITLAB_BACKUP_PATH"${cfg.backupPath}"\ + --set RAILS_ENV "production" + ''; + }; + +in { + + options = { + services.gitlab = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable the gitlab service. + ''; + }; + + satelliteDir = mkOption { + type = types.str; + default = "/var/gitlab/git-satellites"; + description = "Gitlab directory to store checked out git trees requires for operation."; + }; + + stateDir = mkOption { + type = types.str; + default = "/var/gitlab/state"; + description = "Gitlab state directory, logs are stored here."; + }; + + backupPath = mkOption { + type = types.str; + default = cfg.stateDir + "/backup"; + description = "Gitlab path for backups."; + }; + + databaseHost = mkOption { + type = types.str; + default = "127.0.0.1"; + description = "Gitlab database hostname."; + }; + + databasePassword = mkOption { + type = types.str; + default = ""; + description = "Gitlab database user password."; + }; + + databaseName = mkOption { + type = types.str; + default = "gitlab"; + description = "Gitlab database name."; + }; + + databaseUsername = mkOption { + type = types.str; + default = "gitlab"; + description = "Gitlab database user."; + }; + + emailFrom = mkOption { + type = types.str; + default = "example@example.org"; + description = "The source address for emails sent by gitlab."; + }; + + host = mkOption { + type = types.str; + default = config.networking.hostName; + description = "Gitlab host name. Used e.g. for copy-paste URLs."; + }; + + port = mkOption { + type = types.int; + default = 8080; + description = "Gitlab server listening port."; + }; + }; + }; + + config = mkIf cfg.enable { + + environment.systemPackages = [ gitlab-runner pkgs.gitlab-shell ]; + + assertions = [ + { assertion = cfg.databasePassword != ""; + message = "databasePassword must be set"; + } + ]; + + # Redis is required for the sidekiq queue runner. + services.redis.enable = mkDefault true; + # We use postgres as the main data store. + services.postgresql.enable = mkDefault true; + services.postgresql.package = mkDefault pkgs.postgresql; + # Use postfix to send out mails. + services.postfix.enable = mkDefault true; + + users.extraUsers = [ + { name = "gitlab"; + group = "gitlab"; + home = "${cfg.stateDir}/home"; + shell = "${pkgs.bash}/bin/bash"; + uid = config.ids.uids.gitlab; + } ]; + + users.extraGroups = [ + { name = "gitlab"; + gid = config.ids.gids.gitlab; + } ]; + + systemd.services.gitlab-sidekiq = { + after = [ "network.target" "redis.service" ]; + wantedBy = [ "multi-user.target" ]; + environment.HOME = "${cfg.stateDir}/home"; + environment.UNICORN_PATH = "${cfg.stateDir}/"; + environment.GITLAB_PATH = "${pkgs.gitlab}/share/gitlab/"; + environment.GITLAB_APPLICATION_LOG_PATH = "${cfg.stateDir}/log/application.log"; + environment.GITLAB_SATELLITES_PATH = "${cfg.stateDir}/satellites"; + environment.GITLAB_SHELL_PATH = "${pkgs.gitlab-shell}"; + environment.GITLAB_REPOSITORIES_PATH = "${cfg.stateDir}/repositories"; + environment.GITLAB_SHELL_HOOKS_PATH = "${cfg.stateDir}/shell/hooks"; + environment.BUNDLE_GEMFILE = "${pkgs.gitlab}/share/gitlab/Gemfile"; + environment.GITLAB_EMAIL_FROM = "${cfg.emailFrom}"; + environment.GITLAB_SHELL_CONFIG_PATH = "${cfg.stateDir}/shell/config.yml"; + environment.GITLAB_SHELL_SECRET_PATH = "${cfg.stateDir}/config/gitlab_shell_secret"; + environment.GITLAB_HOST = "${cfg.host}"; + environment.GITLAB_PORT = "${toString cfg.port}"; + environment.GITLAB_DATABASE_HOST = "${cfg.databaseHost}"; + environment.GITLAB_DATABASE_PASSWORD = "${cfg.databasePassword}"; + environment.RAILS_ENV = "production"; + path = with pkgs; [ + config.services.postgresql.package + gitAndTools.git + ruby + openssh + nodejs + ]; + serviceConfig = { + Type = "simple"; + User = "gitlab"; + Group = "gitlab"; + TimeoutSec = "300"; + WorkingDirectory = "${pkgs.gitlab}/share/gitlab"; + ExecStart="${rubyLibs.bundler}/bin/bundle exec \"sidekiq -q post_receive -q mailer -q system_hook -q project_web_hook -q gitlab_shell -q common -q default -e production -P ${cfg.stateDir}/tmp/sidekiq.pid\""; + }; + }; + + systemd.services.gitlab = { + after = [ "network.target" "postgresql.service" "redis.service" ]; + wantedBy = [ "multi-user.target" ]; + environment.HOME = "${cfg.stateDir}/home"; + environment.UNICORN_PATH = "${cfg.stateDir}/"; + environment.GITLAB_PATH = "${pkgs.gitlab}/share/gitlab/"; + environment.GITLAB_APPLICATION_LOG_PATH = "${cfg.stateDir}/log/application.log"; + environment.GITLAB_SATELLITES_PATH = "${cfg.stateDir}/satellites"; + environment.GITLAB_SHELL_PATH = "${pkgs.gitlab-shell}"; + environment.GITLAB_REPOSITORIES_PATH = "${cfg.stateDir}/repositories"; + environment.GITLAB_SHELL_HOOKS_PATH = "${cfg.stateDir}/shell/hooks"; + environment.BUNDLE_GEMFILE = "${pkgs.gitlab}/share/gitlab/Gemfile"; + environment.GITLAB_EMAIL_FROM = "${cfg.emailFrom}"; + environment.GITLAB_HOST = "${cfg.host}"; + environment.GITLAB_PORT = "${toString cfg.port}"; + environment.GITLAB_DATABASE_HOST = "${cfg.databaseHost}"; + environment.GITLAB_DATABASE_PASSWORD = "${cfg.databasePassword}"; + environment.RAILS_ENV = "production"; + path = with pkgs; [ + config.services.postgresql.package + gitAndTools.git + ruby + openssh + nodejs + ]; + preStart = '' + # TODO: use env vars + mkdir -p ${cfg.stateDir} + mkdir -p ${cfg.stateDir}/log + mkdir -p ${cfg.stateDir}/satellites + mkdir -p ${cfg.stateDir}/repositories + mkdir -p ${cfg.stateDir}/shell/hooks + mkdir -p ${cfg.stateDir}/tmp/pids + mkdir -p ${cfg.stateDir}/tmp/sockets + rm -rf ${cfg.stateDir}/config + mkdir -p ${cfg.stateDir}/config + # TODO: What exactly is gitlab-shell doing with the secret? + head -c 20 /dev/urandom > ${cfg.stateDir}/config/gitlab_shell_secret + mkdir -p ${cfg.stateDir}/home/.ssh + touch ${cfg.stateDir}/home/.ssh/authorized_keys + + cp -rf ${pkgs.gitlab}/share/gitlab/config ${cfg.stateDir}/ + cp ${pkgs.gitlab}/share/gitlab/VERSION ${cfg.stateDir}/VERSION + + ln -fs ${pkgs.writeText "database.yml" databaseYml} ${cfg.stateDir}/config/database.yml + ln -fs ${pkgs.writeText "unicorn.rb" unicornConfig} ${cfg.stateDir}/config/unicorn.rb + + chown -R gitlab:gitlab ${cfg.stateDir}/ + chmod -R 755 ${cfg.stateDir}/ + + if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then + if ! test -e "${cfg.stateDir}/db-created"; then + psql postgres -c "CREATE ROLE gitlab WITH LOGIN NOCREATEDB NOCREATEROLE NOCREATEUSER ENCRYPTED PASSWORD '${cfg.databasePassword}'" + ${config.services.postgresql.package}/bin/createdb --owner gitlab gitlab || true + touch "${cfg.stateDir}/db-created" + + # force=yes disables the manual-interaction yes/no prompt + # which breaks without an stdin. + force=yes ${rubyLibs.bundler}/bin/bundle exec rake -f ${pkgs.gitlab}/share/gitlab/Rakefile gitlab:setup RAILS_ENV=production + fi + fi + + # Install the shell required to push repositories + ln -fs ${pkgs.writeText "config.yml" gitlabShellYml} ${cfg.stateDir}/shell/config.yml + export GITLAB_SHELL_CONFIG_PATH=""${cfg.stateDir}/shell/config.yml + ${pkgs.gitlab-shell}/bin/install + + # Change permissions in the last step because some of the + # intermediary scripts like to create directories as root. + chown -R gitlab:gitlab ${cfg.stateDir}/ + chmod -R 755 ${cfg.stateDir}/ + ''; + + serviceConfig = { + PermissionsStartOnly = true; # preStart must be run as root + Type = "simple"; + User = "gitlab"; + Group = "gitlab"; + TimeoutSec = "300"; + WorkingDirectory = "${pkgs.gitlab}/share/gitlab"; + ExecStart="${rubyLibs.bundler}/bin/bundle exec \"unicorn -c ${cfg.stateDir}/config/unicorn.rb -E production\""; + }; + + }; + + }; + +} diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix index 37bc1df2361..55a93dfe64c 100644 --- a/nixos/modules/services/networking/networkmanager.nix +++ b/nixos/modules/services/networking/networkmanager.nix @@ -194,7 +194,7 @@ in { }; powerManagement.resumeCommands = '' - Systemctl restart network-manager + systemctl restart network-manager ''; security.polkit.extraConfig = polkitConf; diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix index cf211404649..cd30ce1b7ce 100644 --- a/nixos/modules/system/boot/stage-1.nix +++ b/nixos/modules/system/boot/stage-1.nix @@ -240,8 +240,9 @@ in example = "/dev/sda3"; description = '' Device for manual resume attempt during boot. This should be used primarily - if you want to resume from file. Specify here the device where the file - resides. You should also use <varname>boot.kernelParams</varname> to specify + if you want to resume from file. If left empty, the swap partitions are used. + Specify here the device where the file resides. + You should also use <varname>boot.kernelParams</varname> to specify <literal><replaceable>resume_offset</replaceable></literal>. ''; }; @@ -355,10 +356,17 @@ in config = mkIf (!config.boot.isContainer) { - assertions = singleton + assertions = [ { assertion = any (fs: fs.mountPoint == "/") (attrValues config.fileSystems); message = "The ‘fileSystems’ option does not specify your root file system."; - }; + } + { assertion = let inherit (config.boot) resumeDevice; in + resumeDevice == "" || builtins.substring 0 1 resumeDevice == "/"; + message = "boot.resumeDevice has to be an absolute path." + + " Old \"x:y\" style is no longer supported."; + } + ]; + system.build.bootStage1 = bootStage1; system.build.initialRamdisk = initialRamdisk; diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix index e850c1f6cdd..f2f68a11a28 100644 --- a/nixos/release-combined.nix +++ b/nixos/release-combined.nix @@ -48,6 +48,7 @@ in rec { (all nixos.ova) #(all nixos.tests.containers) + (all nixos.tests.chromium) (all nixos.tests.firefox) (all nixos.tests.firewall) (all nixos.tests.gnome3) diff --git a/nixos/release.nix b/nixos/release.nix index efc49adce46..04b8fd9bf67 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -214,7 +214,7 @@ in rec { }); # Provide container tarball for lxc, libvirt-lxc, docker-lxc, ... - container_tarball = forAllSystems (system: makeSystemTarball { + containerTarball = forAllSystems (system: makeSystemTarball { module = ./modules/virtualisation/lxc-container.nix; inherit system; }); @@ -251,6 +251,7 @@ in rec { tests.firefox = callTest tests/firefox.nix {}; tests.firewall = callTest tests/firewall.nix {}; tests.fleet = scrubDrv (import tests/fleet.nix { system = "x86_64-linux"; }); + tests.gitlab = callTest tests/gitlab.nix {}; tests.gnome3 = callTest tests/gnome3.nix {}; tests.installer.grub1 = forAllSystems (system: scrubDrv (import tests/installer.nix { inherit system; }).grub1.test); tests.installer.lvm = forAllSystems (system: scrubDrv (import tests/installer.nix { inherit system; }).lvm.test); @@ -306,6 +307,7 @@ in rec { tests.simple = callTest tests/simple.nix {}; tests.tomcat = callTest tests/tomcat.nix {}; tests.udisks2 = callTest tests/udisks2.nix {}; + tests.virtualbox = callTest tests/virtualbox.nix {}; tests.xfce = callTest tests/xfce.nix {}; diff --git a/nixos/tests/gitlab.nix b/nixos/tests/gitlab.nix new file mode 100644 index 00000000000..2b0715e97bc --- /dev/null +++ b/nixos/tests/gitlab.nix @@ -0,0 +1,20 @@ +# This test runs gitlab and checks if it works + +import ./make-test.nix { + name = "gitlab"; + + nodes = { + gitlab = { config, pkgs, ... }: { + virtualisation.memorySize = 768; + services.gitlab.enable = true; + services.gitlab.databasePassword = "gitlab"; + }; + }; + + testScript = '' + $gitlab->start(); + $gitlab->waitForUnit("gitlab.service"); + $gitlab->waitForUnit("gitlab-sidekiq.service"); + $gitlab->waitUntilSucceeds("curl http://localhost:8080/users/sign_in"); + ''; +} diff --git a/nixos/tests/kubernetes.nix b/nixos/tests/kubernetes.nix index 1ca6153bcb9..8bc7c8d618a 100644 --- a/nixos/tests/kubernetes.nix +++ b/nixos/tests/kubernetes.nix @@ -47,7 +47,7 @@ import ./make-test.nix rec { master = { config, pkgs, lib, nodes, ... }: { - virtualisation.memorySize = 512; + virtualisation.memorySize = 768; services.kubernetes = { roles = ["master" "node"]; controllerManager.machines = ["master" "node"]; diff --git a/nixos/tests/quake3.nix b/nixos/tests/quake3.nix index b16cb179982..e0e6d6eaadb 100644 --- a/nixos/tests/quake3.nix +++ b/nixos/tests/quake3.nix @@ -15,14 +15,14 @@ in rec { name = "quake3"; - makeCoverageReport = true; + # TODO: lcov doesn't work atm + #makeCoverageReport = true; client = { config, pkgs, ... }: { imports = [ ./common/x11.nix ]; hardware.opengl.driSupport = true; - services.xserver.defaultDepth = pkgs.lib.mkOverride 0 16; environment.systemPackages = [ pkgs.quake3demo ]; nixpkgs.config.packageOverrides = overrides; }; diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix new file mode 100644 index 00000000000..c8912760f3d --- /dev/null +++ b/nixos/tests/virtualbox.nix @@ -0,0 +1,250 @@ +import ./make-test.nix ({ pkgs, ... }: let + + testVMConfig = { config, pkgs, ... }: { + boot.kernelParams = [ + "console=tty0" "console=ttyS0" "ignore_loglevel" + "boot.trace" "panic=1" "boot.panic_on_fail" + ]; + + fileSystems."/" = { + device = "vboxshare"; + fsType = "vboxsf"; + }; + + services.virtualboxGuest.enable = true; + + boot.initrd.kernelModules = [ "vboxsf" ]; + + boot.initrd.extraUtilsCommands = '' + cp -av -t "$out/bin/" \ + "${pkgs.linuxPackages.virtualboxGuestAdditions}/sbin/mount.vboxsf" + ''; + + boot.initrd.postMountCommands = '' + touch /mnt-root/boot-done + + i=0 + while [ ! -e /mnt-root/shutdown ]; do + sleep 10 + i=$(($i + 10)) + [ $i -le 120 ] || fail + done + + rm -f /mnt-root/boot-done /mnt-root/shutdown + poweroff -f + ''; + + system.requiredKernelConfig = with config.lib.kernelConfig; [ + (isYes "SERIAL_8250_CONSOLE") + (isYes "SERIAL_8250") + ]; + }; + + testVM = let + cfg = (import ../lib/eval-config.nix { + system = "i686-linux"; + modules = [ + ../modules/profiles/minimal.nix + testVMConfig + ]; + }).config; + in pkgs.vmTools.runInLinuxVM (pkgs.runCommand "virtualbox-image" { + preVM = '' + mkdir -p "$out" + diskImage="$(pwd)/qimage" + ${pkgs.vmTools.qemu}/bin/qemu-img create -f raw "$diskImage" 100M + ''; + + postVM = '' + echo "creating VirtualBox disk image..." + ${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -O vdi \ + "$diskImage" "$out/disk.vdi" + ''; + + buildInputs = [ pkgs.utillinux pkgs.perl ]; + } '' + ${pkgs.parted}/sbin/parted /dev/vda mklabel msdos + ${pkgs.parted}/sbin/parted /dev/vda -- mkpart primary ext2 1M -1s + . /sys/class/block/vda1/uevent + mknod /dev/vda1 b $MAJOR $MINOR + + ${pkgs.e2fsprogs}/sbin/mkfs.ext4 /dev/vda1 + ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1 + mkdir /mnt + mount /dev/vda1 /mnt + cp "${cfg.system.build.kernel}/bzImage" /mnt/linux + cp "${cfg.system.build.initialRamdisk}/initrd" /mnt/initrd + + ${pkgs.grub2}/bin/grub-install --boot-directory=/mnt /dev/vda + + cat > /mnt/grub/grub.cfg <<GRUB + set root=hd0,1 + linux /linux ${pkgs.lib.concatStringsSep " " cfg.boot.kernelParams} + initrd /initrd + boot + GRUB + umount /mnt + ''); + +in { + name = "virtualbox"; + + machine = { pkgs, ... }: { + imports = [ ./common/user-account.nix ./common/x11.nix ]; + services.virtualboxHost.enable = true; + + systemd.sockets.vboxtestlog = { + description = "VirtualBox Test Machine Log Socket"; + wantedBy = [ "sockets.target" ]; + before = [ "multi-user.target" ]; + socketConfig.ListenStream = "/run/virtualbox-log.sock"; + socketConfig.Accept = true; + }; + + systemd.services."vboxtestlog@" = { + description = "VirtualBox Test Machine Log"; + serviceConfig.StandardInput = "socket"; + serviceConfig.StandardOutput = "syslog"; + serviceConfig.SyslogIdentifier = "testvm"; + serviceConfig.ExecStart = "${pkgs.coreutils}/bin/cat"; + }; + }; + + testScript = let + mkFlags = pkgs.lib.concatStringsSep " "; + + createFlags = mkFlags [ + "--ostype Linux26" + "--register" + ]; + + vmFlags = mkFlags [ + "--uart1 0x3F8 4" + "--uartmode1 client /run/virtualbox-log.sock" + ]; + + controllerFlags = mkFlags [ + "--name SATA" + "--add sata" + "--bootable on" + "--hostiocache on" + ]; + + diskFlags = mkFlags [ + "--storagectl SATA" + "--port 0" + "--device 0" + "--type hdd" + "--mtype immutable" + "--medium ${testVM}/disk.vdi" + ]; + + sharedFlags = mkFlags [ + "--name vboxshare" + "--hostpath /home/alice/vboxshare" + ]; + in '' + sub ru { + return "su - alice -c '$_[0]'"; + } + + sub waitForVMBoot { + $machine->execute(ru( + 'set -e; i=0; '. + 'while ! test -e /home/alice/vboxshare/boot-done; do '. + 'sleep 10; i=$(($i + 10)); [ $i -le 3600 ]; '. + 'VBoxManage list runningvms | grep -qF test; '. + 'done' + )); + } + + sub checkRunning { + my $checkrunning = ru "VBoxManage list runningvms | grep -qF test"; + my ($status, $out) = $machine->execute($checkrunning); + return $status == 0; + } + + sub waitForStartup { + for (my $i = 0; $i <= 120; $i += 10) { + $machine->sleep(10); + return if checkRunning; + } + die "VirtualBox VM didn't start up within 2 minutes"; + } + + sub waitForShutdown { + for (my $i = 0; $i <= 120; $i += 10) { + $machine->sleep(10); + return unless checkRunning; + } + die "VirtualBox VM didn't shut down within 2 minutes"; + } + + sub shutdownVM { + $machine->succeed(ru "touch /home/alice/vboxshare/shutdown"); + $machine->waitUntilSucceeds( + "test ! -e /home/alice/vboxshare/shutdown ". + " -a ! -e /home/alice/vboxshare/boot-done" + ); + waitForShutdown; + } + + sub cleanup { + $machine->execute(ru "VBoxManage controlvm test poweroff") + if checkRunning; + $machine->succeed("rm -rf /home/alice/vboxshare"); + $machine->succeed("mkdir -p /home/alice/vboxshare"); + $machine->succeed("chown alice.users /home/alice/vboxshare"); + } + + $machine->waitForX; + + $machine->succeed(ru "VBoxManage createvm --name test ${createFlags}"); + $machine->succeed(ru "VBoxManage modifyvm test ${vmFlags}"); + + $machine->fail("test -e '/root/VirtualBox VMs'"); + $machine->succeed("test -e '/home/alice/VirtualBox VMs'"); + + $machine->succeed(ru "VBoxManage storagectl test ${controllerFlags}"); + $machine->succeed(ru "VBoxManage storageattach test ${diskFlags}"); + + $machine->succeed(ru "VBoxManage sharedfolder add test ${sharedFlags}"); + + $machine->succeed(ru "VBoxManage showvminfo test >&2"); + + cleanup; + + subtest "virtualbox-gui", sub { + $machine->succeed(ru "VirtualBox &"); + $machine->waitForWindow(qr/Oracle VM VirtualBox Manager/); + $machine->sleep(5); + $machine->screenshot("gui_manager_started"); + $machine->sendKeys("ret"); + $machine->screenshot("gui_manager_sent_startup"); + waitForStartup; + $machine->screenshot("gui_started"); + waitForVMBoot; + $machine->screenshot("gui_booted"); + shutdownVM; + $machine->sleep(5); + $machine->screenshot("gui_stopped"); + $machine->sendKeys("ctrl-q"); + $machine->sleep(5); + $machine->screenshot("gui_manager_stopped"); + }; + + cleanup; + + subtest "virtualbox-cli", sub { + $machine->succeed(ru "VBoxManage startvm test"); + waitForStartup; + $machine->screenshot("cli_started"); + waitForVMBoot; + $machine->screenshot("cli_booted"); + shutdownVM; + }; + + $machine->fail("test -e '/root/VirtualBox VMs'"); + $machine->succeed("test -e '/home/alice/VirtualBox VMs'"); + ''; +}) |