1# Systemd services for openvswitch
2
3{ config, lib, pkgs, ... }:
4
5with lib;
6
7let
8 cfg = config.virtualisation.vswitch;
9
10in {
11
12 options.virtualisation.vswitch = {
13 enable = mkOption {
14 type = types.bool;
15 default = false;
16 description = ''
17 Whether to enable Open vSwitch. A configuration daemon (ovs-server)
18 will be started.
19 '';
20 };
21
22 package = mkOption {
23 type = types.package;
24 default = pkgs.openvswitch;
25 description = ''
26 Open vSwitch package to use.
27 '';
28 };
29
30 ipsec = mkOption {
31 type = types.bool;
32 default = false;
33 description = ''
34 Whether to start racoon service for openvswitch.
35 '';
36 };
37 };
38
39 config = mkIf cfg.enable (let
40
41 # Where the communication sockets live
42 runDir = "/var/run/openvswitch";
43
44 # Where the config database live (can't be in nix-store)
45 stateDir = "/var/db/openvswitch";
46
47 # The path to the an initialized version of the database
48 db = pkgs.stdenv.mkDerivation {
49 name = "vswitch.db";
50 unpackPhase = "true";
51 buildPhase = "true";
52 buildInputs = with pkgs; [
53 cfg.package
54 ];
55 installPhase = "mkdir -p $out";
56 };
57
58 in (mkMerge [{
59
60 environment.systemPackages = [ cfg.package pkgs.ipsecTools ];
61
62 boot.kernelModules = [ "tun" "openvswitch" ];
63
64 boot.extraModulePackages = [ cfg.package ];
65
66 systemd.services.ovsdb = {
67 description = "Open_vSwitch Database Server";
68 wantedBy = [ "multi-user.target" ];
69 after = [ "systemd-udev-settle.service" ];
70 wants = [ "vswitchd.service" ];
71 path = [ cfg.package ];
72 restartTriggers = [ db cfg.package ];
73 # Create the config database
74 preStart =
75 ''
76 mkdir -p ${runDir}
77 mkdir -p /var/db/openvswitch
78 chmod +w /var/db/openvswitch
79 if [[ ! -e /var/db/openvswitch/conf.db ]]; then
80 ${cfg.package}/bin/ovsdb-tool create \
81 "/var/db/openvswitch/conf.db" \
82 "${cfg.package}/share/openvswitch/vswitch.ovsschema"
83 fi
84 chmod -R +w /var/db/openvswitch
85 '';
86 serviceConfig = {
87 ExecStart =
88 ''
89 ${cfg.package}/bin/ovsdb-server \
90 --remote=punix:${runDir}/db.sock \
91 --private-key=db:Open_vSwitch,SSL,private_key \
92 --certificate=db:Open_vSwitch,SSL,certificate \
93 --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \
94 --unixctl=ovsdb.ctl.sock \
95 --pidfile=/var/run/openvswitch/ovsdb.pid \
96 --detach \
97 /var/db/openvswitch/conf.db
98 '';
99 Restart = "always";
100 RestartSec = 3;
101 PIDFile = "/var/run/openvswitch/ovsdb.pid";
102 Type = "forking";
103 };
104 postStart = ''
105 ${cfg.package}/bin/ovs-vsctl --timeout 3 --retry --no-wait init
106 '';
107 };
108
109 systemd.services.vswitchd = {
110 description = "Open_vSwitch Daemon";
111 bindsTo = [ "ovsdb.service" ];
112 after = [ "ovsdb.service" ];
113 path = [ cfg.package ];
114 serviceConfig = {
115 ExecStart = ''
116 ${cfg.package}/bin/ovs-vswitchd \
117 --pidfile=/var/run/openvswitch/ovs-vswitchd.pid \
118 --detach
119 '';
120 PIDFile = "/var/run/openvswitch/ovs-vswitchd.pid";
121 Type = "forking";
122 };
123 };
124
125 }
126 (mkIf cfg.ipsec {
127 services.racoon.enable = true;
128 services.racoon.configPath = "${runDir}/ipsec/etc/racoon/racoon.conf";
129
130 networking.firewall.extraCommands = ''
131 iptables -I INPUT -t mangle -p esp -j MARK --set-mark 1/1
132 iptables -I INPUT -t mangle -p udp --dport 4500 -j MARK --set-mark 1/1
133 '';
134
135 systemd.services.ovs-monitor-ipsec = {
136 description = "Open_vSwitch Ipsec Daemon";
137 wantedBy = [ "multi-user.target" ];
138 requires = [ "racoon.service" ];
139 after = [ "vswitchd.service" ];
140 environment.UNIXCTLPATH = "/tmp/ovsdb.ctl.sock";
141 serviceConfig = {
142 ExecStart = ''
143 ${cfg.package}/bin/ovs-monitor-ipsec \
144 --root-prefix ${runDir}/ipsec \
145 --pidfile /var/run/openvswitch/ovs-monitor-ipsec.pid \
146 --monitor --detach \
147 unix:/var/run/openvswitch/db.sock
148 '';
149 PIDFile = "/var/run/openvswitch/ovs-monitor-ipsec.pid";
150 Type = "forking";
151 };
152
153 preStart = ''
154 rm -r ${runDir}/ipsec/etc/racoon/certs || true
155 mkdir -p ${runDir}/ipsec/{etc/racoon,etc/init.d/,usr/sbin/}
156 ln -fs ${pkgs.ipsecTools}/bin/setkey ${runDir}/ipsec/usr/sbin/setkey
157 ln -fs ${pkgs.writeScript "racoon-restart" ''
158 #!${pkgs.stdenv.shell}
159 /var/run/current-system/sw/bin/systemctl $1 racoon
160 ''} ${runDir}/ipsec/etc/init.d/racoon
161 '';
162 };
163 })]));
164
165}