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