Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jack Cummings 2012-10-19 22:12:25 -07:00
commit d1bafd9e7f
14 changed files with 463 additions and 105 deletions

View File

@ -31,6 +31,7 @@ rec {
inherit pkgs modules baseModules;
modulesPath = ../modules;
pkgs_i686 = import <nixpkgs> { system = "i686-linux"; };
utils = {}; # forward compatibility
};
# Import Nixpkgs, allowing the NixOS option nixpkgs.config to

View File

@ -18,13 +18,6 @@ let
};
localhostWithDomain = optionalString (cfg.domain != "")
"localhost.${cfg.domain}";
hostnameWithDomain = optionalString
(cfg.domain != "" && cfg.hostName != "")
"${cfg.hostName}.${cfg.domain}";
in
{
@ -49,9 +42,8 @@ in
{ # /etc/hosts: Hostname-to-IP mappings.
source = pkgs.writeText "hosts"
''
${optionalString (cfg.hostName != "")
"127.0.0.1 ${hostnameWithDomain} ${cfg.hostName}"}
127.0.0.1 localhost ${localhostWithDomain}
127.0.0.1 localhost
::1 localhost
${cfg.extraHosts}
'';
target = "hosts";

View File

@ -1,11 +0,0 @@
# NSS configuration files with mDNS enabled (requires running Avahi daemon).
passwd: ldap files
group: ldap files
shadow: ldap files
hosts: files mdns_minimal [NOTFOUND=return] dns mdns
networks: files dns
services: files
protocols: files

View File

@ -1,10 +0,0 @@
passwd: files ldap
group: files ldap
shadow: files ldap
hosts: files dns
networks: files dns
ethers: files
services: files
protocols: files

View File

@ -1,13 +1,15 @@
# Configuration for the Name Service Switch (/etc/nsswitch.conf).
{config, pkgs, ...}:
{ config, pkgs, ... }:
with pkgs.lib;
let
options = {
# NSS modules. Hacky!
system.nssModules = pkgs.lib.mkOption {
system.nssModules = mkOption {
internal = true;
default = [];
description = "
@ -15,48 +17,49 @@ let
several DNS resolution methods to be specified via
<filename>/etc/nsswitch.conf</filename>.
";
merge = pkgs.lib.mergeListOption;
merge = mergeListOption;
apply = list:
let
list2 =
list
# !!! this should be in the LDAP module
++ pkgs.lib.optional config.users.ldap.enable pkgs.nss_ldap;
++ optional config.users.ldap.enable pkgs.nss_ldap;
in {
list = list2;
path = pkgs.lib.makeLibraryPath list2;
path = makeLibraryPath list2;
};
};
};
inherit (config.services.avahi) nssmdns;
in
{
require = [options];
require = [ options ];
environment.etc =
[ # Name Service Switch configuration file. Required by the C library.
# !!! Factor out the mdns stuff. The avahi module should define
# an option used by this module.
{ source =
if config.services.avahi.nssmdns
then ./nsswitch-mdns.conf
else ./nsswitch.conf;
{ source = pkgs.writeText "nsswitch.conf"
''
passwd: files ldap
group: files ldap
shadow: files ldap
hosts: files ${optionalString nssmdns "mdns_minimal [NOTFOUND=return]"} dns ${optionalString nssmdns "mdns"} myhostname
networks: files dns
ethers: files
services: files
protocols: files
'';
target = "nsswitch.conf";
}
];
environment.shellInit =
if config.system.nssModules.path != "" then
''
LD_LIBRARY_PATH=${config.system.nssModules.path}:$LD_LIBRARY_PATH
''
else "";
# NSS modules need to be in `systemPath' so that (i) the builder
# chroot gets to seem them, and (ii) applications can benefit from
# changes in the list of NSS modules at run-time, without requiring
# a reboot.
environment.systemPackages = [config.system.nssModules.list];
# Use nss-myhostname to ensure that our hostname always resolves to
# a valid IP address. It returns all locally configured IP
# addresses, or ::1 and 127.0.0.2 as fallbacks.
system.nssModules = [ pkgs.nss_myhostname ];
}

View File

@ -129,6 +129,7 @@
./services/networking/gnunet.nix
./services/networking/gogoclient.nix
./services/networking/gvpe.nix
./services/networking/hostapd.nix
./services/networking/ifplugd.nix
./services/networking/ircd-hybrid/default.nix
./services/networking/nat.nix

View File

@ -7,6 +7,25 @@ with pkgs.lib;
let
initBashCompletion = optionalString config.environment.enableBashCompletion ''
# Check whether we're running a version of Bash that has support for
# programmable completion. If we do, enable all modules installed in
# the system (and user profile).
if shopt -q progcomp &>/dev/null; then
. "${pkgs.bashCompletion}/etc/profile.d/bash_completion.sh"
nullglobStatus=$(shopt -p nullglob)
shopt -s nullglob
for p in $NIX_PROFILES; do
for m in "$p/etc/bash_completion.d/"*; do
. $m
done
done
eval "$nullglobStatus"
unset nullglobStatus p m
fi
'';
options = {
environment.shellInit = mkOption {
@ -18,6 +37,12 @@ let
type = with pkgs.lib.types; string;
};
environment.enableBashCompletion = mkOption {
default = false;
description = "Enable bash-completion for all interactive shells.";
type = with pkgs.lib.types; bool;
};
};
in
@ -38,7 +63,10 @@ in
{ # /etc/bashrc: executed every time a bash starts. Sources
# /etc/profile to ensure that the system environment is
# configured properly.
source = ./bashrc.sh;
source = pkgs.substituteAll {
src = ./bashrc.sh;
inherit initBashCompletion;
};
target = "bashrc";
}
@ -59,4 +87,5 @@ in
mv /bin/.sh.tmp /bin/sh # atomically replace /bin/sh
'';
environment.pathsToLink = optional config.environment.enableBashCompletion "/etc/bash_completion.d";
}

View File

@ -27,15 +27,7 @@ if test "$TERM" = "xterm"; then
PS1="\[\033]2;\h:\u:\w\007\]$PS1"
fi
# Check whether we're running a version of Bash that has support for
# programmable completion. If we do, and if the current user has
# installed the package 'bash-completion' in her $HOME/.nix-profile,
# then completion is enabled automatically.
if [ -f "$HOME/.nix-profile/etc/profile.d/bash_completion.sh" ]; then
if shopt -q progcomp &>/dev/null; then
. "$HOME/.nix-profile/etc/profile.d/bash_completion.sh"
fi
fi
@initBashCompletion@
# Some aliases.
alias ls="ls --color=tty"

View File

@ -5,16 +5,13 @@ with pkgs.lib;
let
cfg = config.services.logcheck;
rulesDir = pkgs.runCommand "logcheck-rules-dir"
{} (
''
mkdir $out
cp -prd ${pkgs.logcheck}/etc/logcheck/* $out/
rm $out/logcheck.*
chmod u+w $out/*
'' + optionalString (! builtins.isNull cfg.extraRulesDir) ''
cp -prd ${cfg.extraRulesDir}/* $out/
'' );
defaultRules = pkgs.runCommand "logcheck-default-rules" {} ''
cp -prd ${pkgs.logcheck}/etc/logcheck $out
chmod u+w $out
rm $out/logcheck.*
'';
rulesDir = pkgs.symlinkJoin "logcheck-rules-dir" ([ defaultRules ] ++ cfg.extraRulesDirs);
configFile = pkgs.writeText "logcheck.conf" cfg.config;
@ -33,6 +30,74 @@ let
2 ${cfg.timeOfDay} * * * logcheck env PATH=/var/setuid-wrappers:$PATH nice -n10 ${pkgs.logcheck}/sbin/logcheck ${flags}
'';
writeIgnoreRule = name: {level, regex, ...}:
pkgs.writeTextFile
{ inherit name;
destination = "/ignore.d.${level}/${name}";
text = ''
^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ ${regex}
'';
};
writeIgnoreCronRule = name: {level, user, regex, cmdline, ...}:
let escapeRegex = escape (stringToCharacters "\\[]{}()^$?*+|.");
cmdline_ = builtins.unsafeDiscardStringContext cmdline;
re = if regex != "" then regex else if cmdline_ == "" then ".*" else escapeRegex cmdline_;
in writeIgnoreRule "cron-${name}" {
inherit level;
regex = ''
(/usr/bin/)?cron\[[0-9]+\]: \(${user}\) CMD \(${re}\)$
'';
};
levelOption = mkOption {
default = "server";
type = types.uniq types.string;
description = ''
Set the logcheck level. Either "workstation", "server", or "paranoid".
'';
};
ignoreOptions = {
level = levelOption;
regex = mkOption {
default = "";
type = types.uniq types.string;
description = ''
Regex specifying which log lines to ignore.
'';
};
};
ignoreCronOptions = {
user = mkOption {
default = "root";
type = types.uniq types.string;
description = ''
User that runs the cronjob.
'';
};
cmdline = mkOption {
default = "";
type = types.uniq types.string;
description = ''
Command line for the cron job. Will be turned into a regex for the logcheck ignore rule.
'';
};
timeArgs = mkOption {
default = null;
type = types.nullOr (types.uniq types.string);
example = "02 06 * * *";
description = ''
"min hr dom mon dow" crontab time args, to auto-create a cronjob too.
Leave at null to not do this and just add a logcheck ignore rule.
'';
};
};
in
{
options = {
@ -98,16 +163,33 @@ in
'';
};
extraRulesDir = mkOption {
default = null;
extraRulesDirs = mkOption {
default = [];
example = "/etc/logcheck";
type = types.nullOr types.path;
type = types.listOf types.path;
description = ''
Directory with extra rules.
Will be merged with bundled rules, so it's possible to override certain behaviour.
Directories with extra rules.
'';
};
ignore = mkOption {
default = {};
description = ''
This option defines extra ignore rules.
'';
type = types.loaOf types.optionSet;
options = [ ignoreOptions ];
};
ignoreCron = mkOption {
default = {};
description = ''
This option defines extra ignore rules for cronjobs.
'';
type = types.loaOf types.optionSet;
options = [ ignoreOptions ignoreCronOptions ];
};
extraGroups = mkOption {
default = [];
type = types.listOf types.string;
@ -122,6 +204,10 @@ in
};
config = mkIf cfg.enable {
services.logcheck.extraRulesDirs =
mapAttrsToList writeIgnoreRule cfg.ignore
++ mapAttrsToList writeIgnoreCronRule cfg.ignoreCron;
users.extraUsers = singleton
{ name = cfg.user;
shell = "/bin/sh";
@ -134,6 +220,12 @@ in
chown ${cfg.user} /var/{lib,lock}/logcheck
'';
services.cron.systemCronJobs = [ cronJob ];
services.cron.systemCronJobs =
let withTime = name: {timeArgs, ...}: ! (builtins.isNull timeArgs);
mkCron = name: {user, cmdline, timeArgs, ...}: ''
${timeArgs} ${user} ${cmdline}
'';
in mapAttrsToList mkCron (filterAttrs withTime cfg.ignoreCron)
++ [ cronJob ];
};
}

View File

@ -24,7 +24,7 @@ let
smartdConf = pkgs.writeText "smartd.conf" (concatMapStrings (device:
''
${device} -a -m root -M exec ${smartdMail}
${device} -a -m root -M exec ${smartdMail} ${cfg.deviceOpts}
''
) cfg.devices);
@ -50,6 +50,17 @@ in
'';
};
deviceOpts = mkOption {
default = "";
type = types.string;
example = "-o on -s (S/../.././02|L/../../7/04)";
description = ''
Additional options for each device that is monitored. The example
turns on SMART Automatic Offline Testing on startup, and schedules short
self-tests daily, and long self-tests weekly.
'';
};
devices = mkOption {
default = [];
example = ["/dev/sda" "/dev/sdb"];

View File

@ -39,6 +39,15 @@ let
}
'';
kernelPackages = config.boot.kernelPackages;
kernelHasRPFilter = kernelPackages.kernel ? features
&& kernelPackages.kernel.features ? netfilterRPFilter
&& kernelPackages.kernel.features.netfilterRPFilter;
kernelCanDisableHelpers = kernelPackages.kernel ? features
&& kernelPackages.kernel.features ? canDisableNetfilterConntrackHelpers
&& kernelPackages.kernel.features.canDisableNetfilterConntrackHelpers;
in
{
@ -140,6 +149,53 @@ in
'';
};
networking.firewall.checkReversePath = mkOption {
default = kernelHasRPFilter;
type = types.bool;
description =
''
Performs a reverse path filter test on a packet.
If a reply to the packet would not be sent via the same interface
that the packet arrived on, it is refused.
If using asymmetric routing or other complicated routing,
disable this setting and setup your own counter-measures.
(needs kernel 3.3+)
'';
};
networking.firewall.connectionTrackingModules = mkOption {
default = [ "ftp" ];
example = [ "ftp" "irc" "sane" "sip" "tftp" "amanda" "h323" "netbios_sn" "pptp" "snmp" ];
type = types.list types.string;
description =
''
List of connection-tracking helpers that are auto-loaded.
The complete list of possible values is given in the example.
As helpers can pose as a security risk, it is adviced to
set this to an empty list and disable the setting
networking.firewall.autoLoadConntrackHelpers
Loading of helpers is recommended to be done through the new
CT target. More info:
https://home.regit.org/netfilter-en/secure-use-of-helpers/
'';
};
networking.firewall.autoLoadConntrackHelpers = mkOption {
default = true;
type = types.bool;
description =
''
Whether to auto-load connection-tracking helpers.
See the description at networking.firewall.connectionTrackingModules
(needs kernel 3.5+)
'';
};
networking.firewall.extraCommands = mkOption {
default = "";
example = "iptables -A INPUT -p icmp -j ACCEPT";
@ -168,7 +224,16 @@ in
environment.systemPackages = [ pkgs.iptables ];
boot.kernelModules = [ "nf_conntrack_ftp" ];
boot.kernelModules = map (x: "nf_conntrack_${x}") cfg.connectionTrackingModules;
boot.extraModprobeConfig = optionalString (!cfg.autoLoadConntrackHelpers) ''
options nf_conntrack nf_conntrack_helper=0
'';
assertions = [ { assertion = ! cfg.checkReversePath || kernelHasRPFilter;
message = "This kernel does not support rpfilter"; }
{ assertion = cfg.autoLoadConntrackHelpers || kernelCanDisableHelpers;
message = "This kernel does not support disabling conntrack helpers"; }
];
jobs.firewall =
{ startOn = "started network-interfaces";
@ -233,6 +298,12 @@ in
# The "nixos-fw" chain does the actual work.
ip46tables -N nixos-fw
# Perform a reverse-path test to refuse spoofers
# For now, we just drop, as the raw table doesn't have a log-refuse yet
${optionalString (kernelHasRPFilter && cfg.checkReversePath) ''
ip46tables -A PREROUTING -t raw -m rpfilter --invert -j DROP
''}
# Accept all traffic on the trusted interfaces.
${flip concatMapStrings cfg.trustedInterfaces (iface: ''
ip46tables -A nixos-fw -i ${iface} -j nixos-fw-accept

View File

@ -0,0 +1,155 @@
{ config, pkgs, ... }:
# TODO:
#
# asserts
# ensure that the nl80211 module is loaded/compiled in the kernel
# hwMode must be a/b/g
# channel must be between 1 and 13 (maybe)
# wpa_supplicant and hostapd on the same wireless interface doesn't make any sense
# perhaps an assertion that there is a dhcp server and a dns server on the IP address serviced by the hostapd?
with pkgs.lib;
let
cfg = config.services.hostapd;
configFile = pkgs.writeText "hostapd.conf"
''
interface=${cfg.interface}
driver=${cfg.driver}
ssid=${cfg.ssid}
hw_mode=${cfg.hwMode}
channel=${toString cfg.channel}
# logging (debug level)
logger_syslog=-1
logger_syslog_level=2
logger_stdout=-1
logger_stdout_level=2
ctrl_interface=/var/run/hostapd
ctrl_interface_group=${cfg.group}
${if cfg.wpa then ''
wpa=1
wpa_passphrase=${cfg.wpaPassphrase}
'' else ""}
${cfg.extraCfg}
'' ;
in
{
###### interface
options = {
services.hostapd = {
enable = mkOption {
default = false;
description = ''
Enable putting a wireless interface into infrastructure mode,
allowing other wireless devices to associate with the wireless interface and do
wireless networking. A simple access point will enable hostapd.wpa, and
hostapd.wpa_passphrase, hostapd.ssid, dhcpd on the wireless interface to
provide IP addresses to the associated stations, and nat (from the wireless
interface to an upstream interface).
'';
};
interface = mkOption {
default = "";
example = "wlan0";
description = ''
The interfaces <command>hostapd</command> will use.
'';
};
driver = mkOption {
default = "nl80211";
example = "hostapd";
type = types.string;
description = "Which driver hostapd will use. Most things will probably use the default.";
};
ssid = mkOption {
default = "nixos";
example = "mySpecialSSID";
type = types.string;
description = "SSID to be used in IEEE 802.11 management frames.";
};
hwMode = mkOption {
default = "b";
example = "g";
type = types.string;
description = "Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g";
};
channel = mkOption {
default = 7;
example = 11;
type = types.int;
description =
''
Channel number (IEEE 802.11)
Please note that some drivers do not use this value from hostapd and the
channel will need to be configured separately with iwconfig.
'';
};
group = mkOption {
default = "wheel";
example = "network";
type = types.string;
description = "members of this group can control hostapd";
};
wpa = mkOption {
default = true;
description = "enable WPA (IEEE 802.11i/D3.0) to authenticate to the access point";
};
wpaPassphrase = mkOption {
default = "my_sekret";
example = "any_64_char_string";
type = types.string;
description =
''
WPA-PSK (pre-shared-key) passphrase. Clients will need this
passphrase to associate with this access point. Warning: This passphrase will
get put into a world-readable file in the nix store.
'';
};
extraCfg = mkOption {
default = "";
example = ''
auth_algo=0
ieee80211n=1
ht_capab=[HT40-][SHORT-GI-40][DSSS_CCK-40]
'';
type = types.string;
description = "Extra configuration options to put in the hostapd.conf";
};
};
};
###### implementation
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.hostapd ];
jobs.hostapd =
{ startOn = "started network-interfaces";
stopOn = "stopping network-interfaces";
exec = "${pkgs.hostapd}/bin/hostapd ${configFile}";
};
};
}

View File

@ -1,4 +1,6 @@
# This module enables Network Address Translation (NAT).
# XXX: todo: support multiple upstream links
# see http://yesican.chsoft.biz/lartc/MultihomedLinuxNetworking.html
{ config, pkgs, ... }:
@ -25,13 +27,16 @@ in
};
networking.nat.internalIPs = mkOption {
example = "192.168.1.0/24";
example = [ "192.168.1.0/24" ] ;
description =
''
The IP address range for which to perform NAT. Packets
coming from these addresses and destined for the external
The IP address ranges for which to perform NAT. Packets
coming from these networks and destined for the external
interface will be rewritten.
'';
# Backward compatibility: this used to be a single range instead
# of a list.
apply = x: if isList x then x else [x];
};
networking.nat.externalInterface = mkOption {
@ -76,13 +81,17 @@ in
''
iptables -t nat -F POSTROUTING
iptables -t nat -X
''
+ (concatMapStrings (network:
''
iptables -t nat -A POSTROUTING \
-s ${cfg.internalIPs} -o ${cfg.externalInterface} \
-s ${network} -o ${cfg.externalInterface} \
${if cfg.externalIP == ""
then "-j MASQUERADE"
else "-j SNAT --to-source ${cfg.externalIP}"}
''
) cfg.internalIPs) +
''
echo 1 > /proc/sys/net/ipv4/ip_forward
'';
@ -91,7 +100,5 @@ in
iptables -t nat -F POSTROUTING
'';
};
};
}

View File

@ -8,6 +8,8 @@ let
httpd = mainCfg.package;
version24 = !versionOlder httpd.version "2.4";
httpdConf = mainCfg.configFile;
php = pkgs.php.override { apacheHttpd = httpd; };
@ -101,7 +103,8 @@ let
"auth_basic" "auth_digest"
# Authentication: is the user who he claims to be?
"authn_file" "authn_dbm" "authn_anon" "authn_alias"
"authn_file" "authn_dbm" "authn_anon"
(if version24 then "authn_core" else "authn_alias")
# Authorization: is the user allowed access?
"authz_user" "authz_groupfile" "authz_host"
@ -113,11 +116,31 @@ let
"vhost_alias" "negotiation" "dir" "imagemap" "actions" "speling"
"userdir" "alias" "rewrite" "proxy" "proxy_http"
]
++ optionals version24 [
"mpm_${mainCfg.multiProcessingModule}"
"authz_core"
"unixd"
]
++ (if mainCfg.multiProcessingModule == "prefork" then [ "cgi" ] else [ "cgid" ])
++ optional enableSSL "ssl"
++ extraApacheModules;
allDenied = if version24 then ''
Require all denied
'' else ''
Order deny,allow
Deny from all
'';
allGranted = if version24 then ''
Require all granted
'' else ''
Order allow,deny
Allow from all
'';
loggingConf = ''
ErrorLog ${mainCfg.logDir}/error_log
@ -186,8 +209,7 @@ let
<Directory "${documentRoot}">
Options Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
${allGranted}
</Directory>
'';
@ -241,12 +263,10 @@ let
AllowOverride FileInfo AuthConfig Limit Indexes
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
<Limit GET POST OPTIONS>
Order allow,deny
Allow from all
${allGranted}
</Limit>
<LimitExcept GET POST OPTIONS>
Order deny,allow
Deny from all
${allDenied}
</LimitExcept>
</Directory>
@ -268,8 +288,7 @@ let
Alias ${elem.urlPath} ${elem.dir}/
<Directory ${elem.dir}>
Options +Indexes
Order allow,deny
Allow from all
${allGranted}
AllowOverride All
</Directory>
'';
@ -286,6 +305,10 @@ let
ServerRoot ${httpd}
${optionalString version24 ''
DefaultRuntimeDir ${mainCfg.stateDir}/runtime
''}
PidFile ${mainCfg.stateDir}/httpd.pid
${optionalString (mainCfg.multiProcessingModule != "prefork") ''
@ -321,8 +344,7 @@ let
AddHandler type-map var
<Files ~ "^\.ht">
Order allow,deny
Deny from all
${allDenied}
</Files>
${mimeConf}
@ -340,16 +362,14 @@ let
<Directory />
Options FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all
${allDenied}
</Directory>
# But do allow access to files in the store so that we don't have
# to generate <Directory> clauses for every generated file that we
# want to serve.
<Directory /nix/store>
Order allow,deny
Allow from all
${allGranted}
</Directory>
# Generate directives for the main server.
@ -359,7 +379,8 @@ let
${let
ports = map getPort allHosts;
uniquePorts = uniqList {inputList = ports;};
in concatMapStrings (port: "NameVirtualHost *:${toString port}\n") uniquePorts
directives = concatMapStrings (port: "NameVirtualHost *:${toString port}\n") uniquePorts;
in optionalString (!version24) directives
}
${let
@ -620,6 +641,10 @@ in
''
mkdir -m 0750 -p ${mainCfg.stateDir}
chown root.${mainCfg.group} ${mainCfg.stateDir}
${optionalString version24 ''
mkdir -m 0750 -p "${mainCfg.stateDir}/runtime"
chown root.${mainCfg.group} "${mainCfg.stateDir}/runtime"
''}
mkdir -m 0700 -p ${mainCfg.logDir}
${optionalString (mainCfg.documentRoot != null)