Merge remote-tracking branch 'origin/master' into systemd
This commit is contained in:
commit
b1da38f564
28 changed files with 853 additions and 272 deletions
|
@ -150,7 +150,7 @@ $ nixos-rebuild switch -I <replaceable>/my/sources</replaceable>
|
|||
definitions. This conditional values can be distinguished in two
|
||||
categories. The condition which are local to the current configuration
|
||||
and conditions which are dependent on others configurations. Local
|
||||
properties are <varname>mkIf</varname>, <varname>mkAlways</varname>
|
||||
properties are <varname>mkIf</varname>
|
||||
and <varname>mkAssert</varname>. Global properties
|
||||
are <varname>mkOverride</varname>, <varname>mkDefault</varname>
|
||||
and <varname>mkOrder</varname>.</para>
|
||||
|
@ -158,12 +158,7 @@ $ nixos-rebuild switch -I <replaceable>/my/sources</replaceable>
|
|||
<para><varname>mkIf</varname> is used to remove the option definitions which
|
||||
are below it if the condition is evaluated to
|
||||
false. <varname>mkAssert</varname> expects the condition to be evaluated
|
||||
to true otherwise it raises an error message. <varname>mkAlways</varname>
|
||||
is used to ignore all the <varname>mkIf</varname>
|
||||
and <varname>mkAssert</varname> which have been made
|
||||
previously. <varname>mkAlways</varname> and <varname>mkAssert</varname>
|
||||
are often used together to set an option value and to ensure that it has
|
||||
not been masked by another one.</para>
|
||||
to true otherwise it raises an error message.</para>
|
||||
|
||||
<para><varname>mkOverride</varname> is used to mask previous definitions if
|
||||
the current value has a lower mask number. The mask value is 100 (default)
|
||||
|
@ -223,14 +218,6 @@ let
|
|||
locatedb = "/var/cache/locatedb";
|
||||
logfile = "/var/log/updatedb";
|
||||
cmd =''root updatedb --localuser=nobody --output=${locatedb} > ${logfile}'';
|
||||
|
||||
mkCheck = x:
|
||||
mkIf cfg.enable (
|
||||
mkAssert config.services.cron.enable ''
|
||||
The cron daemon is not enabled, required by services.locate.enable.
|
||||
''
|
||||
x
|
||||
)
|
||||
in
|
||||
|
||||
{
|
||||
|
@ -260,9 +247,9 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
config = mkCheck {
|
||||
config = mkIf cfg.enable {
|
||||
services.cron = {
|
||||
enable = mkAlways cfg.enable;
|
||||
enable = true;
|
||||
systemCronJobs = "${cfg.period} root ${cmd}";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
{pkgs, config, ...}:
|
||||
|
||||
with pkgs.lib;
|
||||
with pkgs;
|
||||
|
||||
###### interface
|
||||
let
|
||||
inherit (pkgs.lib) mkOption mkIf optionalString stringAfter;
|
||||
inherit mkOption mkIf optionalString stringAfter singleton;
|
||||
|
||||
cfg = config.users.ldap;
|
||||
|
||||
options = {
|
||||
users = {
|
||||
|
@ -41,7 +46,7 @@ let
|
|||
|
||||
timeLimit = mkOption {
|
||||
default = 0;
|
||||
type = with pkgs.lib.types; int;
|
||||
type = types.int;
|
||||
description = "
|
||||
Specifies the time limit (in seconds) to use when performing
|
||||
searches. A value of zero (0), which is the default, is to
|
||||
|
@ -49,11 +54,36 @@ let
|
|||
";
|
||||
};
|
||||
|
||||
daemon = {
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to let the nslcd daemon (nss-pam-ldapd) handle the
|
||||
LDAP lookups for NSS and PAM. This can improve performance,
|
||||
and if you need to bind to the LDAP server with a password,
|
||||
it increases security, since only the nslcd user needs to
|
||||
have access to the bindpw file, not everyone that uses NSS
|
||||
and/or PAM. If this option is enabled, a local nscd user is
|
||||
created automatically, and the nslcd service is started
|
||||
automatically when the network get up.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
default = "";
|
||||
type = types.string;
|
||||
description = ''
|
||||
Extra configuration options that will be added verbatim at
|
||||
the end of the nslcd configuration file (nslcd.conf).
|
||||
'' ;
|
||||
} ;
|
||||
};
|
||||
|
||||
bind = {
|
||||
distinguishedName = mkOption {
|
||||
default = "";
|
||||
example = "cn=admin,dc=example,dc=com";
|
||||
type = with pkgs.lib.types; string;
|
||||
type = types.string;
|
||||
description = "
|
||||
The distinguished name to bind to the LDAP server with. If this
|
||||
is not specified, an anonymous bind will be done.
|
||||
|
@ -62,7 +92,7 @@ let
|
|||
|
||||
password = mkOption {
|
||||
default = "/etc/ldap/bind.password";
|
||||
type = with pkgs.lib.types; string;
|
||||
type = types.string;
|
||||
description = "
|
||||
The path to a file containing the credentials to use when binding
|
||||
to the LDAP server (if not binding anonymously).
|
||||
|
@ -71,7 +101,7 @@ let
|
|||
|
||||
timeLimit = mkOption {
|
||||
default = 30;
|
||||
type = with pkgs.lib.types; int;
|
||||
type = types.int;
|
||||
description = "
|
||||
Specifies the time limit (in seconds) to use when connecting
|
||||
to the directory server. This is distinct from the time limit
|
||||
|
@ -82,7 +112,7 @@ let
|
|||
|
||||
policy = mkOption {
|
||||
default = "hard_open";
|
||||
type = with pkgs.lib.types; string;
|
||||
type = types.string;
|
||||
description = "
|
||||
Specifies the policy to use for reconnecting to an unavailable
|
||||
LDAP server. The default is <literal>hard_open</literal>, which
|
||||
|
@ -99,55 +129,120 @@ let
|
|||
};
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
default = "" ;
|
||||
type = types.string ;
|
||||
description = ''
|
||||
Extra configuration options that will be added verbatim at
|
||||
the end of the ldap configuration file (ldap.conf).
|
||||
If <literal>users.ldap.daemon</literal> is enabled, this
|
||||
configuration will not be used. In that case, use
|
||||
<literal>users.ldap.daemon.extraConfig</literal> instead.
|
||||
'' ;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Careful: OpenLDAP seems to be very picky about the indentation of
|
||||
# this file. Directives HAVE to start in the first column!
|
||||
ldapConfig = {
|
||||
target = "ldap.conf";
|
||||
source = writeText "ldap.conf" ''
|
||||
uri ${config.users.ldap.server}
|
||||
base ${config.users.ldap.base}
|
||||
timelimit ${toString config.users.ldap.timeLimit}
|
||||
bind_timelimit ${toString config.users.ldap.bind.timeLimit}
|
||||
bind_policy ${config.users.ldap.bind.policy}
|
||||
${optionalString config.users.ldap.useTLS ''
|
||||
ssl start_tls
|
||||
tls_checkpeer no
|
||||
''}
|
||||
${optionalString (config.users.ldap.bind.distinguishedName != "") ''
|
||||
binddn ${config.users.ldap.bind.distinguishedName}
|
||||
''}
|
||||
${optionalString (cfg.extraConfig != "") cfg.extraConfig }
|
||||
'';
|
||||
};
|
||||
|
||||
nslcdConfig = {
|
||||
target = "nslcd.conf";
|
||||
source = writeText "nslcd.conf" ''
|
||||
uid nslcd
|
||||
gid nslcd
|
||||
uri ${cfg.server}
|
||||
base ${cfg.base}
|
||||
timelimit ${toString cfg.timeLimit}
|
||||
bind_timelimit ${toString cfg.bind.timeLimit}
|
||||
${optionalString (cfg.bind.distinguishedName != "")
|
||||
"binddn ${cfg.bind.distinguishedName}" }
|
||||
${optionalString (cfg.daemon.extraConfig != "") cfg.daemon.extraConfig }
|
||||
'';
|
||||
};
|
||||
|
||||
insertLdapPassword = !config.users.ldap.daemon.enable &&
|
||||
config.users.ldap.bind.distinguishedName != "";
|
||||
|
||||
in
|
||||
|
||||
###### implementation
|
||||
|
||||
mkIf config.users.ldap.enable {
|
||||
mkIf cfg.enable {
|
||||
require = [
|
||||
options
|
||||
];
|
||||
|
||||
# LDAP configuration.
|
||||
environment = {
|
||||
etc = [
|
||||
environment.etc = if cfg.daemon.enable then [nslcdConfig] else [ldapConfig];
|
||||
|
||||
# Careful: OpenLDAP seems to be very picky about the indentation of
|
||||
# this file. Directives HAVE to start in the first column!
|
||||
{ source = pkgs.writeText "ldap.conf"
|
||||
''
|
||||
uri ${config.users.ldap.server}
|
||||
base ${config.users.ldap.base}
|
||||
timelimit ${toString config.users.ldap.timeLimit}
|
||||
bind_timelimit ${toString config.users.ldap.bind.timeLimit}
|
||||
bind_policy ${config.users.ldap.bind.policy}
|
||||
|
||||
${optionalString config.users.ldap.useTLS ''
|
||||
ssl start_tls
|
||||
tls_checkpeer no
|
||||
''}
|
||||
|
||||
${optionalString (config.users.ldap.bind.distinguishedName != "") ''
|
||||
binddn ${config.users.ldap.bind.distinguishedName}
|
||||
''}
|
||||
'';
|
||||
target = "ldap.conf";
|
||||
}
|
||||
|
||||
];
|
||||
};
|
||||
|
||||
system.activationScripts.ldap = stringAfter [ "etc" ] (
|
||||
optionalString (config.users.ldap.bind.distinguishedName != "") ''
|
||||
if test -f "${config.users.ldap.bind.password}" ; then
|
||||
echo "bindpw $(cat ${config.users.ldap.bind.password})" | cat /etc/ldap.conf - > /etc/ldap.conf.bindpw
|
||||
system.activationScripts = mkIf insertLdapPassword {
|
||||
ldap = stringAfter [ "etc" "groups" "users" ] ''
|
||||
if test -f "${cfg.bind.password}" ; then
|
||||
echo "bindpw "$(cat ${cfg.bind.password})"" | cat ${ldapConfig} - > /etc/ldap.conf.bindpw
|
||||
mv -fT /etc/ldap.conf.bindpw /etc/ldap.conf
|
||||
chmod 600 /etc/ldap.conf
|
||||
fi
|
||||
''
|
||||
'';
|
||||
};
|
||||
|
||||
system.nssModules = singleton (
|
||||
if cfg.daemon.enable then nss_pam_ldapd else nss_ldap
|
||||
);
|
||||
|
||||
users = mkIf cfg.daemon.enable {
|
||||
extraGroups.nslcd = {
|
||||
gid = config.ids.gids.nslcd;
|
||||
};
|
||||
|
||||
extraUsers.nslcd = {
|
||||
uid = config.ids.uids.nslcd;
|
||||
description = "nslcd user.";
|
||||
group = "nslcd";
|
||||
};
|
||||
};
|
||||
|
||||
jobs = mkIf cfg.daemon.enable {
|
||||
nslcd = {
|
||||
startOn = "filesystem";
|
||||
|
||||
stopOn = "stopping network-interfaces";
|
||||
|
||||
daemonType = "fork";
|
||||
|
||||
path = [ nss_pam_ldapd ];
|
||||
|
||||
preStart = ''
|
||||
mkdir -p /run/nslcd
|
||||
chown nslcd.nslcd /run/nslcd
|
||||
${optionalString (cfg.bind.distinguishedName != "") ''
|
||||
if test -s "${cfg.bind.password}" ; then
|
||||
ln -sfT "${cfg.bind.password}" /run/nslcd/bindpw
|
||||
fi
|
||||
''}
|
||||
'';
|
||||
|
||||
postStop = "rm -f /run/nslcd/nslcd.pid";
|
||||
|
||||
exec = "nslcd";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -18,6 +18,18 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
networking.dnsSingleRequest = pkgs.lib.mkOption {
|
||||
default = false;
|
||||
description = ''
|
||||
Recent versions of glibc will issue both ipv4 (A) and ipv6 (AAAA)
|
||||
address queries at the same time, from the same port. Sometimes upstream
|
||||
routers will systemically drop the ipv4 queries. The symptom of this problem is
|
||||
that 'getent hosts example.com' only returns ipv6 (or perhaps only ipv4) addresses. The
|
||||
workaround for this is to specify the option 'single-request' in
|
||||
/etc/resolve.conf. This option enables that.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
in
|
||||
|
@ -64,6 +76,9 @@ in
|
|||
# Invalidate the nscd cache whenever resolv.conf is
|
||||
# regenerated.
|
||||
libc_restart='${pkgs.systemd}/bin/systemctl reload --no-block nscd.service'
|
||||
'' + optionalString cfg.dnsSingleRequest ''
|
||||
# only send one DNS request at a time
|
||||
resolv_conf_options='single-request'
|
||||
'' + optionalString config.services.bind.enable ''
|
||||
# This hosts runs a full-blown DNS resolver.
|
||||
name_servers='127.0.0.1'
|
||||
|
|
|
@ -19,14 +19,9 @@ let
|
|||
";
|
||||
merge = mergeListOption;
|
||||
apply = list:
|
||||
let
|
||||
list2 =
|
||||
list
|
||||
# !!! this should be in the LDAP module
|
||||
++ optional config.users.ldap.enable pkgs.nss_ldap;
|
||||
in {
|
||||
list = list2;
|
||||
path = makeLibraryPath list2;
|
||||
{
|
||||
inherit list;
|
||||
path = makeLibraryPath list;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -28,64 +28,65 @@ let cfg = config.hardware.pulseaudio; in
|
|||
};
|
||||
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = mkMerge
|
||||
[ # Create pulse/client.conf even if PulseAudio is disabled so
|
||||
# that we can disable the autospawn feature in programs that
|
||||
# are built with PulseAudio support (like KDE).
|
||||
{ environment.etc = singleton
|
||||
{ target = "pulse/client.conf";
|
||||
source = pkgs.writeText "client.conf"
|
||||
''
|
||||
autospawn=${if cfg.enable then "yes" else "no"}
|
||||
${optionalString cfg.enable ''
|
||||
daemon-binary=${cfg.package}/bin/pulseaudio
|
||||
''}
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
||||
environment.systemPackages =
|
||||
[ cfg.package ];
|
||||
(mkIf cfg.enable {
|
||||
|
||||
environment.etc = mkAlways (
|
||||
[ # Create pulse/client.conf even if PulseAudio is disabled so
|
||||
# that we can disable the autospawn feature in programs that
|
||||
# are built with PulseAudio support (like KDE).
|
||||
{ target = "pulse/client.conf";
|
||||
source = pkgs.writeText "client.conf"
|
||||
''
|
||||
autospawn=${if cfg.enable then "yes" else "no"}
|
||||
${optionalString cfg.enable ''
|
||||
daemon-binary=${cfg.package}/bin/pulseaudio
|
||||
''}
|
||||
'';
|
||||
}
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
] ++ optionals cfg.enable
|
||||
[ # Write an /etc/asound.conf that causes all ALSA applications to
|
||||
# be re-routed to the PulseAudio server through ALSA's Pulse
|
||||
# plugin.
|
||||
{ target = "asound.conf";
|
||||
source = pkgs.writeText "asound.conf"
|
||||
''
|
||||
pcm_type.pulse {
|
||||
lib ${pkgs.alsaPlugins}/lib/alsa-lib/libasound_module_pcm_pulse.so
|
||||
}
|
||||
environment.etc =
|
||||
[ # Write an /etc/asound.conf that causes all ALSA applications to
|
||||
# be re-routed to the PulseAudio server through ALSA's Pulse
|
||||
# plugin.
|
||||
{ target = "asound.conf";
|
||||
source = pkgs.writeText "asound.conf"
|
||||
''
|
||||
pcm_type.pulse {
|
||||
lib ${pkgs.alsaPlugins}/lib/alsa-lib/libasound_module_pcm_pulse.so
|
||||
}
|
||||
|
||||
pcm.!default {
|
||||
type pulse
|
||||
hint.description "Default Audio Device (via PulseAudio)"
|
||||
}
|
||||
pcm.!default {
|
||||
type pulse
|
||||
hint.description "Default Audio Device (via PulseAudio)"
|
||||
}
|
||||
|
||||
ctl_type.pulse {
|
||||
lib ${pkgs.alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so
|
||||
}
|
||||
ctl_type.pulse {
|
||||
lib ${pkgs.alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so
|
||||
}
|
||||
|
||||
ctl.!default {
|
||||
type pulse
|
||||
}
|
||||
'';
|
||||
}
|
||||
ctl.!default {
|
||||
type pulse
|
||||
}
|
||||
'';
|
||||
}
|
||||
|
||||
{ target = "pulse/default.pa";
|
||||
source = "${cfg.package}/etc/pulse/default.pa";
|
||||
}
|
||||
{ target = "pulse/default.pa";
|
||||
source = "${cfg.package}/etc/pulse/default.pa";
|
||||
}
|
||||
|
||||
{ target = "pulse/system.pa";
|
||||
source = "${cfg.package}/etc/pulse/system.pa";
|
||||
}
|
||||
{ target = "pulse/system.pa";
|
||||
source = "${cfg.package}/etc/pulse/system.pa";
|
||||
}
|
||||
];
|
||||
|
||||
]);
|
||||
# Allow PulseAudio to get realtime priority using rtkit.
|
||||
security.rtkit.enable = true;
|
||||
|
||||
# Allow PulseAudio to get realtime priority using rtkit.
|
||||
security.rtkit.enable = true;
|
||||
|
||||
};
|
||||
})
|
||||
];
|
||||
|
||||
}
|
||||
|
|
89
modules/installer/cd-dvd/system-tarball-pc-readme.txt
Normal file
89
modules/installer/cd-dvd/system-tarball-pc-readme.txt
Normal file
|
@ -0,0 +1,89 @@
|
|||
Let all the files in the system tarball sit in a directory served by NFS (the
|
||||
NFS root) like this in exportfs:
|
||||
/home/pcroot 192.168.1.0/24(rw,no_root_squash,no_all_squash)
|
||||
|
||||
Run "exportfs -a" after editing /etc/exportfs, for the nfs server to be aware
|
||||
of the changes.
|
||||
|
||||
Use a tftp server serving the root of boot/ (from the system tarball).
|
||||
|
||||
In order to have PXE boot, use the boot/dhcpd.conf-example file for your dhcpd
|
||||
server, as it will point your PXE clients to pxelinux.0 from the tftp server.
|
||||
Adapt the configuration to your network.
|
||||
|
||||
Adapt the pxelinux configuration (boot/pxelinux.cfg/default) to set the path to
|
||||
your nfrroot. If you use ip=dhcp in the kernel, the nfs server ip will be taken
|
||||
from dhcp and so you don't have to specify it.
|
||||
|
||||
The linux in bzImage includes network drivers for some usual cards.
|
||||
|
||||
|
||||
QEMU Testing
|
||||
---------------
|
||||
|
||||
You can test qemu pxe boot without having a DHCP server adapted, but having
|
||||
nfsroot, like this:
|
||||
qemu-system-x86_64 -tftp /home/pcroot/boot -net nic -net user,bootfile=pxelinux.0 -boot n
|
||||
|
||||
I don't know how to use NFS through the qemu '-net user' though.
|
||||
|
||||
|
||||
QEMU Testing with NFS root and bridged network
|
||||
-------------------------------------------------
|
||||
|
||||
This allows testing with qemu as any other host in your LAN.
|
||||
|
||||
Testing with the real dhcpd server requires setting up a bridge and having a
|
||||
tap device.
|
||||
tunctl -t tap0
|
||||
brctl addbr br0
|
||||
brctl addif br0 eth0
|
||||
brctl addif tap0 eth0
|
||||
ifconfig eth0 0.0.0.0 up
|
||||
ifconfig tap0 0.0.0.0 up
|
||||
ifconfig br0 up # With your ip configuration
|
||||
|
||||
Then you can run qemu:
|
||||
qemu-system-x86_64 -boot n -net tap,ifname=tap0,script=no -net nic,model=e1000
|
||||
|
||||
|
||||
Using the system-tarball-pc in a chroot
|
||||
--------------------------------------------------
|
||||
|
||||
Installation:
|
||||
mkdir nixos-chroot && cd nixos-chroot
|
||||
tar xf your-system-tarball.tar.xz
|
||||
mkdir sys dev proc tmp root var run
|
||||
mount --bind /sys sys
|
||||
mount --bind /dev dev
|
||||
mount --bind /proc proc
|
||||
|
||||
Activate the system: look for a directory in nix/store similar to:
|
||||
"/nix/store/y0d1lcj9fppli0hl3x0m0ba5g1ndjv2j-nixos-feb97bx-53f008"
|
||||
Having found it, activate that nixos system *twice*:
|
||||
chroot . /nix/store/SOMETHING-nixos-SOMETHING/activate
|
||||
chroot . /nix/store/SOMETHING-nixos-SOMETHING/activate
|
||||
|
||||
This runs a 'hostname' command. Restore your old hostname with:
|
||||
hostname OLDHOSTNAME
|
||||
|
||||
Copy your system resolv.conf to the /etc/resolv.conf inside the chroot:
|
||||
cp /etc/resolv.conf etc
|
||||
|
||||
Then you can get an interactive shell in the nixos chroot. '*' means
|
||||
to run inside the chroot interactive shell
|
||||
chroot . /bin/sh
|
||||
* source /etc/profile
|
||||
|
||||
Populate the nix database: that should be done in the init script if you
|
||||
had booted this nixos. Run:
|
||||
* `grep local-cmds run/current-system/init`
|
||||
|
||||
Then you can proceed normally subscribing to a nixos channel:
|
||||
nix-channel --add http://nixos.org/releases/nixos/channels/nixos-unstable
|
||||
nix-channel --update
|
||||
|
||||
Testing:
|
||||
nix-env -i hello
|
||||
which hello
|
||||
hello
|
|
@ -60,54 +60,7 @@ let
|
|||
}
|
||||
'';
|
||||
|
||||
readme = pkgs.writeText "readme.txt" ''
|
||||
Let all the files in the system tarball sit in a directory served by NFS (the NFS root)
|
||||
like this in exportfs:
|
||||
/home/pcroot 192.168.1.0/24(rw,no_root_squash,no_all_squash)
|
||||
|
||||
Run "exportfs -a" after editing /etc/exportfs, for the nfs server to be aware of the
|
||||
changes.
|
||||
|
||||
Use a tftp server serving the root of boot/ (from the system tarball).
|
||||
|
||||
In order to have PXE boot, use the boot/dhcpd.conf-example file for your dhcpd server,
|
||||
as it will point your PXE clients to pxelinux.0 from the tftp server. Adapt the
|
||||
configuration to your network.
|
||||
|
||||
Adapt the pxelinux configuration (boot/pxelinux.cfg/default) to set the path to your
|
||||
nfrroot. If you use ip=dhcp in the kernel, the nfs server ip will be taken from
|
||||
dhcp and so you don't have to specify it.
|
||||
|
||||
The linux in bzImage includes network drivers for some usual cards.
|
||||
|
||||
|
||||
QEMU Testing
|
||||
---------------
|
||||
|
||||
You can test qemu pxe boot without having a DHCP server adapted, but having nfsroot,
|
||||
like this:
|
||||
qemu-system-x86_64 -tftp /home/pcroot/boot -net nic -net user,bootfile=pxelinux.0 -boot n
|
||||
|
||||
I don't know how to use NFS through the qemu '-net user' though.
|
||||
|
||||
|
||||
QEMU Testing with NFS root and bridged network
|
||||
-------------------------------------------------
|
||||
|
||||
This allows testing with qemu as any other host in your LAN.
|
||||
|
||||
Testing with the real dhcpd server requires setting up a bridge and having a tap device.
|
||||
tunctl -t tap0
|
||||
brctl addbr br0
|
||||
brctl addif br0 eth0
|
||||
brctl addif tap0 eth0
|
||||
ifconfig eth0 0.0.0.0 up
|
||||
ifconfig tap0 0.0.0.0 up
|
||||
ifconfig br0 up # With your ip configuration
|
||||
|
||||
Then you can run qemu:
|
||||
qemu-system-x86_64 -boot n -net tap,ifname=tap0,script=no -net nic,model=e1000
|
||||
'';
|
||||
readme = ./system-tarball-pc-readme.txt;
|
||||
|
||||
in
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ let
|
|||
crashdump = config.boot.crashDump;
|
||||
|
||||
kernelParams = concatStringsSep " " crashdump.kernelParams;
|
||||
|
||||
in
|
||||
###### interface
|
||||
{
|
||||
|
@ -55,6 +56,8 @@ in
|
|||
kernelParams = [
|
||||
"crashkernel=64M"
|
||||
"nmi_watchdog=panic"
|
||||
"softlockup_panic=1"
|
||||
"idle=poll"
|
||||
];
|
||||
kernelPackages = mkOverride 50 (crashdump.kernelPackages // {
|
||||
kernel = crashdump.kernelPackages.kernel.override
|
||||
|
|
|
@ -74,6 +74,7 @@ in
|
|||
bind = 53;
|
||||
wwwrun = 54;
|
||||
spamd = 56;
|
||||
nslcd = 58;
|
||||
|
||||
# When adding a uid, make sure it doesn't match an existing gid.
|
||||
|
||||
|
@ -129,6 +130,7 @@ in
|
|||
adm = 55;
|
||||
spamd = 56;
|
||||
networkmanager = 57;
|
||||
nslcd = 58;
|
||||
|
||||
# When adding a gid, make sure it doesn't match an existing uid.
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
./programs/blcr.nix
|
||||
./programs/info.nix
|
||||
./programs/shadow.nix
|
||||
./programs/shell.nix
|
||||
./programs/ssh.nix
|
||||
./programs/ssmtp.nix
|
||||
./programs/wvdial.nix
|
||||
|
@ -127,6 +128,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
|
||||
|
|
|
@ -25,6 +25,10 @@ let
|
|||
fi
|
||||
'';
|
||||
|
||||
shellAliases = concatStringsSep "\n" (
|
||||
mapAttrsFlatten (k: v: "alias ${k}='${v}'") config.environment.shellAliases
|
||||
);
|
||||
|
||||
options = {
|
||||
|
||||
environment.promptInit = mkOption {
|
||||
|
@ -90,12 +94,12 @@ in
|
|||
{ # /etc/bashrc: executed every time a bash starts. Sources
|
||||
# /etc/profile to ensure that the system environment is
|
||||
# configured properly.
|
||||
source = pkgs.substituteAll {
|
||||
src = ./bashrc.sh;
|
||||
inherit (config.environment) promptInit;
|
||||
inherit initBashCompletion;
|
||||
};
|
||||
target = "bashrc";
|
||||
source = pkgs.substituteAll {
|
||||
src = ./bashrc.sh;
|
||||
inherit (config.environment) promptInit;
|
||||
inherit initBashCompletion shellAliases;
|
||||
};
|
||||
target = "bashrc";
|
||||
}
|
||||
|
||||
{ # Configuration for readline in bash.
|
||||
|
@ -104,6 +108,13 @@ in
|
|||
}
|
||||
];
|
||||
|
||||
environment.shellAliases =
|
||||
{ ls = "ls --color=tty";
|
||||
ll = "ls -l";
|
||||
l = "ls -alh";
|
||||
which = "type -P";
|
||||
};
|
||||
|
||||
system.build.binsh = pkgs.bashInteractive;
|
||||
|
||||
system.activationScripts.binsh = stringAfter [ "stdio" ]
|
||||
|
|
|
@ -21,15 +21,4 @@ shopt -s checkwinsize
|
|||
|
||||
@promptInit@
|
||||
@initBashCompletion@
|
||||
|
||||
# Some aliases.
|
||||
alias ls="ls --color=tty"
|
||||
alias ll="ls -l"
|
||||
alias l="ls -alh"
|
||||
alias which="type -P"
|
||||
|
||||
# Convenience for people used to Upstart.
|
||||
alias start="systemctl start"
|
||||
alias stop="systemctl stop"
|
||||
alias restart="systemctl restart"
|
||||
alias status="systemctl status"
|
||||
@shellAliases@
|
||||
|
|
25
modules/programs/shell.nix
Normal file
25
modules/programs/shell.nix
Normal file
|
@ -0,0 +1,25 @@
|
|||
# This module defines global configuration for the shells.
|
||||
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
{
|
||||
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 = {
|
||||
};
|
||||
}
|
|
@ -16,11 +16,15 @@ in
|
|||
programs.ssh = {
|
||||
|
||||
forwardX11 = mkOption {
|
||||
default = cfgd.forwardX11;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to request X11 forwarding on outgoing connections by default.
|
||||
This is useful for running graphical programs on the remote machine and have them display to your local X11 server.
|
||||
Historically, this value has depended on the value used by the local sshd daemon, but there really isn't a relation between the two.
|
||||
Note: there are some security risks to forwarding an X11 connection.
|
||||
NixOS's X server is built with the SECURITY extension, which prevents some obvious attacks.
|
||||
To enable or disable forwarding on a per-connection basis, see the -X and -x options to ssh.
|
||||
The -Y option to ssh enables trusted forwarding, which bypasses the SECURITY extension.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
|
@ -7,7 +7,9 @@ with pkgs.lib;
|
|||
|
||||
let
|
||||
|
||||
inherit (pkgs) pam_ldap pam_krb5 pam_ccreds;
|
||||
inherit (pkgs) pam_krb5 pam_ccreds;
|
||||
|
||||
pam_ldap = if config.users.ldap.daemon.enable then pkgs.nss_pam_ldapd else pkgs.pam_ldap;
|
||||
|
||||
otherService = pkgs.writeText "other.pam"
|
||||
''
|
||||
|
@ -249,6 +251,7 @@ in
|
|||
{ name = "i3lock"; }
|
||||
{ name = "lshd"; }
|
||||
{ name = "samba"; }
|
||||
{ name = "screen"; }
|
||||
{ name = "vlock"; }
|
||||
{ name = "xlock"; }
|
||||
{ name = "xscreensaver"; }
|
||||
|
|
|
@ -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 ];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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"];
|
||||
|
|
|
@ -154,23 +154,23 @@ in
|
|||
|
||||
defaultShare = {
|
||||
enable = mkOption {
|
||||
description = "Whether to share /home/smbd as 'default'.";
|
||||
default = false;
|
||||
};
|
||||
description = "Whether to share /home/smbd as 'default'.";
|
||||
default = false;
|
||||
};
|
||||
writeable = mkOption {
|
||||
description = "Whether to allow write access to default share.";
|
||||
default = false;
|
||||
};
|
||||
description = "Whether to allow write access to default share.";
|
||||
default = false;
|
||||
};
|
||||
guest = mkOption {
|
||||
description = "Whether to allow guest access to default share.";
|
||||
default = true;
|
||||
};
|
||||
description = "Whether to allow guest access to default share.";
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
|
||||
securityType = mkOption {
|
||||
description = "Samba security type";
|
||||
default = "user";
|
||||
example = "share";
|
||||
default = "user";
|
||||
example = "share";
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -180,43 +180,45 @@ in
|
|||
|
||||
###### implementation
|
||||
|
||||
config = mkIf config.services.samba.enable {
|
||||
config = mkMerge
|
||||
[ { # Always provide a smb.conf to shut up programs like smbclient and smbspool.
|
||||
environment.etc = singleton
|
||||
{ source =
|
||||
if cfg.enable then configFile
|
||||
else pkgs.writeText "smb-dummy.conf" "# Samba is disabled.";
|
||||
target = "samba/smb.conf";
|
||||
};
|
||||
}
|
||||
|
||||
users.extraUsers = singleton
|
||||
{ name = user;
|
||||
description = "Samba service user";
|
||||
group = group;
|
||||
};
|
||||
(mkIf config.services.samba.enable {
|
||||
users.extraUsers = singleton
|
||||
{ name = user;
|
||||
description = "Samba service user";
|
||||
group = group;
|
||||
};
|
||||
|
||||
users.extraGroups = singleton
|
||||
{ name = group;
|
||||
};
|
||||
users.extraGroups = singleton
|
||||
{ name = group;
|
||||
};
|
||||
|
||||
# always provide a smb.conf to shut up programs like smbclient and smbspool.
|
||||
environment.etc = mkAlways (singleton
|
||||
{ source =
|
||||
if cfg.enable then configFile
|
||||
else pkgs.writeText "smb-dummy.conf" "# Samba is disabled.";
|
||||
target = "samba/smb.conf";
|
||||
});
|
||||
|
||||
# Dummy job to start the real Samba daemons (nmbd, smbd, winbindd).
|
||||
jobs.sambaControl =
|
||||
{ name = "samba";
|
||||
description = "Samba server";
|
||||
# Dummy job to start the real Samba daemons (nmbd, smbd, winbindd).
|
||||
jobs.sambaControl =
|
||||
{ name = "samba";
|
||||
description = "Samba server";
|
||||
|
||||
startOn = "started network-interfaces";
|
||||
stopOn = "stopping network-interfaces";
|
||||
startOn = "started network-interfaces";
|
||||
stopOn = "stopping network-interfaces";
|
||||
|
||||
preStart = setupScript;
|
||||
};
|
||||
preStart = setupScript;
|
||||
};
|
||||
|
||||
jobs.nmbd = daemonJob "nmbd" "-D";
|
||||
jobs.nmbd = daemonJob "nmbd" "-D";
|
||||
|
||||
jobs.smbd = daemonJob "smbd" "-D";
|
||||
jobs.smbd = daemonJob "smbd" "-D";
|
||||
|
||||
jobs.winbindd = daemonJob "winbindd" "-D";
|
||||
|
||||
};
|
||||
jobs.winbindd = daemonJob "winbindd" "-D";
|
||||
})
|
||||
];
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,10 @@ let
|
|||
|
||||
serversParam = concatMapStrings (s: "-S ${s} ") cfg.servers;
|
||||
|
||||
dnsmasqConf = pkgs.writeText "dnsmasq.conf" ''
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
@ -33,6 +37,15 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.string;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra configuration directives that should be added to
|
||||
<literal>dnsmasq.conf</literal>
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -49,7 +62,7 @@ in
|
|||
|
||||
daemonType = "daemon";
|
||||
|
||||
exec = "${dnsmasq}/bin/dnsmasq -R ${serversParam}";
|
||||
exec = "${dnsmasq}/bin/dnsmasq -R ${serversParam} -o -C ${dnsmasqConf}";
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -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";
|
||||
|
@ -232,6 +297,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
|
||||
|
|
155
modules/services/networking/hostapd.nix
Normal file
155
modules/services/networking/hostapd.nix
Normal 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}";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ in
|
|||
flags = "REUSE NAMEINARGS";
|
||||
protocol = "tcp";
|
||||
user = "root";
|
||||
server = "${pkgs.tcpWrapper}/sbin/tcpd";
|
||||
server = "${pkgs.tcp_wrappers}/sbin/tcpd";
|
||||
serverArgs = "${pkgs.heimdal}/sbin/kadmind";
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -604,6 +625,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)
|
||||
|
|
|
@ -343,7 +343,8 @@ in
|
|||
optional (elem "virtualbox" driverNames) kernelPackages.virtualboxGuestAdditions ++
|
||||
optional (elem "ati_unfree" driverNames) kernelPackages.ati_drivers_x11;
|
||||
|
||||
environment.etc = optionals cfg.exportConfiguration
|
||||
environment.etc =
|
||||
(optionals cfg.exportConfiguration
|
||||
[ { source = "${configFile}";
|
||||
target = "X11/xorg.conf";
|
||||
}
|
||||
|
@ -351,7 +352,15 @@ in
|
|||
{ source = "${pkgs.xkeyboard_config}/etc/X11/xkb";
|
||||
target = "X11/xkb";
|
||||
}
|
||||
];
|
||||
])
|
||||
++ (optionals (elem "ati_unfree" driverNames) [
|
||||
|
||||
# according toiive on #ati you don't need the pcs, it is like registry... keeps old stuff to make your
|
||||
# life harder ;) Still it seems to be required
|
||||
{ source = "${kernelPackages.ati_drivers_x11}/etc/ati";
|
||||
target = "ati";
|
||||
}
|
||||
]);
|
||||
|
||||
environment.x11Packages =
|
||||
[ xorg.xorgserver
|
||||
|
@ -417,6 +426,8 @@ in
|
|||
"ln -sf ${kernelPackages.nvidia_x11_legacy96} /run/opengl-driver"
|
||||
else if elem "nvidiaLegacy173" driverNames then
|
||||
"ln -sf ${kernelPackages.nvidia_x11_legacy173} /run/opengl-driver"
|
||||
else if elem "ati_unfree" driverNames then
|
||||
"ln -sf ${kernelPackages.ati_drivers_x11} /run/opengl-driver"
|
||||
else if cfg.driSupport then
|
||||
"ln -sf ${pkgs.mesa} /run/opengl-driver"
|
||||
else ""
|
||||
|
|
|
@ -40,10 +40,10 @@ EOF
|
|||
|
||||
case $reply in
|
||||
f)
|
||||
exec setsid @shell@ < /dev/$console >/dev/$console 2>/dev/$console ;;
|
||||
exec setsid @shell@ -c "@shell@ < /dev/$console >/dev/$console 2>/dev/$console" ;;
|
||||
i)
|
||||
echo "Starting interactive shell..."
|
||||
setsid @shell@ < /dev/$console >/dev/$console 2>/dev/$console || fail
|
||||
setsid @shell@ -c "@shell@ < /dev/$console >/dev/$console 2>/dev/$console" || fail
|
||||
;;
|
||||
*)
|
||||
echo "Continuing...";;
|
||||
|
|
|
@ -469,5 +469,12 @@ in
|
|||
"CGROUPS" "AUTOFS4_FS" "DEVTMPFS"
|
||||
];
|
||||
|
||||
environment.shellAliases =
|
||||
{ start = "systemctl start";
|
||||
stop = "systemctl stop";
|
||||
restart = "systemctl restart";
|
||||
status = "systemctl status";
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,8 +5,19 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
options = {
|
||||
ec2.metadata = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to allow access to EC2 metadata.
|
||||
'';
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
require = [options];
|
||||
|
||||
boot.systemd.services."fetch-ec2-data" =
|
||||
{ description = "Fetch EC2 Data";
|
||||
|
@ -56,9 +67,11 @@ with pkgs.lib;
|
|||
echo "$key_pub" > /etc/ssh/ssh_host_dsa_key.pub
|
||||
fi
|
||||
|
||||
${optionalString (! config.ec2.metadata) ''
|
||||
# Since the user data is sensitive, prevent it from being
|
||||
# accessed from now on.
|
||||
ip route add blackhole 169.254.169.254/32
|
||||
''}
|
||||
'';
|
||||
|
||||
serviceConfig.Type = "oneshot";
|
||||
|
|
Loading…
Reference in a new issue