Files
nixpkgs/nixos/modules/virtualisation/openvswitch.nix
Ihar Hrachyshka ebdfdea4aa nixos/openvswitch: clean up transient ports on boot
Run transient port cleanup after ovsdb starts and before ovs-vswitchd
starts.

To cite ovs-ctl(8),

  This is important on certain environments where some ports are
  going to be recreated after reboot, but other ports need to be
  persisted in the database.

Consumers (e.g. libvirt or ovn-kubernetes) may mark ports as transient
and expect these ports will be removed from ovsdb on new boot.

Note: this mimics upstream rhel systemd unit:
https://github.com/openvswitch/ovs/blob/main/rhel/usr_lib_systemd_system_ovs-delete-transient-ports.service

Assisted-by: Codex gpt-5.6-sol high
2026-09-07 22:23:27 -04:00

180 lines
5.1 KiB
Nix

# Systemd services for openvswitch
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.virtualisation.vswitch;
in
{
options.virtualisation.vswitch = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable Open vSwitch. A configuration daemon (ovs-server)
will be started.
'';
};
resetOnStart = mkOption {
type = types.bool;
default = false;
description = ''
Whether to reset the Open vSwitch configuration database to a default
configuration on every start of the systemd `ovsdb.service`.
'';
};
package = mkPackageOption pkgs "openvswitch" { };
};
config = mkIf cfg.enable (
let
# Where the communication sockets live
runDir = "/run/openvswitch";
# The path to the an initialized version of the database
db = pkgs.stdenv.mkDerivation {
name = "vswitch.db";
dontUnpack = true;
buildPhase = "true";
buildInputs = [
cfg.package
];
installPhase = "mkdir -p $out";
};
in
{
environment.systemPackages = [ cfg.package ];
boot.kernelModules = [
"tun"
"openvswitch"
];
boot.extraModulePackages = [ cfg.package ];
systemd.sockets.ovsdb = {
description = "Open_vSwitch Database Socket";
wantedBy = [ "sockets.target" ];
before = [ "ovsdb.service" ];
socketConfig = {
ListenStream = "${runDir}/db.sock";
Service = "ovsdb.service";
SocketMode = "0770";
};
};
systemd.services.ovsdb = {
description = "Open_vSwitch Database Server";
wantedBy = [ "multi-user.target" ];
requires = [ "ovsdb.socket" ];
after = [ "ovsdb.socket" ];
wants = [ "ovs-delete-transient-ports.service" ];
path = [ cfg.package ];
restartTriggers = [
db
cfg.package
];
# Create the config database
preStart = ''
mkdir -p ${runDir}
mkdir -p /var/db/openvswitch
chmod +w /var/db/openvswitch
${optionalString cfg.resetOnStart "rm -f /var/db/openvswitch/conf.db"}
if [[ ! -e /var/db/openvswitch/conf.db ]]; then
${cfg.package}/bin/ovsdb-tool create \
"/var/db/openvswitch/conf.db" \
"${cfg.package}/share/openvswitch/vswitch.ovsschema"
fi
chmod -R +w /var/db/openvswitch
if ${cfg.package}/bin/ovsdb-tool needs-conversion /var/db/openvswitch/conf.db | grep -q "yes"
then
echo "Performing database upgrade"
${cfg.package}/bin/ovsdb-tool convert /var/db/openvswitch/conf.db
else
echo "Database already up to date"
fi
'';
serviceConfig = {
ExecStart = ''
${cfg.package}/bin/ovsdb-server \
--remote=pfd:3 \
--private-key=db:Open_vSwitch,SSL,private_key \
--certificate=db:Open_vSwitch,SSL,certificate \
--bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \
--unixctl=ovsdb.ctl.sock \
--pidfile=/run/openvswitch/ovsdb.pid \
--detach \
/var/db/openvswitch/conf.db
'';
Restart = "always";
RestartMode = "direct";
RestartSec = 3;
PIDFile = "/run/openvswitch/ovsdb.pid";
# Use service type 'forking' to correctly determine when ovsdb-server is ready.
Type = "forking";
};
postStart = ''
${cfg.package}/bin/ovs-vsctl --timeout 3 --retry --no-wait init
'';
};
systemd.services.ovs-delete-transient-ports = {
description = "Open vSwitch Delete Transient Ports";
after = [ "ovsdb.service" ];
before = [ "ovs-vswitchd.service" ];
path = [ cfg.package ];
unitConfig.AssertPathExists = "${runDir}/db.sock";
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${cfg.package}/share/openvswitch/scripts/ovs-ctl delete-transient-ports";
};
};
systemd.services.ovs-vswitchd = {
description = "Open_vSwitch Daemon";
wantedBy = [ "multi-user.target" ];
requires = [ "ovsdb.socket" ];
after = [ "ovsdb.socket" ];
path = [ cfg.package ];
serviceConfig = {
ExecStart = ''
${cfg.package}/bin/ovs-vswitchd \
--pidfile=/run/openvswitch/ovs-vswitchd.pid \
--detach
'';
PIDFile = "/run/openvswitch/ovs-vswitchd.pid";
# Use service type 'forking' to correctly determine when vswitchd is ready.
Type = "forking";
Restart = "always";
RestartMode = "direct";
RestartSec = 3;
};
};
}
);
imports = [
(mkRemovedOptionModule [ "virtualisation" "vswitch" "ipsec" ] ''
OpenVSwitch IPSec functionality has been removed, because it depended on racoon,
which was removed from nixpkgs, because it was abanoded upstream.
'')
];
meta.maintainers = with maintainers; [ netixx ];
}