-
Notifications
You must be signed in to change notification settings - Fork 4
/
lxc-container.nix
163 lines (138 loc) · 5.35 KB
/
lxc-container.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
let
# XXX: This is needed so that hybrid cgroup layouts are properly working in
# containers. Remove this as soon as lxc >= 2.0.9 has landed in <nixpkgs>.
overlays = [
(self: super: (import ./patches.nix { inherit super;}))
];
in
{ system ? builtins.currentSystem
, pkgs ? import <nixpkgs> { inherit system overlays; }
, lib ? pkgs.stdenv.lib
, lxcExtraConfig ? ""
, name ? ""
, ip ? ""
, container
}:
with pkgs;
with lib;
#assert ip != "" && container_ ? network && container.network ? ip;
let
container_ = if container ? configuration then container else { configuration = container; };
configuration = container_.configuration;
containerName = if name == "" then container.name else name;
containerIp = if container ? network && container.network ? ip then container.network.ip else ip;
gateway = if container_ ? network && container.network ? gateway then
container.network.gateway else "10.101.0.1";
bridge = if container_ ? network && container.network ? bridge then
container.network.bridge else "brNC-hostonly";
addBridgeInet = (container ? network && container.network ? enableNat && container.network.enableNat);
bridgeInet = "brNC-internet";
autostart = if container_ ? autostart && container.autostart then "1" else "0";
containerConfig = (import <nixpkgs/nixos/lib/eval-config.nix> {
modules =
let
extraConfig = {
nixpkgs.system = system;
boot.isContainer = true;
environment.systemPackages = with pkgs; [ dfc htop iptables ];
networking = {
hostName = mkDefault containerName;
interfaces.hostonly = {
useDHCP = false;
ipv4.addresses = [ { address = ip; prefixLength = 16; } ];
};
};
nixpkgs.overlays = overlays;
services.mingetty.autologinUser = mkDefault "root";
};
networkInetBridge = if addBridgeInet then {
networking = {
dhcpcd = {
allowInterfaces = [ "internet" ];
extraConfig = ''
ipv6
noipv4ll
# we are using radvd, so we disable router solicitation in dhcpd6
noipv6rs
waitip 4
interface internet
# request a normal (IA_NA) IPv6 address with IAID 1
ia_na 1
waitip 4
waitip 6
'';
};
interfaces = {
internet.useDHCP = true;
};
};
} else {};
in [ extraConfig networkInetBridge configuration ];
prefix = [ "systemd" "containers" containerName ];
extraArgs = { inherit ip; name = containerName; };
}).config.system.build.toplevel;
lxcConfigWrapper = pkgs.writeText "configWrapper" ''
lxc.include = /nix/var/nix/profiles/nixcloud-container/${containerName}/profile/config
'';
lxcConfig = pkgs.writeText "config" ''
lxc.uts.name = ${containerName}
# Fixme also support other architectures?
lxc.arch = ${if system == "x86_64-linux" then "x86_64" else "i686"}
# Not needed, just makes spares a few cpu cycles as LXC doesn't have
# to detect the backend.
#lxc.rootfs.backend = dir
lxc.rootfs.path = /var/lib/lxc/${containerName}/rootfs
lxc.init.cmd = /init/profile/container/init
#lxc.rootfs = /var/lib/lxc/${containerName}/rootfs
# Ensures correct functionality with user namespaces. Since mknod is not possible stuff like
# /dev/console, /dev/tty, /dev/urandom, etc. need to be bind mounted. Note the order
# of the file inclusion here is important.
lxc.include = ${pkgs.lxc}/share/lxc/config/common.conf
lxc.include = ${pkgs.lxc}/share/lxc/config/userns.conf
## Network
# see also https://wiki.archlinux.org/index.php/Linux_Containers
lxc.net.0.type = veth
lxc.net.0.name = hostonly
#lxc.net.0.ipv4.address = ${containerIp} (we assign this using nix, not from lxc)
lxc.net.0.flags = up
lxc.net.0.link = ${bridge}
${optionalString addBridgeInet ''
lxc.net.1.type = veth
lxc.net.1.name = internet
lxc.net.1.flags = up
lxc.net.1.link = ${bridgeInet}
''
}
# Specifiy {u,g}id mapping.
lxc.idmap = u 0 100000 65536
lxc.idmap = g 0 100000 65536
# FIXME apparmor support
# Nixos does not provide AppArmor support.
#lxc.aa_profile = unconfined
#lxc.aa_allow_incomplete = 1
lxc.apparmor.profile = unconfined
lxc.apparmor.allow_incomplete = 1
# Tweaks for systemd.
lxc.autodev = 1
# Additional mount entries.
lxc.mount.entry = /nix/store nix/store none defaults,bind.ro 0.0
lxc.mount.entry = /nix/var/nix/profiles/nixcloud-container/${containerName}/ init none defaults,bind.ro 0 0
# Mount entries that lead to a cleaner boot experience.
lxc.mount.entry = /sys/kernel/debug sys/kernel/debug none bind,optional 0 0
lxc.mount.entry = /sys/kernel/security sys/kernel/security none bind,optional 0 0
lxc.mount.entry = /sys/fs/pstore sys/fs/pstore none bind,optional 0 0
lxc.mount.entry = mqueue dev/mqueue mqueue rw,relatime,create=dir,optional 0 0
# LXC autostart
lxc.start.auto = ${autostart}
${lxcExtraConfig}
'';
in pkgs.stdenv.mkDerivation {
name = "nixcloudContainer-${name}";
phases = "installPhase";
installPhase = ''
mkdir $out
ln -s ${containerConfig} $out/container
ln -s ${lxcConfig} $out/config
ln -s ${lxcConfigWrapper} $out/configWrapper
'';
}