diff options
Diffstat (limited to 'nixos/modules/services/misc')
-rw-r--r-- | nixos/modules/services/misc/airsonic.nix | 19 | ||||
-rw-r--r-- | nixos/modules/services/misc/emby.nix | 19 | ||||
-rw-r--r-- | nixos/modules/services/misc/gitea.nix | 13 | ||||
-rw-r--r-- | nixos/modules/services/misc/gitit.nix | 2 | ||||
-rw-r--r-- | nixos/modules/services/misc/gitlab.nix | 15 | ||||
-rw-r--r-- | nixos/modules/services/misc/gitlab.xml | 124 | ||||
-rw-r--r-- | nixos/modules/services/misc/lidarr.nix | 46 | ||||
-rw-r--r-- | nixos/modules/services/misc/nix-daemon.nix | 9 | ||||
-rw-r--r-- | nixos/modules/services/misc/nixos-manual.nix | 127 | ||||
-rw-r--r-- | nixos/modules/services/misc/redmine.nix | 294 | ||||
-rw-r--r-- | nixos/modules/services/misc/sickbeard.nix | 92 | ||||
-rw-r--r-- | nixos/modules/services/misc/synergy.nix | 12 | ||||
-rw-r--r-- | nixos/modules/services/misc/taskserver/doc.xml | 209 | ||||
-rw-r--r-- | nixos/modules/services/misc/weechat.nix | 56 | ||||
-rw-r--r-- | nixos/modules/services/misc/weechat.xml | 66 |
15 files changed, 668 insertions, 435 deletions
diff --git a/nixos/modules/services/misc/airsonic.nix b/nixos/modules/services/misc/airsonic.nix index 083587b8ebb1..01d7b3cf6b9d 100644 --- a/nixos/modules/services/misc/airsonic.nix +++ b/nixos/modules/services/misc/airsonic.nix @@ -73,6 +73,24 @@ in { ${cfg.home}/transcoders. ''; }; + + jvmOptions = mkOption { + description = '' + Extra command line options for the JVM running AirSonic. + Useful for sending jukebox output to non-default alsa + devices. + ''; + default = [ + ]; + type = types.listOf types.str; + example = [ + "-Djavax.sound.sampled.Clip='#CODEC [plughw:1,0]'" + "-Djavax.sound.sampled.Port='#Port CODEC [hw:1]'" + "-Djavax.sound.sampled.SourceDataLine='#CODEC [plughw:1,0]'" + "-Djavax.sound.sampled.TargetDataLine='#CODEC [plughw:1,0]'" + ]; + }; + }; }; @@ -98,6 +116,7 @@ in { -Dserver.port=${toString cfg.port} \ -Dairsonic.contextPath=${cfg.contextPath} \ -Djava.awt.headless=true \ + ${toString cfg.jvmOptions} \ -verbose:gc \ -jar ${pkgs.airsonic}/webapps/airsonic.war ''; diff --git a/nixos/modules/services/misc/emby.nix b/nixos/modules/services/misc/emby.nix index 64cc9c610ac3..151edd0e761a 100644 --- a/nixos/modules/services/misc/emby.nix +++ b/nixos/modules/services/misc/emby.nix @@ -36,11 +36,18 @@ in after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; preStart = '' - test -d ${cfg.dataDir} || { - echo "Creating initial Emby data directory in ${cfg.dataDir}" - mkdir -p ${cfg.dataDir} - chown -R ${cfg.user}:${cfg.group} ${cfg.dataDir} - } + if [ -d ${cfg.dataDir} ] + then + for plugin in ${cfg.dataDir}/plugins/* + do + echo "Correcting permissions of plugin: $plugin" + chmod u+w $plugin + done + else + echo "Creating initial Emby data directory in ${cfg.dataDir}" + mkdir -p ${cfg.dataDir} + chown -R ${cfg.user}:${cfg.group} ${cfg.dataDir} + fi ''; serviceConfig = { @@ -48,7 +55,7 @@ in User = cfg.user; Group = cfg.group; PermissionsStartOnly = "true"; - ExecStart = "${pkgs.emby}/bin/MediaBrowser.Server.Mono"; + ExecStart = "${pkgs.emby}/bin/emby"; Restart = "on-failure"; }; }; diff --git a/nixos/modules/services/misc/gitea.nix b/nixos/modules/services/misc/gitea.nix index 5d664728e0b5..a222325579fe 100644 --- a/nixos/modules/services/misc/gitea.nix +++ b/nixos/modules/services/misc/gitea.nix @@ -261,7 +261,8 @@ in runConfig = "${cfg.stateDir}/custom/conf/app.ini"; secretKey = "${cfg.stateDir}/custom/conf/secret_key"; in '' - mkdir -p ${cfg.stateDir} + # Make sure that the stateDir exists, as well as the conf dir in there + mkdir -p ${cfg.stateDir}/conf # copy custom configuration and generate a random secret key if needed ${optionalString (cfg.useWizard == false) '' @@ -282,7 +283,7 @@ in mkdir -p ${cfg.repositoryRoot} # update all hooks' binary paths - HOOKS=$(find ${cfg.repositoryRoot} -mindepth 4 -maxdepth 5 -type f -wholename "*git/hooks/*") + HOOKS=$(find ${cfg.repositoryRoot} -mindepth 4 -maxdepth 6 -type f -wholename "*git/hooks/*") if [ "$HOOKS" ] then sed -ri 's,/nix/store/[a-z0-9.-]+/bin/gitea,${gitea.bin}/bin/gitea,g' $HOOKS @@ -290,11 +291,13 @@ in sed -ri 's,/nix/store/[a-z0-9.-]+/bin/bash,${pkgs.bash}/bin/bash,g' $HOOKS sed -ri 's,/nix/store/[a-z0-9.-]+/bin/perl,${pkgs.perl}/bin/perl,g' $HOOKS fi - if [ ! -d ${cfg.stateDir}/conf/locale ] + # If we have a folder or symlink with gitea locales, remove it + if [ -e ${cfg.stateDir}/conf/locale ] then - mkdir -p ${cfg.stateDir}/conf - cp -r ${gitea.out}/locale ${cfg.stateDir}/conf/locale + rm -r ${cfg.stateDir}/conf/locale fi + # And symlink the current gitea locales in place + ln -s ${gitea.out}/locale ${cfg.stateDir}/conf/locale # update command option in authorized_keys if [ -r ${cfg.stateDir}/.ssh/authorized_keys ] then diff --git a/nixos/modules/services/misc/gitit.nix b/nixos/modules/services/misc/gitit.nix index 0025d96bd37b..1ec030549f98 100644 --- a/nixos/modules/services/misc/gitit.nix +++ b/nixos/modules/services/misc/gitit.nix @@ -10,7 +10,7 @@ let toYesNo = b: if b then "yes" else "no"; - gititShared = with cfg.haskellPackages; gitit + "/share/" + pkgs.stdenv.system + "-" + ghc.name + "/" + gitit.pname + "-" + gitit.version; + gititShared = with cfg.haskellPackages; gitit + "/share/" + pkgs.stdenv.hostPlatform.system + "-" + ghc.name + "/" + gitit.pname + "-" + gitit.version; gititWithPkgs = hsPkgs: extras: hsPkgs.ghcWithPackages (self: with self; [ gitit ] ++ (extras self)); diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix index 5bf66354f487..d81aa5643e53 100644 --- a/nixos/modules/services/misc/gitlab.nix +++ b/nixos/modules/services/misc/gitlab.nix @@ -162,7 +162,7 @@ let makeWrapper ${cfg.packages.gitlab.rubyEnv}/bin/rake $out/bin/gitlab-rake \ ${concatStrings (mapAttrsToList (name: value: "--set ${name} '${value}' ") gitlabEnv)} \ --set GITLAB_CONFIG_PATH '${cfg.statePath}/config' \ - --set PATH '${lib.makeBinPath [ pkgs.nodejs pkgs.gzip pkgs.git pkgs.gnutar config.services.postgresql.package ]}:$PATH' \ + --set PATH '${lib.makeBinPath [ pkgs.nodejs pkgs.gzip pkgs.git pkgs.gnutar config.services.postgresql.package pkgs.coreutils pkgs.procps ]}:$PATH' \ --set RAKEOPT '-f ${cfg.packages.gitlab}/share/gitlab/Rakefile' \ --run 'cd ${cfg.packages.gitlab}/share/gitlab' ''; @@ -203,6 +203,7 @@ in { default = pkgs.gitlab; defaultText = "pkgs.gitlab"; description = "Reference to the gitlab package"; + example = "pkgs.gitlab-ee"; }; packages.gitlab-shell = mkOption { @@ -501,7 +502,7 @@ in { }; systemd.services.gitlab-workhorse = { - after = [ "network.target" "gitlab.service" ]; + after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; environment.HOME = gitlabEnv.HOME; environment.GITLAB_SHELL_CONFIG_PATH = gitlabEnv.GITLAB_SHELL_CONFIG_PATH; @@ -569,9 +570,9 @@ in { mkdir -p /run/gitlab mkdir -p ${cfg.statePath}/log - ln -sf ${cfg.statePath}/log /run/gitlab/log - ln -sf ${cfg.statePath}/tmp /run/gitlab/tmp - ln -sf ${cfg.statePath}/uploads /run/gitlab/uploads + [ -d /run/gitlab/log ] || ln -sf ${cfg.statePath}/log /run/gitlab/log + [ -d /run/gitlab/tmp ] || ln -sf ${cfg.statePath}/tmp /run/gitlab/tmp + [ -d /run/gitlab/uploads ] || ln -sf ${cfg.statePath}/uploads /run/gitlab/uploads ln -sf $GITLAB_SHELL_CONFIG_PATH /run/gitlab/shell-config.yml chown -R ${cfg.user}:${cfg.group} /run/gitlab @@ -629,6 +630,10 @@ in { touch "${cfg.statePath}/db-seeded" fi + # The gitlab:shell:setup regenerates the authorized_keys file so that + # the store path to the gitlab-shell in it gets updated + ${pkgs.sudo}/bin/sudo -u ${cfg.user} force=yes ${gitlab-rake}/bin/gitlab-rake gitlab:shell:setup RAILS_ENV=production + # The gitlab:shell:create_hooks task seems broken for fixing links # so we instead delete all the hooks and create them anew rm -f ${cfg.statePath}/repositories/**/*.git/hooks diff --git a/nixos/modules/services/misc/gitlab.xml b/nixos/modules/services/misc/gitlab.xml index 3306ba8e9b11..ab99d7bd3a60 100644 --- a/nixos/modules/services/misc/gitlab.xml +++ b/nixos/modules/services/misc/gitlab.xml @@ -3,20 +3,22 @@ xmlns:xi="http://www.w3.org/2001/XInclude" version="5.0" xml:id="module-services-gitlab"> - -<title>Gitlab</title> - -<para>Gitlab is a feature-rich git hosting service.</para> - -<section><title>Prerequisites</title> - -<para>The gitlab service exposes only an Unix socket at -<literal>/run/gitlab/gitlab-workhorse.socket</literal>. You need to configure a -webserver to proxy HTTP requests to the socket.</para> - -<para>For instance, the following configuration could be used to use nginx as - frontend proxy: - + <title>Gitlab</title> + <para> + Gitlab is a feature-rich git hosting service. + </para> + <section xml:id="module-services-gitlab-prerequisites"> + <title>Prerequisites</title> + + <para> + The gitlab service exposes only an Unix socket at + <literal>/run/gitlab/gitlab-workhorse.socket</literal>. You need to + configure a webserver to proxy HTTP requests to the socket. + </para> + + <para> + For instance, the following configuration could be used to use nginx as + frontend proxy: <programlisting> <link linkend="opt-services.nginx.enable">services.nginx</link> = { <link linkend="opt-services.nginx.enable">enable</link> = true; @@ -31,21 +33,24 @@ webserver to proxy HTTP requests to the socket.</para> }; }; </programlisting> -</para> - -</section> - -<section><title>Configuring</title> - -<para>Gitlab depends on both PostgreSQL and Redis and will automatically enable -both services. In the case of PostgreSQL, a database and a role will be created. -</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 with some custom settings could look like this: - + </para> + </section> + <section xml:id="module-services-gitlab-configuring"> + <title>Configuring</title> + + <para> + Gitlab depends on both PostgreSQL and Redis and will automatically enable + both services. In the case of PostgreSQL, a database and a role will be + created. + </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 with some custom settings could look like this: <programlisting> services.gitlab = { <link linkend="opt-services.gitlab.enable">enable</link> = true; @@ -105,40 +110,41 @@ services.gitlab = { }; }; </programlisting> -</para> - -<para>If you're setting up a new Gitlab instance, generate new secrets. You -for instance use <literal>tr -dc A-Za-z0-9 < /dev/urandom | head -c 128</literal> -to generate a new secret. Gitlab encrypts sensitive data stored in the database. -If you're restoring an existing Gitlab instance, you must specify the secrets -secret from <literal>config/secrets.yml</literal> located in your Gitlab state -folder.</para> - -<para>Refer to <xref linkend="ch-options" /> for all available configuration -options for the <link linkend="opt-services.gitlab.enable">services.gitlab</link> module.</para> - -</section> - -<section><title>Maintenance</title> - -<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 example, to backup a Gitlab instance: - + </para> + + <para> + If you're setting up a new Gitlab instance, generate new secrets. You for + instance use <literal>tr -dc A-Za-z0-9 < /dev/urandom | head -c + 128</literal> to generate a new secret. Gitlab encrypts sensitive data + stored in the database. If you're restoring an existing Gitlab instance, you + must specify the secrets secret from <literal>config/secrets.yml</literal> + located in your Gitlab state folder. + </para> + + <para> + Refer to <xref linkend="ch-options" /> for all available configuration + options for the + <link linkend="opt-services.gitlab.enable">services.gitlab</link> module. + </para> + </section> + <section xml:id="module-services-gitlab-maintenance"> + <title>Maintenance</title> + + <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 example, to backup a Gitlab instance: <programlisting> $ sudo -u git -H gitlab-rake gitlab:backup:create </programlisting> - -A list of all availabe rake tasks can be obtained by running: - + A list of all availabe rake tasks can be obtained by running: <programlisting> $ sudo -u git -H gitlab-rake -T </programlisting> -</para> - -</section> - + </para> + </section> </chapter> diff --git a/nixos/modules/services/misc/lidarr.nix b/nixos/modules/services/misc/lidarr.nix new file mode 100644 index 000000000000..627f22334fe8 --- /dev/null +++ b/nixos/modules/services/misc/lidarr.nix @@ -0,0 +1,46 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.lidarr; +in +{ + options = { + services.lidarr = { + enable = mkEnableOption "Lidarr"; + }; + }; + + config = mkIf cfg.enable { + systemd.services.lidarr = { + description = "Lidarr"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + preStart = '' + [ ! -d /var/lib/lidarr ] && mkdir -p /var/lib/lidarr + chown -R lidarr:lidarr /var/lib/lidarr + ''; + + serviceConfig = { + Type = "simple"; + User = "lidarr"; + Group = "lidarr"; + PermissionsStartOnly = "true"; + ExecStart = "${pkgs.lidarr}/bin/Lidarr"; + Restart = "on-failure"; + + StateDirectory = "/var/lib/lidarr/"; + StateDirectoryMode = "0770"; + }; + }; + + users.users.lidarr = { + uid = config.ids.uids.lidarr; + home = "/var/lib/lidarr"; + group = "lidarr"; + }; + + users.groups.lidarr.gid = config.ids.gids.lidarr; + }; +} diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix index 5ca879bf2664..24379ec27354 100644 --- a/nixos/modules/services/misc/nix-daemon.nix +++ b/nixos/modules/services/misc/nix-daemon.nix @@ -88,7 +88,7 @@ in }; maxJobs = mkOption { - type = types.int; + type = types.either types.int (types.enum ["auto"]); default = 1; example = 64; description = '' @@ -345,7 +345,6 @@ in type = types.listOf types.str; default = [ - "$HOME/.nix-defexpr/channels" "nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos" "nixos-config=/etc/nixos/configuration.nix" "/nix/var/nix/profiles/per-user/root/channels" @@ -436,7 +435,7 @@ in # Set up the environment variables for running Nix. environment.sessionVariables = cfg.envVars // - { NIX_PATH = concatStringsSep ":" cfg.nixPath; + { NIX_PATH = cfg.nixPath; }; environment.extraInit = optionalString (!isNix20) @@ -446,6 +445,10 @@ in if [ "$USER" != root -o ! -w /nix/var/nix/db ]; then export NIX_REMOTE=daemon fi + '' + '' + if [ -e "$HOME/.nix-defexpr/channels" ]; then + export NIX_PATH="$HOME/.nix-defexpr/channels''${NIX_PATH:+:$NIX_PATH}" + fi ''; nix.nrBuildUsers = mkDefault (lib.max 32 cfg.maxJobs); diff --git a/nixos/modules/services/misc/nixos-manual.nix b/nixos/modules/services/misc/nixos-manual.nix index 3916c3052e8b..df3e71c80dea 100644 --- a/nixos/modules/services/misc/nixos-manual.nix +++ b/nixos/modules/services/misc/nixos-manual.nix @@ -1,85 +1,21 @@ -# This module includes the NixOS man-pages in the system environment, -# and optionally starts a browser that shows the NixOS manual on one -# of the virtual consoles. The latter is useful for the installation +# This module optionally starts a browser that shows the NixOS manual +# on one of the virtual consoles which is useful for the installation # CD. -{ config, lib, pkgs, baseModules, ... }: +{ config, lib, pkgs, ... }: with lib; let - cfg = config.services.nixosManual; - - /* For the purpose of generating docs, evaluate options with each derivation - in `pkgs` (recursively) replaced by a fake with path "\${pkgs.attribute.path}". - It isn't perfect, but it seems to cover a vast majority of use cases. - Caveat: even if the package is reached by a different means, - the path above will be shown and not e.g. `${config.services.foo.package}`. */ - manual = import ../../../doc/manual rec { - inherit pkgs config; - version = config.system.nixos.release; - revision = "release-${version}"; - options = - let - scrubbedEval = evalModules { - modules = [ { nixpkgs.localSystem = config.nixpkgs.localSystem; } ] ++ baseModules; - args = (config._module.args) // { modules = [ ]; }; - specialArgs = { pkgs = scrubDerivations "pkgs" pkgs; }; - }; - scrubDerivations = namePrefix: pkgSet: mapAttrs - (name: value: - let wholeName = "${namePrefix}.${name}"; in - if isAttrs value then - scrubDerivations wholeName value - // (optionalAttrs (isDerivation value) { outPath = "\${${wholeName}}"; }) - else value - ) - pkgSet; - in scrubbedEval.options; - }; - - entry = "${manual.manual}/share/doc/nixos/index.html"; - - helpScript = pkgs.writeScriptBin "nixos-help" - '' - #! ${pkgs.runtimeShell} -e - browser="$BROWSER" - if [ -z "$browser" ]; then - browser="$(type -P xdg-open || true)" - if [ -z "$browser" ]; then - browser="$(type -P w3m || true)" - if [ -z "$browser" ]; then - echo "$0: unable to start a web browser; please set \$BROWSER" - exit 1 - fi - fi - fi - exec "$browser" ${entry} - ''; - - desktopItem = pkgs.makeDesktopItem { - name = "nixos-manual"; - desktopName = "NixOS Manual"; - genericName = "View NixOS documentation in a web browser"; - icon = "nix-snowflake"; - exec = "${helpScript}/bin/nixos-help"; - categories = "System"; - }; + cfgd = config.documentation; in { options = { - services.nixosManual.enable = mkOption { - type = types.bool; - default = true; - description = '' - Whether to build the NixOS manual pages. - ''; - }; - + # TODO(@oxij): rename this to `.enable` eventually. services.nixosManual.showManual = mkOption { type = types.bool; default = false; @@ -108,37 +44,30 @@ in }; - config = mkIf cfg.enable { - - system.build.manual = manual; - - environment.systemPackages = [] - ++ optionals config.services.xserver.enable [ desktopItem pkgs.nixos-icons ] - ++ optional config.documentation.man.enable manual.manpages - ++ optionals config.documentation.doc.enable [ manual.manual helpScript ]; - - boot.extraTTYs = mkIf cfg.showManual ["tty${toString cfg.ttyNumber}"]; - - systemd.services = optionalAttrs cfg.showManual - { "nixos-manual" = - { description = "NixOS Manual"; - wantedBy = [ "multi-user.target" ]; - serviceConfig = - { ExecStart = "${cfg.browser} ${entry}"; - StandardInput = "tty"; - StandardOutput = "tty"; - TTYPath = "/dev/tty${toString cfg.ttyNumber}"; - TTYReset = true; - TTYVTDisallocate = true; - Restart = "always"; - }; + config = mkMerge [ + (mkIf cfg.showManual { + assertions = singleton { + assertion = cfgd.enable && cfgd.nixos.enable; + message = "Can't enable `services.nixosManual.showManual` without `documentation.nixos.enable`"; + }; + }) + (mkIf (cfg.showManual && cfgd.enable && cfgd.nixos.enable) { + boot.extraTTYs = [ "tty${toString cfg.ttyNumber}" ]; + + systemd.services."nixos-manual" = { + description = "NixOS Manual"; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${cfg.browser} ${config.system.build.manual.manualHTMLIndex}"; + StandardInput = "tty"; + StandardOutput = "tty"; + TTYPath = "/dev/tty${toString cfg.ttyNumber}"; + TTYReset = true; + TTYVTDisallocate = true; + Restart = "always"; }; }; - - services.mingetty.helpLine = "\nRun `nixos-help` " - + lib.optionalString cfg.showManual "or press <Alt-F${toString cfg.ttyNumber}> " - + "for the NixOS manual."; - - }; + }) + ]; } diff --git a/nixos/modules/services/misc/redmine.nix b/nixos/modules/services/misc/redmine.nix index 9a9424449f80..f763ba21d0b2 100644 --- a/nixos/modules/services/misc/redmine.nix +++ b/nixos/modules/services/misc/redmine.nix @@ -1,121 +1,124 @@ { config, lib, pkgs, ... }: -# TODO: support non-postgresql - with lib; let cfg = config.services.redmine; - ruby = pkgs.ruby; + bundle = "${pkgs.redmine}/share/redmine/bin/bundle"; - databaseYml = '' + databaseYml = pkgs.writeText "database.yml" '' production: - adapter: postgresql - database: ${cfg.databaseName} - host: ${cfg.databaseHost} - password: ${cfg.databasePassword} - username: ${cfg.databaseUsername} - encoding: utf8 + adapter: ${cfg.database.type} + database: ${cfg.database.name} + host: ${cfg.database.host} + port: ${toString cfg.database.port} + username: ${cfg.database.user} + password: #dbpass# ''; - configurationYml = '' + configurationYml = pkgs.writeText "configuration.yml" '' default: - # Absolute path to the directory where attachments are stored. - # The default is the 'files' directory in your Redmine instance. - # Your Redmine instance needs to have write permission on this - # directory. - # Examples: - # attachments_storage_path: /var/redmine/files - # attachments_storage_path: D:/redmine/files - attachments_storage_path: ${cfg.stateDir}/files - - # Absolute path to the SCM commands errors (stderr) log file. - # The default is to log in the 'log' directory of your Redmine instance. - # Example: - # scm_stderr_log_file: /var/log/redmine_scm_stderr.log - scm_stderr_log_file: ${cfg.stateDir}/redmine_scm_stderr.log - - ${cfg.extraConfig} + scm_subversion_command: ${pkgs.subversion}/bin/svn + scm_mercurial_command: ${pkgs.mercurial}/bin/hg + scm_git_command: ${pkgs.gitAndTools.git}/bin/git + scm_cvs_command: ${pkgs.cvs}/bin/cvs + scm_bazaar_command: ${pkgs.bazaar}/bin/bzr + scm_darcs_command: ${pkgs.darcs}/bin/darcs + + ${cfg.extraConfig} ''; - unpackTheme = unpack "theme"; - unpackPlugin = unpack "plugin"; - unpack = id: (name: source: - pkgs.stdenv.mkDerivation { - name = "redmine-${id}-${name}"; - buildInputs = [ pkgs.unzip ]; - buildCommand = '' - mkdir -p $out - cd $out - unpackFile ${source} - ''; - }); - -in { +in +{ options = { services.redmine = { enable = mkOption { type = types.bool; default = false; - description = '' - Enable the redmine service. - ''; + description = "Enable the Redmine service."; }; - stateDir = mkOption { + user = mkOption { type = types.str; - default = "/var/redmine"; - description = "The state directory, logs and plugins are stored here"; - }; - - extraConfig = mkOption { - type = types.lines; - default = ""; - description = "Extra configuration in configuration.yml"; - }; - - themes = mkOption { - type = types.attrsOf types.path; - default = {}; - description = "Set of themes"; + default = "redmine"; + description = "User under which Redmine is ran."; }; - plugins = mkOption { - type = types.attrsOf types.path; - default = {}; - description = "Set of plugins"; + group = mkOption { + type = types.str; + default = "redmine"; + description = "Group under which Redmine is ran."; }; - #databaseType = mkOption { - # type = types.str; - # default = "postgresql"; - # description = "Type of database"; - #}; - - databaseHost = mkOption { + stateDir = mkOption { type = types.str; - default = "127.0.0.1"; - description = "Database hostname"; + default = "/var/lib/redmine"; + description = "The state directory, logs and plugins are stored here."; }; - databasePassword = mkOption { - type = types.str; + extraConfig = mkOption { + type = types.lines; default = ""; - description = "Database user password"; - }; + description = '' + Extra configuration in configuration.yml. - databaseName = mkOption { - type = types.str; - default = "redmine"; - description = "Database name"; + See https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration + ''; }; - databaseUsername = mkOption { - type = types.str; - default = "redmine"; - description = "Database user"; + database = { + type = mkOption { + type = types.enum [ "mysql2" "postgresql" ]; + example = "postgresql"; + default = "mysql2"; + description = "Database engine to use."; + }; + + host = mkOption { + type = types.str; + default = "127.0.0.1"; + description = "Database host address."; + }; + + port = mkOption { + type = types.int; + default = 3306; + description = "Database host port."; + }; + + name = mkOption { + type = types.str; + default = "redmine"; + description = "Database name."; + }; + + user = mkOption { + type = types.str; + default = "redmine"; + description = "Database user."; + }; + + password = mkOption { + type = types.str; + default = ""; + description = '' + The password corresponding to <option>database.user</option>. + Warning: this is stored in cleartext in the Nix store! + Use <option>database.passwordFile</option> instead. + ''; + }; + + passwordFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/run/keys/redmine-dbpassword"; + description = '' + A file containing the password corresponding to + <option>database.user</option>. + ''; + }; }; }; }; @@ -123,99 +126,106 @@ in { config = mkIf cfg.enable { assertions = [ - { assertion = cfg.databasePassword != ""; - message = "services.redmine.databasePassword must be set"; + { assertion = cfg.database.passwordFile != null || cfg.database.password != ""; + message = "either services.redmine.database.passwordFile or services.redmine.database.password must be set"; } ]; - users.users = [ - { name = "redmine"; - group = "redmine"; - uid = config.ids.uids.redmine; - } ]; - - users.groups = [ - { name = "redmine"; - gid = config.ids.gids.redmine; - } ]; + environment.systemPackages = [ pkgs.redmine ]; systemd.services.redmine = { - after = [ "network.target" "postgresql.service" ]; + after = [ "network.target" (if cfg.database.type == "mysql2" then "mysql.service" else "postgresql.service") ]; wantedBy = [ "multi-user.target" ]; + environment.HOME = "${pkgs.redmine}/share/redmine"; environment.RAILS_ENV = "production"; - environment.RAILS_ETC = "${cfg.stateDir}/config"; - environment.RAILS_LOG = "${cfg.stateDir}/log"; - environment.RAILS_VAR = "${cfg.stateDir}/var"; environment.RAILS_CACHE = "${cfg.stateDir}/cache"; - environment.RAILS_PLUGINS = "${cfg.stateDir}/plugins"; - environment.RAILS_PUBLIC = "${cfg.stateDir}/public"; - environment.RAILS_TMP = "${cfg.stateDir}/tmp"; - environment.SCHEMA = "${cfg.stateDir}/cache/schema.db"; - environment.HOME = "${pkgs.redmine}/share/redmine"; environment.REDMINE_LANG = "en"; - environment.GEM_HOME = "${pkgs.redmine}/share/redmine/vendor/bundle/ruby/1.9.1"; - environment.GEM_PATH = "${pkgs.bundler}/${pkgs.bundler.ruby.gemPath}"; + environment.SCHEMA = "${cfg.stateDir}/cache/schema.db"; path = with pkgs; [ imagemagickBig - subversion - mercurial - cvs - config.services.postgresql.package bazaar + cvs + darcs gitAndTools.git - # once we build binaries for darc enable it - #darcs + mercurial + subversion ]; preStart = '' - # TODO: use env vars - for i in plugins public/plugin_assets db files log config cache var/files tmp; do + # start with a fresh config directory every time + rm -rf ${cfg.stateDir}/config + cp -r ${pkgs.redmine}/share/redmine/config.dist ${cfg.stateDir}/config + + # create the basic state directory layout pkgs.redmine expects + mkdir -p /run/redmine + + for i in config files log plugins tmp; do mkdir -p ${cfg.stateDir}/$i + ln -fs ${cfg.stateDir}/$i /run/redmine/$i done - chown -R redmine:redmine ${cfg.stateDir} - chmod -R 755 ${cfg.stateDir} + # ensure cache directory exists for db:migrate command + mkdir -p ${cfg.stateDir}/cache - rm -rf ${cfg.stateDir}/public/* - cp -R ${pkgs.redmine}/share/redmine/public/* ${cfg.stateDir}/public/ - for theme in ${concatStringsSep " " (mapAttrsToList unpackTheme cfg.themes)}; do - ln -fs $theme/* ${cfg.stateDir}/public/themes/ - done + # link in the application configuration + ln -fs ${configurationYml} ${cfg.stateDir}/config/configuration.yml - rm -rf ${cfg.stateDir}/plugins/* - for plugin in ${concatStringsSep " " (mapAttrsToList unpackPlugin cfg.plugins)}; do - ln -fs $plugin/* ${cfg.stateDir}/plugins/''${plugin##*-redmine-plugin-} - done + chmod -R ug+rwX,o-rwx+x ${cfg.stateDir}/ - ln -fs ${pkgs.writeText "database.yml" databaseYml} ${cfg.stateDir}/config/database.yml - ln -fs ${pkgs.writeText "configuration.yml" configurationYml} ${cfg.stateDir}/config/configuration.yml + # handle database.passwordFile + DBPASS=$(head -n1 ${cfg.database.passwordFile}) + cp -f ${databaseYml} ${cfg.stateDir}/config/database.yml + sed -e "s,#dbpass#,$DBPASS,g" -i ${cfg.stateDir}/config/database.yml + chmod 440 ${cfg.stateDir}/config/database.yml - if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then - if ! test -e "${cfg.stateDir}/db-created"; then - psql postgres -c "CREATE ROLE redmine WITH LOGIN NOCREATEDB NOCREATEROLE ENCRYPTED PASSWORD '${cfg.databasePassword}'" - ${config.services.postgresql.package}/bin/createdb --owner redmine redmine || true - touch "${cfg.stateDir}/db-created" - fi + # generate a secret token if required + if ! test -e "${cfg.stateDir}/config/initializers/secret_token.rb"; then + ${bundle} exec rake generate_secret_token + chmod 440 ${cfg.stateDir}/config/initializers/secret_token.rb fi - cd ${pkgs.redmine}/share/redmine/ - ${ruby}/bin/rake db:migrate - ${ruby}/bin/rake redmine:plugins:migrate - ${ruby}/bin/rake redmine:load_default_data - ${ruby}/bin/rake generate_secret_token + # ensure everything is owned by ${cfg.user} + chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir} + + ${bundle} exec rake db:migrate + ${bundle} exec rake redmine:load_default_data ''; serviceConfig = { PermissionsStartOnly = true; # preStart must be run as root Type = "simple"; - User = "redmine"; - Group = "redmine"; + User = cfg.user; + Group = cfg.group; TimeoutSec = "300"; WorkingDirectory = "${pkgs.redmine}/share/redmine"; - ExecStart="${ruby}/bin/ruby ${pkgs.redmine}/share/redmine/script/rails server webrick -e production -P ${cfg.stateDir}/redmine.pid"; + ExecStart="${bundle} exec rails server webrick -e production -P ${cfg.stateDir}/redmine.pid"; }; }; + users.extraUsers = optionalAttrs (cfg.user == "redmine") (singleton + { name = "redmine"; + group = cfg.group; + home = cfg.stateDir; + createHome = true; + uid = config.ids.uids.redmine; + }); + + users.extraGroups = optionalAttrs (cfg.group == "redmine") (singleton + { name = "redmine"; + gid = config.ids.gids.redmine; + }); + + warnings = optional (cfg.database.password != "") + ''config.services.redmine.database.password will be stored as plaintext + in the Nix store. Use database.passwordFile instead.''; + + # Create database passwordFile default when password is configured. + services.redmine.database.passwordFile = + (mkDefault (toString (pkgs.writeTextFile { + name = "redmine-database-password"; + text = cfg.database.password; + }))); + }; } diff --git a/nixos/modules/services/misc/sickbeard.nix b/nixos/modules/services/misc/sickbeard.nix new file mode 100644 index 000000000000..5cfbbe516ae1 --- /dev/null +++ b/nixos/modules/services/misc/sickbeard.nix @@ -0,0 +1,92 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + name = "sickbeard"; + + cfg = config.services.sickbeard; + sickbeard = cfg.package; + +in +{ + + ###### interface + + options = { + services.sickbeard = { + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the sickbeard server."; + }; + package = mkOption { + type = types.package; + default = pkgs.sickbeard; + example = literalExample "pkgs.sickrage"; + description ='' + Enable <literal>pkgs.sickrage</literal> or <literal>pkgs.sickgear</literal> + as an alternative to SickBeard + ''; + }; + dataDir = mkOption { + type = types.path; + default = "/var/lib/${name}"; + description = "Path where to store data files."; + }; + configFile = mkOption { + type = types.path; + default = "${cfg.dataDir}/config.ini"; + description = "Path to config file."; + }; + port = mkOption { + type = types.ints.u16; + default = 8081; + description = "Port to bind to."; + }; + user = mkOption { + type = types.str; + default = name; + description = "User to run the service as"; + }; + group = mkOption { + type = types.str; + default = name; + description = "Group to run the service as"; + }; + }; + }; + + + ###### implementation + + config = mkIf cfg.enable { + + users.users = optionalAttrs (cfg.user == name) (singleton { + name = name; + uid = config.ids.uids.sickbeard; + group = cfg.group; + description = "sickbeard user"; + home = cfg.dataDir; + createHome = true; + }); + + users.groups = optionalAttrs (cfg.group == name) (singleton { + name = name; + gid = config.ids.gids.sickbeard; + }); + + systemd.services.sickbeard = { + description = "Sickbeard Server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + User = cfg.user; + Group = cfg.group; + ExecStart = "${sickbeard}/SickBeard.py --datadir ${cfg.dataDir} --config ${cfg.configFile} --port ${toString cfg.port}"; + }; + }; + }; +} diff --git a/nixos/modules/services/misc/synergy.nix b/nixos/modules/services/misc/synergy.nix index 7e8eadbe5f37..b89cb41ac3ad 100644 --- a/nixos/modules/services/misc/synergy.nix +++ b/nixos/modules/services/misc/synergy.nix @@ -83,20 +83,20 @@ in config = mkMerge [ (mkIf cfgC.enable { - systemd.services."synergy-client" = { - after = [ "network.target" ]; + systemd.user.services."synergy-client" = { + after = [ "network.target" "graphical-session.target" ]; description = "Synergy client"; - wantedBy = optional cfgC.autoStart "multi-user.target"; + wantedBy = optional cfgC.autoStart "graphical-session.target"; path = [ pkgs.synergy ]; serviceConfig.ExecStart = ''${pkgs.synergy}/bin/synergyc -f ${optionalString (cfgC.screenName != "") "-n ${cfgC.screenName}"} ${cfgC.serverAddress}''; serviceConfig.Restart = "on-failure"; }; }) (mkIf cfgS.enable { - systemd.services."synergy-server" = { - after = [ "network.target" ]; + systemd.user.services."synergy-server" = { + after = [ "network.target" "graphical-session.target" ]; description = "Synergy server"; - wantedBy = optional cfgS.autoStart "multi-user.target"; + wantedBy = optional cfgS.autoStart "graphical-session.target"; path = [ pkgs.synergy ]; serviceConfig.ExecStart = ''${pkgs.synergy}/bin/synergys -c ${cfgS.configFile} -f ${optionalString (cfgS.address != "") "-a ${cfgS.address}"} ${optionalString (cfgS.screenName != "") "-n ${cfgS.screenName}" }''; serviceConfig.Restart = "on-failure"; diff --git a/nixos/modules/services/misc/taskserver/doc.xml b/nixos/modules/services/misc/taskserver/doc.xml index 75493ac1394f..5eac8d9ef784 100644 --- a/nixos/modules/services/misc/taskserver/doc.xml +++ b/nixos/modules/services/misc/taskserver/doc.xml @@ -2,101 +2,93 @@ xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="module-taskserver"> - - <title>Taskserver</title> + <title>Taskserver</title> + <para> + Taskserver is the server component of + <link xlink:href="https://taskwarrior.org/">Taskwarrior</link>, a free and + open source todo list application. + </para> + <para> + <emphasis>Upstream documentation:</emphasis> + <link xlink:href="https://taskwarrior.org/docs/#taskd"/> + </para> + <section xml:id="module-services-taskserver-configuration"> + <title>Configuration</title> <para> - Taskserver is the server component of - <link xlink:href="https://taskwarrior.org/">Taskwarrior</link>, a free and - open source todo list application. + Taskserver does all of its authentication via TLS using client certificates, + so you either need to roll your own CA or purchase a certificate from a + known CA, which allows creation of client certificates. These certificates + are usually advertised as <quote>server certificates</quote>. </para> <para> - <emphasis>Upstream documentation:</emphasis> - <link xlink:href="https://taskwarrior.org/docs/#taskd"/> + So in order to make it easier to handle your own CA, there is a helper tool + called <command>nixos-taskserver</command> which manages the custom CA along + with Taskserver organisations, users and groups. </para> - <section> - <title>Configuration</title> - - <para> - Taskserver does all of its authentication via TLS using client - certificates, so you either need to roll your own CA or purchase a - certificate from a known CA, which allows creation of client - certificates. - - These certificates are usually advertised as - <quote>server certificates</quote>. - </para> - - <para> - So in order to make it easier to handle your own CA, there is a helper - tool called <command>nixos-taskserver</command> which manages the custom - CA along with Taskserver organisations, users and groups. - </para> - - <para> - While the client certificates in Taskserver only authenticate whether a - user is allowed to connect, every user has its own UUID which identifies - it as an entity. - </para> - - <para> - With <command>nixos-taskserver</command> the client certificate is created - along with the UUID of the user, so it handles all of the credentials - needed in order to setup the Taskwarrior client to work with a Taskserver. - </para> - </section> + <para> + While the client certificates in Taskserver only authenticate whether a user + is allowed to connect, every user has its own UUID which identifies it as an + entity. + </para> - <section> - <title>The nixos-taskserver tool</title> + <para> + With <command>nixos-taskserver</command> the client certificate is created + along with the UUID of the user, so it handles all of the credentials needed + in order to setup the Taskwarrior client to work with a Taskserver. + </para> + </section> + <section xml:id="module-services-taskserver-nixos-taskserver-tool"> + <title>The nixos-taskserver tool</title> - <para> - Because Taskserver by default only provides scripts to setup users - imperatively, the <command>nixos-taskserver</command> tool is used for - addition and deletion of organisations along with users and groups defined - by <xref linkend="opt-services.taskserver.organisations"/> and as well for - imperative set up. - </para> + <para> + Because Taskserver by default only provides scripts to setup users + imperatively, the <command>nixos-taskserver</command> tool is used for + addition and deletion of organisations along with users and groups defined + by <xref linkend="opt-services.taskserver.organisations"/> and as well for + imperative set up. + </para> - <para> - The tool is designed to not interfere if the command is used to manually - set up some organisations, users or groups. - </para> + <para> + The tool is designed to not interfere if the command is used to manually set + up some organisations, users or groups. + </para> - <para> - For example if you add a new organisation using - <command>nixos-taskserver org add foo</command>, the organisation is not - modified and deleted no matter what you define in - <option>services.taskserver.organisations</option>, even if you're adding - the same organisation in that option. - </para> + <para> + For example if you add a new organisation using <command>nixos-taskserver + org add foo</command>, the organisation is not modified and deleted no + matter what you define in + <option>services.taskserver.organisations</option>, even if you're adding + the same organisation in that option. + </para> - <para> - The tool is modelled to imitate the official <command>taskd</command> - command, documentation for each subcommand can be shown by using the - <option>--help</option> switch. - </para> - </section> - <section> - <title>Declarative/automatic CA management</title> + <para> + The tool is modelled to imitate the official <command>taskd</command> + command, documentation for each subcommand can be shown by using the + <option>--help</option> switch. + </para> + </section> + <section xml:id="module-services-taskserver-declarative-ca-management"> + <title>Declarative/automatic CA management</title> - <para> - Everything is done according to what you specify in the module options, - however in order to set up a Taskwarrior client for synchronisation with a - Taskserver instance, you have to transfer the keys and certificates to the - client machine. - </para> + <para> + Everything is done according to what you specify in the module options, + however in order to set up a Taskwarrior client for synchronisation with a + Taskserver instance, you have to transfer the keys and certificates to the + client machine. + </para> - <para> - This is done using - <command>nixos-taskserver user export $orgname $username</command> which - is printing a shell script fragment to stdout which can either be used - verbatim or adjusted to import the user on the client machine. - </para> + <para> + This is done using <command>nixos-taskserver user export $orgname + $username</command> which is printing a shell script fragment to stdout + which can either be used verbatim or adjusted to import the user on the + client machine. + </para> - <para> - For example, let's say you have the following configuration: + <para> + For example, let's say you have the following configuration: <screen> { <xref linkend="opt-services.taskserver.enable"/> = true; @@ -105,40 +97,39 @@ <link linkend="opt-services.taskserver.organisations._name_.users">services.taskserver.organisations.my-company.users</link> = [ "alice" ]; } </screen> - This creates an organisation called <literal>my-company</literal> with the - user <literal>alice</literal>. - </para> + This creates an organisation called <literal>my-company</literal> with the + user <literal>alice</literal>. + </para> - <para> - Now in order to import the <literal>alice</literal> user to another - machine <literal>alicebox</literal>, all we need to do is something like - this: + <para> + Now in order to import the <literal>alice</literal> user to another machine + <literal>alicebox</literal>, all we need to do is something like this: <screen> $ ssh server nixos-taskserver user export my-company alice | sh </screen> - Of course, if no SSH daemon is available on the server you can also copy - & paste it directly into a shell. - </para> + Of course, if no SSH daemon is available on the server you can also copy + & paste it directly into a shell. + </para> - <para> - After this step the user should be set up and you can start synchronising - your tasks for the first time with <command>task sync init</command> on - <literal>alicebox</literal>. - </para> + <para> + After this step the user should be set up and you can start synchronising + your tasks for the first time with <command>task sync init</command> on + <literal>alicebox</literal>. + </para> - <para> - Subsequent synchronisation requests merely require the command - <command>task sync</command> after that stage. - </para> - </section> - <section> - <title>Manual CA management</title> + <para> + Subsequent synchronisation requests merely require the command <command>task + sync</command> after that stage. + </para> + </section> + <section xml:id="module-services-taskserver-manual-ca-management"> + <title>Manual CA management</title> - <para> - If you set any options within - <link linkend="opt-services.taskserver.pki.manual.ca.cert">service.taskserver.pki.manual</link>.*, - <command>nixos-taskserver</command> won't issue certificates, but you can - still use it for adding or removing user accounts. - </para> - </section> + <para> + If you set any options within + <link linkend="opt-services.taskserver.pki.manual.ca.cert">service.taskserver.pki.manual</link>.*, + <command>nixos-taskserver</command> won't issue certificates, but you can + still use it for adding or removing user accounts. + </para> + </section> </chapter> diff --git a/nixos/modules/services/misc/weechat.nix b/nixos/modules/services/misc/weechat.nix new file mode 100644 index 000000000000..1fcfb440485d --- /dev/null +++ b/nixos/modules/services/misc/weechat.nix @@ -0,0 +1,56 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.weechat; +in + +{ + options.services.weechat = { + enable = mkEnableOption "weechat"; + root = mkOption { + description = "Weechat state directory."; + type = types.str; + default = "/var/lib/weechat"; + }; + sessionName = mkOption { + description = "Name of the `screen' session for weechat."; + default = "weechat-screen"; + type = types.str; + }; + binary = mkOption { + description = "Binary to execute (by default \${weechat}/bin/weechat)."; + example = literalExample '' + ''${pkgs.weechat}/bin/weechat-headless + ''; + default = "${pkgs.weechat}/bin/weechat"; + }; + }; + + config = mkIf cfg.enable { + users = { + groups.weechat = {}; + users.weechat = { + createHome = true; + group = "weechat"; + home = cfg.root; + isSystemUser = true; + }; + }; + + systemd.services.weechat = { + environment.WEECHAT_HOME = cfg.root; + serviceConfig = { + User = "weechat"; + Group = "weechat"; + RemainAfterExit = "yes"; + }; + script = "exec ${pkgs.screen}/bin/screen -Dm -S ${cfg.sessionName} ${cfg.binary}"; + wantedBy = [ "multi-user.target" ]; + wants = [ "network.target" ]; + }; + }; + + meta.doc = ./weechat.xml; +} diff --git a/nixos/modules/services/misc/weechat.xml b/nixos/modules/services/misc/weechat.xml new file mode 100644 index 000000000000..9c9ee0448c92 --- /dev/null +++ b/nixos/modules/services/misc/weechat.xml @@ -0,0 +1,66 @@ +<chapter 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="module-services-weechat"> + <title>WeeChat</title> + <para> + <link xlink:href="https://weechat.org/">WeeChat</link> is a fast and + extensible IRC client. + </para> + <section> + <title>Basic Usage</title> + + <para> + By default, the module creates a + <literal><link xlink:href="https://www.freedesktop.org/wiki/Software/systemd/">systemd</link></literal> + unit which runs the chat client in a detached + <literal><link xlink:href="https://www.gnu.org/software/screen/">screen</link></literal> + session. + </para> + + <para> + This can be done by enabling the <literal>weechat</literal> service: +<programlisting> +{ ... }: + +{ + <link linkend="opt-services.weechat.enable">services.weechat.enable</link> = true; +} +</programlisting> + </para> + + <para> + The service is managed by a dedicated user named <literal>weechat</literal> + in the state directory <literal>/var/lib/weechat</literal>. + </para> + </section> + <section> + <title>Re-attaching to WeeChat</title> + + <para> + WeeChat runs in a screen session owned by a dedicated user. To explicitly + allow your another user to attach to this session, the + <literal>screenrc</literal> needs to be tweaked by adding + <link xlink:href="https://www.gnu.org/software/screen/manual/html_node/Multiuser.html#Multiuser">multiuser</link> + support: +<programlisting> +{ + <link linkend="opt-programs.screen.screenrc">programs.screen.screenrc</link> = '' + multiuser on + acladd normal_user + ''; +} +</programlisting> + Now, the session can be re-attached like this: +<programlisting> +screen -r weechat-screen +</programlisting> + </para> + + <para> + <emphasis>The session name can be changed using + <link linkend="opt-services.weechat.sessionName">services.weechat.sessionName.</link></emphasis> + </para> + </section> +</chapter> |