Merge pull request #256 from oxij/shells-environment

I tested the previous "version" and found my environment to be exactly the same.

Let's start discussing possible extensions/improvements somewhere else. For now it's a nice improvement.
This commit is contained in:
Mathijs Kwik 2013-09-23 11:23:10 -07:00
commit 3840e96e79
22 changed files with 746 additions and 320 deletions

@ -46,13 +46,10 @@ with pkgs.lib;
</fontconfig> </fontconfig>
''; '';
environment.shellInit =
''
# FIXME: This variable is no longer needed, but we'll keep it # FIXME: This variable is no longer needed, but we'll keep it
# around for a while for applications linked against old # around for a while for applications linked against old
# fontconfig builds. # fontconfig builds.
export FONTCONFIG_FILE=/etc/fonts/fonts.conf environment.variables.FONTCONFIG_FILE.value = "/etc/fonts/fonts.conf";
'';
environment.systemPackages = [ pkgs.fontconfig ]; environment.systemPackages = [ pkgs.fontconfig ];

@ -69,10 +69,7 @@ in
environment.systemPackages = [ glibcLocales ]; environment.systemPackages = [ glibcLocales ];
environment.shellInit = environment.variables.LANG.value = config.i18n.defaultLocale;
''
export LANG=${config.i18n.defaultLocale}
'';
# /etc/locale.conf is used by systemd. # /etc/locale.conf is used by systemd.
environment.etc = singleton environment.etc = singleton

@ -0,0 +1,202 @@
# This module defines a global environment configuration and
# a common configuration for all shells.
{ config, pkgs, ... }:
with pkgs.lib;
let
cfg = config.environment;
environOpts = { name, config, ... }: {
options = {
value = mkOption {
example = "/foo/bin";
description =
''
Variable value.
Exactly one of this or <option>list</option> must be set.
'';
type = types.uniq types.string;
};
list = mkOption {
default = null;
example = [ "/foo/bin" "/bar/bin" ];
description =
''
Variable value.
Exactly one of this or <option>value</option> must be set.
'';
type = types.nullOr (types.listOf types.string);
};
};
config = {
value = mkIf (config.list != null)
(concatStringsSep ":" config.list);
};
};
in
{
options = {
environment.variables = mkOption {
default = {};
description = ''
A set of environment variables used in the global environment.
'';
type = types.attrsOf types.optionSet;
options = [ environOpts ];
};
environment.profiles = mkOption {
default = [];
description = ''
A list of profiles used to setup the global environment.
'';
type = types.listOf types.string;
};
environment.profileVariables = mkOption {
default = (p: {});
description = ''
A function which given a profile path should give back
a set of environment variables for that profile.
'';
# !!! this should be of the following type:
#type = types.functionTo (types.attrsOf (types.optionSet envVar));
# and envVar should be changed to something more like environOpts.
# Having unique `value' _or_ multiple `list' is much more useful
# than just sticking everything together with ':' unconditionally.
# Anyway, to have this type mentioned above
# types.optionSet needs to be transformed into a type constructor
# (it has a !!! mark on that in nixpkgs)
# for now we hack all this to be
type = types.functionTo (types.attrsOf (types.listOf types.string));
};
# !!! isn't there a better way?
environment.extraInit = mkOption {
default = "";
description = ''
Shell script code called during global environment initialisation
after all variables and profileVariables have been set.
This code is asumed to be shell-independent, which means you should
stick to pure sh without sh word split.
'';
type = types.lines;
};
environment.shellInit = mkOption {
default = "";
description = ''
Shell script code called during shell initialisation.
This code is asumed to be shell-independent, which means you should
stick to pure sh without sh word split.
'';
type = types.lines;
};
environment.loginShellInit = mkOption {
default = "";
description = ''
Shell script code called during login shell initialisation.
This code is asumed to be shell-independent, which means you should
stick to pure sh without sh word split.
'';
type = types.lines;
};
environment.interactiveShellInit = mkOption {
default = "";
description = ''
Shell script code called during interactive shell initialisation.
This code is asumed to be shell-independent, which means you should
stick to pure sh without sh word split.
'';
type = types.lines;
};
environment.shellAliases = mkOption {
default = {};
example = { ll = "ls -l"; };
description = ''
An attribute set that maps aliases (the top level attribute names in
this option) to command strings or directly to build outputs. The
aliases are added to all users' shells.
'';
type = types.attrs; # types.attrsOf types.stringOrPath;
};
environment.binsh = mkOption {
default = "${config.system.build.binsh}/bin/sh";
example = "\${pkgs.dash}/bin/dash";
type = with pkgs.lib.types; path;
description = ''
The shell executable that is linked system-wide to
<literal>/bin/sh</literal>. Please note that NixOS assumes all
over the place that shell to be Bash, so override the default
setting only if you know exactly what you're doing.
'';
};
environment.shells = mkOption {
default = [];
example = [ "/run/current-system/sw/bin/zsh" ];
description = ''
A list of permissible login shells for user accounts.
No need to mention <literal>/bin/sh</literal>
here, it is placed into this list implicitly.
'';
type = types.listOf types.path;
};
};
config = {
system.build.binsh = pkgs.bashInteractive;
environment.etc."shells".text =
''
${concatStringsSep "\n" cfg.shells}
/bin/sh
'';
environment.etc."environment".text =
''
${concatStringsSep "\n" (
(mapAttrsToList (n: v: ''export ${n}="${concatStringsSep ":" v}"'')
# This line is a kind of a hack because of !!! note above
(fold (mergeAttrsWithFunc concat) {} ([ (mapAttrs (n: v: [ v.value ]) cfg.variables) ] ++ map cfg.profileVariables cfg.profiles))))}
${cfg.extraInit}
# The setuid wrappers override other bin directories.
export PATH="${config.security.wrapperDir}:$PATH"
# ~/bin if it exists overrides other bin directories.
export PATH="$HOME/bin:$PATH"
'';
system.activationScripts.binsh = stringAfter [ "stdio" ]
''
# Create the required /bin/sh symlink; otherwise lots of things
# (notably the system() function) won't work.
mkdir -m 0755 -p /bin
ln -sfn "${cfg.binsh}" /bin/.sh.tmp
mv /bin/.sh.tmp /bin/sh # atomically replace /bin/sh
'';
};
}

@ -1,24 +0,0 @@
# This module creates /etc/shells, the file that defines the list of
# permissible login shells for user accounts.
{ config, pkgs, ... }:
with pkgs.lib;
{
config = {
environment.etc = singleton
{ target = "shells";
source = pkgs.writeText "shells"
''
/run/current-system/sw/bin/bash
/var/run/current-system/sw/bin/bash
/bin/sh
'';
};
};
}

@ -24,11 +24,8 @@ with pkgs.lib;
config = { config = {
environment.shellInit = environment.variables.TZDIR.value = "/etc/zoneinfo";
'' environment.variables.TZ.value = config.time.timeZone;
export TZDIR=/etc/zoneinfo
export TZ=${config.time.timeZone}
'';
environment.etc.localtime.source = "${pkgs.tzdata}/share/zoneinfo/${config.time.timeZone}"; environment.etc.localtime.source = "${pkgs.tzdata}/share/zoneinfo/${config.time.timeZone}";

@ -13,7 +13,7 @@
./config/nsswitch.nix ./config/nsswitch.nix
./config/power-management.nix ./config/power-management.nix
./config/pulseaudio.nix ./config/pulseaudio.nix
./config/shells.nix ./config/shells-environment.nix
./config/swap.nix ./config/swap.nix
./config/sysctl.nix ./config/sysctl.nix
./config/system-path.nix ./config/system-path.nix
@ -45,6 +45,7 @@
./programs/bash/bash.nix ./programs/bash/bash.nix
./programs/bash/command-not-found.nix ./programs/bash/command-not-found.nix
./programs/blcr.nix ./programs/blcr.nix
./programs/environment.nix
./programs/info.nix ./programs/info.nix
./programs/shadow.nix ./programs/shadow.nix
./programs/shell.nix ./programs/shell.nix
@ -52,6 +53,7 @@
./programs/ssmtp.nix ./programs/ssmtp.nix
./programs/venus.nix ./programs/venus.nix
./programs/wvdial.nix ./programs/wvdial.nix
./programs/zsh/zsh.nix
./rename.nix ./rename.nix
./security/apparmor.nix ./security/apparmor.nix
./security/apparmor-suid.nix ./security/apparmor-suid.nix

@ -50,9 +50,7 @@ with pkgs.lib;
# Tell the Nix evaluator to garbage collect more aggressively. # Tell the Nix evaluator to garbage collect more aggressively.
# This is desirable in memory-constrained environments that don't # This is desirable in memory-constrained environments that don't
# (yet) have swap set up. # (yet) have swap set up.
environment.shellInit = environment.variables.GC_INITIAL_HEAP_SIZE.value = "100000";
''
export GC_INITIAL_HEAP_SIZE=100000
'';
}; };
} }

@ -7,9 +7,11 @@ with pkgs.lib;
let let
cfg = config.environment; cfge = config.environment;
initBashCompletion = optionalString cfg.enableBashCompletion '' cfg = config.programs.bash;
bashCompletion = optionalString cfg.enableCompletion ''
# Check whether we're running a version of Bash that has support for # Check whether we're running a version of Bash that has support for
# programmable completion. If we do, enable all modules installed in # programmable completion. If we do, enable all modules installed in
# the system (and user profile). # the system (and user profile).
@ -27,7 +29,7 @@ let
fi fi
''; '';
shellAliases = concatStringsSep "\n" ( bashAliases = concatStringsSep "\n" (
mapAttrsFlatten (k: v: "alias ${k}='${v}'") cfg.shellAliases mapAttrsFlatten (k: v: "alias ${k}='${v}'") cfg.shellAliases
); );
@ -36,7 +38,55 @@ in
{ {
options = { options = {
environment.promptInit = mkOption { programs.bash = {
enable = mkOption {
default = true;
description = ''
Whenever to configure Bash as an interactive shell.
Note that this tries to make Bash the default
<option>users.defaultUserShell</option>,
which in turn means that you might need to explicitly
set this variable if you have another shell configured
with NixOS.
'';
type = types.bool;
};
shellAliases = mkOption {
default = config.environment.shellAliases // { which = "type -P"; };
description = ''
Set of aliases for bash shell. See <option>environment.shellAliases</option>
for an option format description.
'';
type = types.attrs; # types.attrsOf types.stringOrPath;
};
shellInit = mkOption {
default = "";
description = ''
Shell script code called during bash shell initialisation.
'';
type = types.lines;
};
loginShellInit = mkOption {
default = "";
description = ''
Shell script code called during login bash shell initialisation.
'';
type = types.lines;
};
interactiveShellInit = mkOption {
default = "";
description = ''
Shell script code called during interactive bash shell initialisation.
'';
type = types.lines;
};
promptInit = mkOption {
default = '' default = ''
# Provide a nice prompt. # Provide a nice prompt.
PROMPT_COLOR="1;31m" PROMPT_COLOR="1;31m"
@ -47,106 +97,113 @@ in
fi fi
''; '';
description = '' description = ''
Shell script code used to initialise the shell prompt. Shell script code used to initialise the bash prompt.
''; '';
type = types.lines; type = types.lines;
}; };
environment.shellInit = mkOption { enableCompletion = mkOption {
default = "";
example = ''export PATH=/godi/bin/:$PATH'';
description = ''
Shell script code called during login shell initialisation.
'';
type = types.lines;
};
environment.interactiveShellInit = mkOption {
default = "";
example = ''export PATH=/godi/bin/:$PATH'';
description = ''
Shell script code called during interactive shell initialisation.
'';
type = types.lines;
};
environment.enableBashCompletion = mkOption {
default = false; default = false;
description = "Enable Bash completion for all interactive shells."; description = ''
Enable Bash completion for all interactive bash shells.
'';
type = types.bool; type = types.bool;
}; };
environment.binsh = mkOption { };
default = "${config.system.build.binsh}/bin/sh";
example = "\${pkgs.dash}/bin/dash"; };
type = types.path;
description = '' config = mkIf cfg.enable {
Select the shell executable that is linked system-wide to
<literal>/bin/sh</literal>. Please note that NixOS assumes all programs.bash = {
over the place that shell to be Bash, so override the default
setting only if you know exactly what you're doing. shellInit = ''
. /etc/environment
${cfge.shellInit}
'';
loginShellInit = cfge.loginShellInit;
interactiveShellInit = ''
${cfge.interactiveShellInit}
# Check the window size after every command.
shopt -s checkwinsize
# Disable hashing (i.e. caching) of command lookups.
set +h
${cfg.promptInit}
${bashCompletion}
${bashAliases}
''; '';
};
}; };
environment.etc."profile".text =
''
# /etc/profile: DO NOT EDIT -- this file has been generated automatically.
# This file is read for login shells.
config = { # Only execute this file once per shell.
if [ -n "$__ETC_PROFILE_SOURCED" ]; then return; fi
__ETC_PROFILE_SOURCED=1
# Script executed when the shell starts as a login shell. if [ -z "$__BASH_SHELL_INIT_DONE" ]; then
environment.etc."profile".source = __BASH_SHELL_INIT_DONE=1
pkgs.substituteAll { ${cfg.shellInit}
src = ./profile.sh; fi
wrapperDir = config.security.wrapperDir;
inherit (cfg) shellInit;
};
# /etc/bashrc: executed every time an interactive bash ${cfg.loginShellInit}
# starts. Sources /etc/profile to ensure that the system
# environment is configured properly. # Read system-wide modifications.
environment.etc."bashrc".source = if test -f /etc/profile.local; then
pkgs.substituteAll { . /etc/profile.local
src = ./bashrc.sh; fi
inherit (cfg) interactiveShellInit;
}; if [ -n "''${BASH_VERSION:-}" ]; then
. /etc/bashrc
fi
'';
environment.etc."bashrc".text =
''
# /etc/bashrc: DO NOT EDIT -- this file has been generated automatically.
# Only execute this file once per shell.
if [ -n "$__ETC_BASHRC_SOURCED" -o -n "$NOSYSBASHRC" ]; then return; fi
__ETC_BASHRC_SOURCED=1
if [ -z "$__BASH_SHELL_INIT_DONE" ]; then
__BASH_SHELL_INIT_DONE=1
${cfg.shellInit}
fi
# We are not always an interactive shell.
if [ -n "$PS1" ]; then
${cfg.interactiveShellInit}
fi
# Read system-wide modifications.
if test -f /etc/bashrc.local; then
. /etc/bashrc.local
fi
'';
# Configuration for readline in bash. # Configuration for readline in bash.
environment.etc."inputrc".source = ./inputrc; environment.etc."inputrc".source = ./inputrc;
environment.shellAliases = users.defaultUserShell = mkDefault "/run/current-system/sw/bin/bash";
{ ls = "ls --color=tty";
ll = "ls -l";
l = "ls -alh";
which = "type -P";
};
environment.interactiveShellInit = environment.shells =
'' [ "/run/current-system/sw/bin/bash"
# Check the window size after every command. "/var/run/current-system/sw/bin/bash"
shopt -s checkwinsize "/run/current-system/sw/bin/sh"
"/var/run/current-system/sw/bin/sh"
${cfg.promptInit} "${pkgs.bashInteractive}/bin/bash"
${initBashCompletion} "${pkgs.bashInteractive}/bin/sh"
${shellAliases}
# Disable hashing (i.e. caching) of command lookups.
set +h
'';
system.build.binsh = pkgs.bashInteractive;
system.activationScripts.binsh = stringAfter [ "stdio" ]
''
# Create the required /bin/sh symlink; otherwise lots of things
# (notably the system() function) won't work.
mkdir -m 0755 -p /bin
ln -sfn "${cfg.binsh}" /bin/.sh.tmp
mv /bin/.sh.tmp /bin/sh # atomically replace /bin/sh
'';
environment.pathsToLink = optionals cfg.enableBashCompletion [
"/etc/bash_completion.d"
"/share/bash-completion"
]; ];
}; };

@ -1,19 +0,0 @@
# /etc/bashrc: DO NOT EDIT -- this file has been generated automatically.
# This file is read for interactive non-login shells.
# Only execute this file once per shell.
if [ -n "$__ETC_BASHRC_SOURCED" -o -n "$NOSYSBASHRC" ]; then return; fi
__ETC_BASHRC_SOURCED=1
# If the profile was not loaded in a parent process, source it. But
# otherwise don't do it because we don't want to clobber overridden
# values of $PATH, etc.
if [ -z "$__ETC_PROFILE_DONE" ]; then
. /etc/profile
fi
# We are not always an interactive shell.
if [ -z "$PS1" ]; then return; fi
@interactiveShellInit@

@ -23,7 +23,7 @@ in
{ {
environment.interactiveShellInit = programs.bash.interactiveShellInit =
'' ''
# This function is called whenever a command is not found. # This function is called whenever a command is not found.
command_not_found_handle() { command_not_found_handle() {

@ -1,119 +0,0 @@
# /etc/profile: DO NOT EDIT -- this file has been generated automatically.
# This file is read for (interactive) login shells. Any
# initialisation specific to interactive shells should be put in
# /etc/bashrc, which is sourced from here.
# Only execute this file once per shell.
if [ -n "$__ETC_PROFILE_SOURCED" ]; then return; fi
__ETC_PROFILE_SOURCED=1
# Prevent this file from being sourced by interactive non-login child shells.
export __ETC_PROFILE_DONE=1
# Initialise a bunch of environment variables.
export LOCALE_ARCHIVE=/run/current-system/sw/lib/locale/locale-archive
export LD_LIBRARY_PATH=/run/opengl-driver/lib:/run/opengl-driver-32/lib # !!! only set if needed
export NIXPKGS_CONFIG=/etc/nix/nixpkgs-config.nix
export NIX_PATH=/nix/var/nix/profiles/per-user/root/channels/nixos:nixpkgs=/etc/nixos/nixpkgs:nixos=/etc/nixos/nixos:nixos-config=/etc/nixos/configuration.nix:services=/etc/nixos/services
export PAGER="less -R"
export EDITOR=nano
export LOCATE_PATH=/var/cache/locatedb
# Include the various profiles in the appropriate environment variables.
export NIX_USER_PROFILE_DIR=/nix/var/nix/profiles/per-user/$USER
export NIX_PROFILES="/run/current-system/sw /nix/var/nix/profiles/default $HOME/.nix-profile"
unset PATH INFOPATH PKG_CONFIG_PATH PERL5LIB ALSA_PLUGIN_DIRS GST_PLUGIN_PATH KDEDIRS
unset QT_PLUGIN_PATH QTWEBKIT_PLUGIN_PATH STRIGI_PLUGIN_PATH XDG_CONFIG_DIRS XDG_DATA_DIRS
unset MOZ_PLUGIN_PATH TERMINFO_DIRS
for i in $NIX_PROFILES; do # !!! reverse
# We have to care not leaving an empty PATH element, because that means '.' to Linux
export PATH=$i/bin:$i/sbin:$i/lib/kde4/libexec${PATH:+:}$PATH
export INFOPATH=$i/info:$i/share/info${INFOPATH:+:}$INFOPATH
export PKG_CONFIG_PATH="$i/lib/pkgconfig${PKG_CONFIG_PATH:+:}$PKG_CONFIG_PATH"
# terminfo and reset TERM with new TERMINFO available
export TERMINFO_DIRS=$i/share/terminfo${TERMINFO_DIRS:+:}$TERMINFO_DIRS
export TERM=$TERM
export PERL5LIB="$i/lib/perl5/site_perl${PERL5LIB:+:}$PERL5LIB"
# ALSA plugins
export ALSA_PLUGIN_DIRS="$i/lib/alsa-lib${ALSA_PLUGIN_DIRS:+:}$ALSA_PLUGIN_DIRS"
# GStreamer.
export GST_PLUGIN_PATH="$i/lib/gstreamer-0.10${GST_PLUGIN_PATH:+:}$GST_PLUGIN_PATH"
# KDE/Gnome stuff.
export KDEDIRS=$i${KDEDIRS:+:}$KDEDIRS
export STRIGI_PLUGIN_PATH=$i/lib/strigi/${STRIGI_PLUGIN_PATH:+:}$STRIGI_PLUGIN_PATH
export QT_PLUGIN_PATH=$i/lib/qt4/plugins:$i/lib/kde4/plugins${QT_PLUGIN_PATH:+:}:$QT_PLUGIN_PATH
export QTWEBKIT_PLUGIN_PATH=$i/lib/mozilla/plugins/${QTWEBKIT_PLUGIN_PATH:+:}$QTWEBKIT_PLUGIN_PATH
export XDG_CONFIG_DIRS=$i/etc/xdg${XDG_CONFIG_DIRS:+:}$XDG_CONFIG_DIRS
export XDG_DATA_DIRS=$i/share${XDG_DATA_DIRS:+:}$XDG_DATA_DIRS
# Mozilla plugins.
export MOZ_PLUGIN_PATH=$i/lib/mozilla/plugins${MOZ_PLUGIN_PATH:+:}$MOZ_PLUGIN_PATH
# Search directory for Aspell dictionaries.
if [ -d "$i/lib/aspell" ]; then
export ASPELL_CONF="dict-dir $i/lib/aspell"
fi
done
# The setuid wrappers override other bin directories.
export PATH=@wrapperDir@:$PATH
# ~/bin if it exists overrides other bin directories.
export PATH=$HOME/bin:$PATH
# Set up the per-user profile.
mkdir -m 0755 -p $NIX_USER_PROFILE_DIR
if test "$(stat --printf '%u' $NIX_USER_PROFILE_DIR)" != "$(id -u)"; then
echo "WARNING: bad ownership on $NIX_USER_PROFILE_DIR" >&2
fi
if ! test -L $HOME/.nix-profile; then
echo "creating $HOME/.nix-profile" >&2
if test "$USER" != root; then
ln -s $NIX_USER_PROFILE_DIR/profile $HOME/.nix-profile
else
# Root installs in the system-wide profile by default.
ln -s /nix/var/nix/profiles/default $HOME/.nix-profile
fi
fi
# Subscribe the root user to the NixOS channel by default.
if [ "$USER" = root -a ! -e $HOME/.nix-channels ]; then
echo "http://nixos.org/channels/nixos-unstable nixos" > $HOME/.nix-channels
fi
# Create the per-user garbage collector roots directory.
NIX_USER_GCROOTS_DIR=/nix/var/nix/gcroots/per-user/$USER
mkdir -m 0755 -p $NIX_USER_GCROOTS_DIR
if test "$(stat --printf '%u' $NIX_USER_GCROOTS_DIR)" != "$(id -u)"; then
echo "WARNING: bad ownership on $NIX_USER_GCROOTS_DIR" >&2
fi
# Set up a default Nix expression from which to install stuff.
if [ ! -e $HOME/.nix-defexpr -o -L $HOME/.nix-defexpr ]; then
echo "creating $HOME/.nix-defexpr" >&2
rm -f $HOME/.nix-defexpr
mkdir $HOME/.nix-defexpr
if [ "$USER" != root ]; then
ln -s /nix/var/nix/profiles/per-user/root/channels $HOME/.nix-defexpr/channels_root
fi
fi
@shellInit@
# Read system-wide modifications.
if test -f /etc/profile.local; then
. /etc/profile.local
fi
if [ -n "${BASH_VERSION:-}" ]; then
. /etc/bashrc
fi

@ -0,0 +1,79 @@
# This module defines a standard configuration for NixOS global environment.
# Most of the stuff here should probably be moved elsewhere sometime.
{ config, pkgs, ... }:
with pkgs.lib;
let
cfg = config.environment;
in
{
config = {
environment.variables =
{ LOCALE_ARCHIVE.value = "/run/current-system/sw/lib/locale/locale-archive";
LOCATE_PATH.value = "/var/cache/locatedb";
NIXPKGS_CONFIG.value = "/etc/nix/nixpkgs-config.nix";
NIX_PATH.list =
[ "/nix/var/nix/profiles/per-user/root/channels/nixos"
"nixpkgs=/etc/nixos/nixpkgs"
"nixos=/etc/nixos/nixos"
"nixos-config=/etc/nixos/configuration.nix"
"services=/etc/nixos/services"
];
PAGER.value = "less -R";
EDITOR.value = "nano";
};
environment.profiles =
[ "$HOME/.nix-profile"
"/nix/var/nix/profiles/default"
"/run/current-system/sw"
];
# !!! fix environment.profileVariables definition and then move
# most of these elsewhere
environment.profileVariables = (i:
{ PATH = [ "${i}/bin" "${i}/sbin" "${i}/lib/kde4/libexec" ];
MANPATH = [ "${i}/man" "${i}/share/man" ];
INFOPATH = [ "${i}/info" "${i}/share/info" ];
PKG_CONFIG_PATH = [ "${i}/lib/pkgconfig" ];
TERMINFO_DIRS = [ "${i}/share/terminfo" ];
PERL5LIB = [ "${i}/lib/perl5/site_perl" ];
ALSA_PLUGIN_DIRS = [ "${i}/lib/alsa-lib" ];
GST_PLUGIN_PATH = [ "${i}/lib/gstreamer-0.10" ];
KDEDIRS = [ "${i}" ];
STRIGI_PLUGIN_PATH = [ "${i}/lib/strigi/" ];
QT_PLUGIN_PATH = [ "${i}/lib/qt4/plugins" "${i}/lib/kde4/plugins" ];
QTWEBKIT_PLUGIN_PATH = [ "${i}/lib/mozilla/plugins/" ];
GTK_PATH = [ "${i}/lib/gtk-2.0" ];
XDG_CONFIG_DIRS = [ "${i}/etc/xdg" ];
XDG_DATA_DIRS = [ "${i}/share" ];
MOZ_PLUGIN_PATH = [ "${i}/lib/mozilla/plugins" ];
});
environment.extraInit =
''
# reset TERM with new TERMINFO available (if any)
export TERM=$TERM
unset ASPELL_CONF
for i in ${concatStringsSep " " (reverseList cfg.profiles)} ; do
if [ -d "$i/lib/aspell" ]; then
export ASPELL_CONF="dict-dir $i/lib/aspell"
fi
done
export NIX_USER_PROFILE_DIR="/nix/var/nix/profiles/per-user/$USER"
export NIX_PROFILES="${concatStringsSep " " (reverseList cfg.profiles)}"
'';
};
}

@ -2,6 +2,8 @@
{ config, pkgs, ... }: { config, pkgs, ... }:
with pkgs.lib;
let let
loginDefs = loginDefs =
@ -39,7 +41,6 @@ in
options = { options = {
users.defaultUserShell = pkgs.lib.mkOption { users.defaultUserShell = pkgs.lib.mkOption {
default = "/run/current-system/sw/bin/bash";
description = '' description = ''
This option defines the default shell assigned to user This option defines the default shell assigned to user
accounts. This must not be a store path, since the path is accounts. This must not be a store path, since the path is
@ -47,6 +48,7 @@ in
Rather, it should be the path of a symlink that points to the Rather, it should be the path of a symlink that points to the
actual shell in the Nix store. actual shell in the Nix store.
''; '';
type = types.uniq types.path;
}; };
}; };

@ -1,25 +1,67 @@
# This module defines global configuration for the shells. # This module defines a standard configuration for NixOS shells.
{ config, pkgs, ... }: { config, pkgs, ... }:
with pkgs.lib; with pkgs.lib;
let
cfg = config.environment;
in
{ {
options = {
environment.shellAliases = mkOption {
type = types.attrs; # types.attrsOf types.stringOrPath;
default = {};
example = {
ll = "ls -lh";
};
description = ''
An attribute set that maps aliases (the top level attribute names in
this option) to command strings or directly to build outputs. The
aliases are added to all users' shells.
'';
};
};
config = { config = {
environment.shellAliases =
{ ls = "ls --color=tty";
ll = "ls -l";
l = "ls -alh";
}; };
environment.shellInit =
''
# Set up the per-user profile.
mkdir -m 0755 -p $NIX_USER_PROFILE_DIR
if test "$(stat --printf '%u' $NIX_USER_PROFILE_DIR)" != "$(id -u)"; then
echo "WARNING: bad ownership on $NIX_USER_PROFILE_DIR" >&2
fi
if ! test -L $HOME/.nix-profile; then
echo "creating $HOME/.nix-profile" >&2
if test "$USER" != root; then
ln -s $NIX_USER_PROFILE_DIR/profile $HOME/.nix-profile
else
# Root installs in the system-wide profile by default.
ln -s /nix/var/nix/profiles/default $HOME/.nix-profile
fi
fi
# Subscribe the root user to the NixOS channel by default.
if [ "$USER" = root -a ! -e $HOME/.nix-channels ]; then
echo "creating $HOME/.nix-channels with nixos-unstable subscription" >&2
echo "http://nixos.org/channels/nixos-unstable nixos" > $HOME/.nix-channels
fi
# Create the per-user garbage collector roots directory.
NIX_USER_GCROOTS_DIR=/nix/var/nix/gcroots/per-user/$USER
mkdir -m 0755 -p $NIX_USER_GCROOTS_DIR
if test "$(stat --printf '%u' $NIX_USER_GCROOTS_DIR)" != "$(id -u)"; then
echo "WARNING: bad ownership on $NIX_USER_GCROOTS_DIR" >&2
fi
# Set up a default Nix expression from which to install stuff.
if [ ! -e $HOME/.nix-defexpr -o -L $HOME/.nix-defexpr ]; then
echo "creating $HOME/.nix-defexpr" >&2
rm -f $HOME/.nix-defexpr
mkdir $HOME/.nix-defexpr
if [ "$USER" != root ]; then
ln -s /nix/var/nix/profiles/per-user/root/channels $HOME/.nix-defexpr/channels_root
fi
fi
'';
};
} }

@ -0,0 +1,42 @@
# Stolen from ArchWiki
# create a zkbd compatible hash;
# to add other keys to this hash, see: man 5 terminfo
typeset -A key
key[Home]=${terminfo[khome]}
key[End]=${terminfo[kend]}
key[Insert]=${terminfo[kich1]}
key[Delete]=${terminfo[kdch1]}
key[Up]=${terminfo[kcuu1]}
key[Down]=${terminfo[kcud1]}
key[Left]=${terminfo[kcub1]}
key[Right]=${terminfo[kcuf1]}
key[PageUp]=${terminfo[kpp]}
key[PageDown]=${terminfo[knp]}
# setup key accordingly
[[ -n "${key[Home]}" ]] && bindkey "${key[Home]}" beginning-of-line
[[ -n "${key[End]}" ]] && bindkey "${key[End]}" end-of-line
[[ -n "${key[Insert]}" ]] && bindkey "${key[Insert]}" overwrite-mode
[[ -n "${key[Delete]}" ]] && bindkey "${key[Delete]}" delete-char
[[ -n "${key[Up]}" ]] && bindkey "${key[Up]}" up-line-or-history
[[ -n "${key[Down]}" ]] && bindkey "${key[Down]}" down-line-or-history
[[ -n "${key[Left]}" ]] && bindkey "${key[Left]}" backward-char
[[ -n "${key[Right]}" ]] && bindkey "${key[Right]}" forward-char
[[ -n "${key[PageUp]}" ]] && bindkey "${key[PageUp]}" beginning-of-buffer-or-history
[[ -n "${key[PageDown]}" ]] && bindkey "${key[PageDown]}" end-of-buffer-or-history
# Finally, make sure the terminal is in application mode, when zle is
# active. Only then are the values from $terminfo valid.
if (( ${+terminfo[smkx]} )) && (( ${+terminfo[rmkx]} )); then
function zle-line-init () {
printf '%s' "${terminfo[smkx]}"
}
function zle-line-finish () {
printf '%s' "${terminfo[rmkx]}"
}
zle -N zle-line-init
zle -N zle-line-finish
fi

@ -0,0 +1,180 @@
# This module defines global configuration for the zshell.
{ config, pkgs, ... }:
with pkgs.lib;
let
cfge = config.environment;
cfg = config.programs.zsh;
zshAliases = concatStringsSep "\n" (
mapAttrsFlatten (k: v: "alias ${k}='${v}'") cfg.shellAliases
);
in
{
options = {
programs.zsh = {
enable = mkOption {
default = false;
description = ''
Whenever to configure Zsh as an interactive shell.
Note that this tries to make Zsh the default
<option>users.defaultUserShell</option>,
which in turn means that you might need to explicitly
set this variable if you have another shell configured
with NixOS.
'';
type = types.bool;
};
shellAliases = mkOption {
default = config.environment.shellAliases;
description = ''
Set of aliases for zsh shell. See <option>environment.shellAliases</option>
for an option format description.
'';
type = types.attrs; # types.attrsOf types.stringOrPath;
};
shellInit = mkOption {
default = "";
description = ''
Shell script code called during zsh shell initialisation.
'';
type = types.lines;
};
loginShellInit = mkOption {
default = "";
description = ''
Shell script code called during zsh login shell initialisation.
'';
type = types.lines;
};
interactiveShellInit = mkOption {
default = "";
description = ''
Shell script code called during interactive zsh shell initialisation.
'';
type = types.lines;
};
promptInit = mkOption {
default = ''
autoload -U promptinit && promptinit && prompt walters
'';
description = ''
Shell script code used to initialise the zsh prompt.
'';
type = types.lines;
};
};
};
config = mkIf cfg.enable {
programs.zsh = {
shellInit = ''
. /etc/environment
${cfge.shellInit}
'';
loginShellInit = cfge.loginShellInit;
interactiveShellInit = ''
${cfge.interactiveShellInit}
${cfg.promptInit}
${zshAliases}
# Some sane history defaults
export SAVEHIST=2000
export HISTSIZE=2000
export HISTFILE=$HOME/.zsh_history
setopt HIST_IGNORE_DUPS SHARE_HISTORY
'';
};
environment.etc."zshenv".text =
''
# /etc/zshenv: DO NOT EDIT -- this file has been generated automatically.
# This file is read for all shells.
# Only execute this file once per shell.
if [ -n "$__ETC_ZSHENV_SOURCED" ]; then return; fi
__ETC_ZSHENV_SOURCED=1
${cfg.shellInit}
# Read system-wide modifications.
if test -f /etc/zshenv.local; then
. /etc/zshenv.local
fi
'';
environment.etc."zprofile".text =
''
# /etc/zprofile: DO NOT EDIT -- this file has been generated automatically.
# This file is read for login shells.
# Only execute this file once per shell.
if [ -n "$__ETC_ZPROFILE_SOURCED" ]; then return; fi
__ETC_ZPROFILE_SOURCED=1
${cfg.loginShellInit}
# Read system-wide modifications.
if test -f /etc/zprofile.local; then
. /etc/zprofile.local
fi
'';
environment.etc."zshrc".text =
''
# /etc/zshrc: DO NOT EDIT -- this file has been generated automatically.
# This file is read for interactive shells.
# Only execute this file once per shell.
if [ -n "$__ETC_ZSHRC_SOURCED" -o -n "$NOSYSZSHRC" ]; then return; fi
__ETC_ZSHRC_SOURCED=1
. /etc/zinputrc
${cfg.interactiveShellInit}
# Read system-wide modifications.
if test -f /etc/zshrc.local; then
. /etc/zshrc.local
fi
'';
environment.etc."zinputrc".source = ./zinputrc;
environment.systemPackages = [ pkgs.zsh ];
users.defaultUserShell = mkDefault "/run/current-system/sw/bin/zsh";
environment.shells =
[ "/run/current-system/sw/bin/zsh"
"/var/run/current-system/sw/bin/zsh"
"${pkgs.zsh}/bin/zsh"
];
};
}

@ -66,6 +66,7 @@ in zipModules ([]
# usage example: # usage example:
# ++ rename alias "services.xserver.slim.theme" "services.xserver.displayManager.slim.theme" # ++ rename alias "services.xserver.slim.theme" "services.xserver.displayManager.slim.theme"
++ rename obsolete "environment.extraPackages" "environment.systemPackages" ++ rename obsolete "environment.extraPackages" "environment.systemPackages"
++ rename obsolete "environment.enableBashCompletion" "programs.bash.enableCompletion"
++ rename obsolete "security.extraSetuidPrograms" "security.setuidPrograms" ++ rename obsolete "security.extraSetuidPrograms" "security.setuidPrograms"
++ rename obsolete "networking.enableWLAN" "networking.wireless.enable" ++ rename obsolete "networking.enableWLAN" "networking.wireless.enable"

@ -17,13 +17,9 @@ with pkgs.lib;
} }
]; ];
environment.shellInit = environment.variables.OPENSSL_X509_CERT_FILE.value = "/etc/ssl/certs/ca-bundle.crt";
'' environment.variables.CURL_CA_BUNDLE.value = "/etc/ssl/certs/ca-bundle.crt";
export OPENSSL_X509_CERT_FILE=/etc/ssl/certs/ca-bundle.crt environment.variables.GIT_SSL_CAINFO.value = "/etc/ssl/certs/ca-bundle.crt";
export CURL_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt
export GIT_SSL_CAINFO=/etc/ssl/certs/ca-bundle.crt
'';
}; };

@ -198,8 +198,7 @@ in
example = "http://127.0.0.1:3128"; example = "http://127.0.0.1:3128";
}; };
# Environment variables for running Nix. !!! Misnomer - it's # Environment variables for running Nix.
# actually a shell script.
envVars = mkOption { envVars = mkOption {
internal = true; internal = true;
default = {}; default = {};
@ -328,11 +327,11 @@ in
ftp_proxy = cfg.proxy; ftp_proxy = cfg.proxy;
}; };
environment.shellInit =
''
# Set up the environment variables for running Nix. # Set up the environment variables for running Nix.
${concatMapStrings (n: "export ${n}=\"${getAttr n cfg.envVars}\"\n") (attrNames cfg.envVars)} environment.variables = mapAttrs (n: v: { value = v; }) cfg.envVars;
environment.extraInit =
''
# Set up secure multi-user builds: non-root users build through the # Set up secure multi-user builds: non-root users build through the
# Nix daemon. # Nix daemon.
if test "$USER" != root; then if test "$USER" != root; then

@ -79,10 +79,7 @@ in
environment.pathsToLink = environment.pathsToLink =
[ "/share/xfce4" "/share/themes" "/share/mime" "/share/desktop-directories" "/share/gtksourceview-2.0" ]; [ "/share/xfce4" "/share/themes" "/share/mime" "/share/desktop-directories" "/share/gtksourceview-2.0" ];
environment.shellInit = environment.variables.GIO_EXTRA_MODULES.value = "${pkgs.xfce.gvfs}/lib/gio/modules";
''
export GIO_EXTRA_MODULES=${pkgs.xfce.gvfs}/lib/gio/modules
'';
# Enable helpful DBus services. # Enable helpful DBus services.
services.udisks2.enable = true; services.udisks2.enable = true;

@ -409,6 +409,9 @@ in
boot.blacklistedKernelModules = boot.blacklistedKernelModules =
optionals (elem "nvidia" driverNames) [ "nouveau" "nvidiafb" ]; optionals (elem "nvidia" driverNames) [ "nouveau" "nvidiafb" ];
environment.variables.LD_LIBRARY_PATH.list =
[ "/run/opengl-driver/lib" "/run/opengl-driver-32/lib" ];
environment.etc = environment.etc =
(optionals cfg.exportConfiguration (optionals cfg.exportConfiguration
[ { source = "${configFile}"; [ { source = "${configFile}";

@ -105,10 +105,7 @@ with pkgs.lib;
echo ${config.system.sbin.modprobe}/sbin/modprobe > /proc/sys/kernel/modprobe echo ${config.system.sbin.modprobe}/sbin/modprobe > /proc/sys/kernel/modprobe
''; '';
environment.shellInit = environment.variables.MODULE_DIR.value = "/run/current-system/kernel-modules/lib/modules";
''
export MODULE_DIR=/run/current-system/kernel-modules/lib/modules
'';
}; };