From 0298d484f13e7f7479fd17d9cad20b3d7206b3ac Mon Sep 17 00:00:00 2001 From: Luke Granger-Brown Date: Sun, 11 Aug 2024 18:13:10 +0100 Subject: [PATCH] ops/nixos/lib/open5gs: init --- nix/pkgs/srsran5g/default.nix | 8 +- ops/nixos/lib/open5gs.nix | 787 +++++++++++++++++++++++++++++++++ ops/nixos/nausicaa/default.nix | 1 + 3 files changed, 794 insertions(+), 2 deletions(-) create mode 100644 ops/nixos/lib/open5gs.nix diff --git a/nix/pkgs/srsran5g/default.nix b/nix/pkgs/srsran5g/default.nix index e28a5fcd4b..c3b62b457e 100644 --- a/nix/pkgs/srsran5g/default.nix +++ b/nix/pkgs/srsran5g/default.nix @@ -4,7 +4,7 @@ , cmake , ninja , pkg-config -, fftw +, fftwFloat , lksctp-tools , yaml-cpp , mbedtls @@ -12,6 +12,8 @@ , elfutils , libbfd , libdwarf + +, soapysdr-with-plugins }: stdenv.mkDerivation { @@ -42,7 +44,7 @@ stdenv.mkDerivation { ]; buildInputs = [ - fftw + fftwFloat lksctp-tools yaml-cpp mbedtls @@ -50,5 +52,7 @@ stdenv.mkDerivation { elfutils # libdw libbfd libdwarf + + soapysdr-with-plugins ]; } diff --git a/ops/nixos/lib/open5gs.nix b/ops/nixos/lib/open5gs.nix new file mode 100644 index 0000000000..af72b45285 --- /dev/null +++ b/ops/nixos/lib/open5gs.nix @@ -0,0 +1,787 @@ +# SPDX-FileCopyrightText: 2024 Luke Granger-Brown +# +# SPDX-License-Identifier: Apache-2.0 + +{ lib, config, depot, yaml, pkgs, ... }: + +let + cfg = config.my.services.open5gs; + + settingsFormat = pkgs.formats.yaml {}; +in +{ + options.my.services.open5gs = let + package = lib.mkOption { + type = lib.types.package; + default = depot.nix.pkgs.open5gs; + }; + settings = lib.mkOption { + type = lib.types.submodule { + freeformType = settingsFormat.type; + }; + default = {}; + }; + in { + enable = lib.mkEnableOption "Open5GS"; + inherit package; + globalSettings = settings; + enableSAComponents = (lib.mkEnableOption "default Open5GS components for 5G SA core") // { + default = true; + }; + enableNSAComponents = (lib.mkEnableOption "default Open5GS components for 4G/5G NSA core") // { + default = true; + }; + webui = { + enable = lib.mkEnableOption "Open5GS WebUI"; + package = lib.mkOption { + type = lib.types.package; + default = depot.nix.pkgs.open5gs.webui; + }; + + secretKeyFile = lib.mkOption { + type = lib.types.path; + }; + databaseURI = lib.mkOption { + type = lib.types.str; + default = "mongodb://localhost/open5gs"; + }; + listenHostname = lib.mkOption { + type = lib.types.str; + default = "localhost"; + }; + listenPort = lib.mkOption { + type = lib.types.port; + default = 9999; + }; + }; + + nrf = { + enable = lib.mkEnableOption "Open5GS NF Repository Function"; + inherit package settings; + }; + scp = { + enable = lib.mkEnableOption "Open5GS Service Communication Proxy"; + inherit package settings; + }; + sepp = { + enable = lib.mkEnableOption "Open5GS Security Edge Protection Proxy"; + inherit package settings; + }; + amf = { + enable = lib.mkEnableOption "Open5GS Access and Mobility Management Function"; + inherit package settings; + }; + smf = { + enable = lib.mkEnableOption "Open5GS Session Management Function"; + inherit package settings; + }; + upf = { + enable = lib.mkEnableOption "Open5GS User Plane Function"; + inherit package settings; + }; + ausf = { + enable = lib.mkEnableOption "Open5GS Authentication Server Function"; + inherit package settings; + }; + udm = { + enable = lib.mkEnableOption "Open5GS Unified Data Management"; + inherit package settings; + }; + udr = { + enable = lib.mkEnableOption "Open5GS Unified Data Repository"; + inherit package settings; + }; + pcf = { + enable = lib.mkEnableOption "Policy and Charging Function"; + inherit package settings; + }; + nssf = { + enable = lib.mkEnableOption "Network Slice Selection Function"; + inherit package settings; + }; + bsf = { + enable = lib.mkEnableOption "Binding Support Function"; + inherit package settings; + }; + + mme = { + enable = lib.mkEnableOption "Mobility Management Entity"; + inherit package settings; + }; + hss = { + enable = lib.mkEnableOption "Home Subscriber Server"; + inherit package settings; + }; + pcrf = { + enable = lib.mkEnableOption "Policy and Charging Rules Function"; + inherit package settings; + }; + sgwc = { + enable = lib.mkEnableOption "Serving Gateway Control Plane"; + inherit package settings; + }; + sgwu = { + enable = lib.mkEnableOption "Serving Gateway User Plane"; + inherit package settings; + }; + }; + + config = let + mkComponent = componentCfg: componentName: defaultSettings: lib.mkIf componentCfg.enable { + my.services.open5gs."${componentName}".settings = lib.mkMerge [cfg.globalSettings { + logger.file.path = lib.mkDefault "/var/log/open5gs/${componentName}.log"; + } defaultSettings]; + environment.etc."open5gs/${componentName}.yaml".source = settingsFormat.generate "open5gs-${componentName}-config.yaml" componentCfg.settings; + systemd.services."open5gs-${componentName}" = { + wantedBy = [ "open5gs.target" ]; + restartTriggers = [ config.environment.etc."open5gs/${componentName}.yaml".source or null ]; + serviceConfig = { + LogsDirectory = "open5gs"; + ExecStart = "${componentCfg.package}/bin/open5gs-${componentName}d -c /etc/open5gs/${componentName}.yaml"; + }; + }; + }; + in lib.mkIf cfg.enable (lib.mkMerge [ + { + services.mongodb.enable = lib.mkDefault true; + my.services.open5gs = { + nrf.enable = lib.mkDefault cfg.enableSAComponents; + nrf.package = lib.mkDefault cfg.package; + scp.enable = lib.mkDefault cfg.enableSAComponents; + scp.package = lib.mkDefault cfg.package; + sepp.enable = lib.mkDefault cfg.enableSAComponents; + sepp.package = lib.mkDefault cfg.package; + amf.enable = lib.mkDefault cfg.enableSAComponents; + amf.package = lib.mkDefault cfg.package; + smf.enable = lib.mkDefault (cfg.enableSAComponents || cfg.enableNSAComponents); + smf.package = lib.mkDefault cfg.package; + upf.enable = lib.mkDefault (cfg.enableSAComponents || cfg.enableNSAComponents); + upf.package = lib.mkDefault cfg.package; + ausf.enable = lib.mkDefault cfg.enableSAComponents; + ausf.package = lib.mkDefault cfg.package; + udm.enable = lib.mkDefault cfg.enableSAComponents; + udm.package = lib.mkDefault cfg.package; + udr.enable = lib.mkDefault cfg.enableSAComponents; + udr.package = lib.mkDefault cfg.package; + pcf.enable = lib.mkDefault cfg.enableSAComponents; + pcf.package = lib.mkDefault cfg.package; + nssf.enable = lib.mkDefault cfg.enableSAComponents; + nssf.package = lib.mkDefault cfg.package; + bsf.enable = lib.mkDefault cfg.enableSAComponents; + bsf.package = lib.mkDefault cfg.package; + mme.enable = lib.mkDefault cfg.enableNSAComponents; + mme.package = lib.mkDefault cfg.package; + hss.enable = lib.mkDefault cfg.enableNSAComponents; + hss.package = lib.mkDefault cfg.package; + pcrf.enable = lib.mkDefault cfg.enableNSAComponents; + pcrf.package = lib.mkDefault cfg.package; + sgwc.enable = lib.mkDefault cfg.enableNSAComponents; + sgwc.package = lib.mkDefault cfg.package; + sgwu.enable = lib.mkDefault cfg.enableNSAComponents; + sgwu.package = lib.mkDefault cfg.package; + webui.enable = lib.mkDefault (cfg.enableSAComponents || cfg.enableNSAComponents); + + globalSettings = { + db_uri = lib.mkDefault "mongodb://localhost/open5gs"; + logger.level = lib.mkDefault "info"; + global = { + max.ue = lib.mkDefault 1024; + parameter = { + no_nrf = lib.mkDefault (!cfg.enableSAComponents); + no_scp = lib.mkDefault (!cfg.enableSAComponents); + no_sepp = lib.mkDefault (!cfg.enableSAComponents); + no_amf = lib.mkDefault (!cfg.enableSAComponents); + no_smf = lib.mkDefault (!cfg.enableSAComponents && !cfg.enableNSAComponents); + no_upf = lib.mkDefault (!cfg.enableSAComponents && !cfg.enableNSAComponents); + no_ausf = lib.mkDefault (!cfg.enableSAComponents); + no_udm = lib.mkDefault (!cfg.enableSAComponents); + no_udr = lib.mkDefault (!cfg.enableSAComponents); + no_pcf = lib.mkDefault (!cfg.enableSAComponents); + no_nssf = lib.mkDefault (!cfg.enableSAComponents); + no_bsf = lib.mkDefault (!cfg.enableSAComponents); + + no_mme = lib.mkDefault (!cfg.enableNSAComponents); + no_sgwc = lib.mkDefault (!cfg.enableNSAComponents); + no_sgwu = lib.mkDefault (!cfg.enableNSAComponents); + no_pcrf = lib.mkDefault (!cfg.enableNSAComponents); + no_hss = lib.mkDefault (!cfg.enableNSAComponents); + }; + }; + }; + }; + + users.groups.open5gs = {}; + + systemd.targets.open5gs = { + description = "Open5GS"; + wantedBy = [ "multi-user.target" ]; + }; + } + (lib.mkIf cfg.webui.enable { + systemd.services.open5gs-webui = { + wantedBy = [ "open5gs.target" ]; + script = '' + export SECRET_KEY="$(cat "''${CREDENTIALS_DIRECTORY}/secret_key")" + exec ${cfg.webui.package}/bin/open5gs-webui + ''; + serviceConfig = { + LoadCredential = "secret_key:${cfg.webui.secretKeyFile}"; + DynamicUser = true; + User = "open5gs-webui"; + Group = "open5gs"; + }; + environment = { + SECRET_KEY = cfg.webui.secretKeyFile; + DB_URI = cfg.webui.databaseURI; + HOSTNAME = cfg.webui.listenHostname; + PORT = toString cfg.webui.listenPort; + }; + }; + }) + (mkComponent cfg.nrf "nrf" { + nrf = lib.mkDefault { + serving = [ + { + plmn_id = { + mcc = 999; + mnc = 42; + }; + } + ]; + sbi.server = [ + { + address = "127.0.0.10"; + port = 7777; + } + ]; + }; + }) + (mkComponent cfg.scp "scp" { + scp = lib.mkDefault { + sbi = { + server = [ + { + address = "127.0.0.200"; + port = 7777; + } + ]; + client = { + nrf = [ + { + uri = "http://127.0.0.10:7777"; + } + ]; + }; + }; + }; + }) + (mkComponent cfg.sepp "sepp" { + sepp = lib.mkDefault { + default.tls = { + server = { + private_key = "${cfg.sepp.package}/etc/open5gs/tls/sepp1.key"; + cert = "${cfg.sepp.package}/etc/open5gs/tls/sepp1.crt"; + }; + client = { + cacert = "${cfg.sepp.package}/etc/open5gs/tls/ca.crt"; + }; + }; + sbi = { + server = [ + { + address = "127.0.1.250"; + port = 7777; + } + ]; + client = { + scp = [ + { + uri = "http://127.0.0.200:7777"; + } + ]; + }; + }; + n32 = { + server = [ + { + sender = "sepp1.localdomain"; + scheme = "https"; + address = "127.0.1.251"; + port = 7777; + n32f = { + scheme = "https"; + address = "127.0.1.252"; + port = 7777; + }; + } + ]; + }; + }; + }) + (mkComponent cfg.amf "amf" { + amf = lib.mkDefault { + sbi = { + server = [ + { + address = "127.0.0.5"; + port = 7777; + } + ]; + client = { + scp = [ + { + uri = "http://127.0.0.200:7777"; + } + ]; + }; + }; + ngap.server = [ + { + address = "127.0.0.5"; + } + ]; + metrics.server = [ + { + address = "127.0.0.5"; + port = 9090; + } + ]; + guami = [ + { + plmn_id = { + mcc = 999; + mnc = 42; + }; + amf_id = { + region = 2; + set = 1; + }; + } + ]; + tai = [ + { + plmn_id = { + mcc = 999; + mnc = 42; + }; + tac = 1; + } + ]; + plmn_support = [ + { + plmn_id = { + mcc = 999; + mnc = 42; + }; + s_nssai = [ + { + sst = 1; + } + ]; + } + ]; + security = { + integrity_order = [ + "NIA2" + "NIA1" + "NIA0" + ]; + ciphering_order = [ + "NEA0" + "NEA1" + "NEA2" + ]; + }; + network_name = { + full = "Open5GS"; + short = "Next"; + }; + amf_name = "open5gs-amf0"; + time.t3512.value = 540; + }; + }) + (mkComponent cfg.smf "smf" { + smf = lib.mkDefault { + sbi = { + server = [ + { + address = "127.0.0.4"; + port = 7777; + } + ]; + client = { + scp = [ + { + uri = "http://127.0.0.200:7777"; + } + ]; + }; + }; + pfcp = { + server = [ + { + address = "127.0.0.4"; + } + ]; + client = { + upf = [ + { + address = "127.0.0.7"; + } + ]; + }; + }; + gtpc.server = [ + { + address = "127.0.0.4"; + } + ]; + gtpu.server = [ + { + address = "127.0.0.4"; + } + ]; + metrics.server = [ + { + address = "127.0.0.4"; + port = 9090; + } + ]; + session = [ + { + subnet = "10.45.0.0/16"; + gateway = "10.45.0.1"; + } + { + subnet = "2001:db8:cafe::/48"; + gateway = "2001:db8:cafe::1"; + } + ]; + dns = [ + "8.8.8.8" + "8.8.4.4" + "2001:4860:4860::8888" + "2001:4860:4860::8844" + ]; + mtu = 1400; + freeDiameter = "${cfg.smf.package}/etc/freeDiameter/smf.conf"; + }; + }) + (mkComponent cfg.upf "upf" { + upf = lib.mkDefault { + pfcp = { + server = [ + { + address = "127.0.0.7"; + } + ]; + client = null; + }; + gtpu.server = [ + { + address = "127.0.0.7"; + } + ]; + session = [ + { + subnet = "10.45.0.0/16"; + gateway = "10.45.0.1"; + } + { + subnet = "2001:db8:cafe::/48"; + gateway = "2001:db8:cafe::1"; + } + ]; + metrics.server = [ + { + address = "127.0.0.7"; + port = 9090; + } + ]; + }; + }) + (mkComponent cfg.ausf "ausf" { + ausf = lib.mkDefault { + sbi = { + server = [ + { + address = "127.0.0.11"; + port = 7777; + } + ]; + client = { + scp = [ + { + uri = "http://127.0.0.200:7777"; + } + ]; + }; + }; + }; + }) + (mkComponent cfg.udm "udm" { + udm = lib.mkDefault { + hnet = [ + { + id = 1; + scheme = 1; + key = "${cfg.udm.package}/etc/open5gs/hnet/curve25519-1.key"; + } + { + id = 2; + scheme = 2; + key = "${cfg.udm.package}/etc/open5gs/hnet/secp256r1-2.key"; + } + { + id = 3; + scheme = 1; + key = "${cfg.udm.package}/etc/open5gs/hnet/curve25519-3.key"; + } + { + id = 4; + scheme = 2; + key = "${cfg.udm.package}/etc/open5gs/hnet/secp256r1-4.key"; + } + { + id = 5; + scheme = 1; + key = "${cfg.udm.package}/etc/open5gs/hnet/curve25519-5.key"; + } + { + id = 6; + scheme = 2; + key = "${cfg.udm.package}/etc/open5gs/hnet/secp256r1-6.key"; + } + ]; + sbi = { + server = [ + { + address = "127.0.0.12"; + port = 7777; + } + ]; + client = { + scp = [ + { + uri = "http://127.0.0.200:7777"; + } + ]; + }; + }; + }; + }) + (mkComponent cfg.udr "udr" { + udr = lib.mkDefault { + sbi = { + server = [ + { + address = "127.0.0.20"; + port = 7777; + } + ]; + client = { + scp = [ + { + uri = "http://127.0.0.200:7777"; + } + ]; + }; + }; + }; + }) + (mkComponent cfg.pcf "pcf" { + pcf = lib.mkDefault { + sbi = { + server = [ + { + address = "127.0.0.13"; + port = 7777; + } + ]; + client = { + scp = [ + { + uri = "http://127.0.0.200:7777"; + } + ]; + }; + }; + metrics.server = [ + { + address = "127.0.0.13"; + port = 9090; + } + ]; + }; + }) + (mkComponent cfg.nssf "nssf" { + nssf = lib.mkDefault { + sbi = { + server = [ + { + address = "127.0.0.14"; + port = 7777; + } + ]; + client = { + scp = [ + { + uri = "http://127.0.0.200:7777"; + } + ]; + nsi = [ + { + uri = "http://127.0.0.10:7777"; + s_nssai = { + sst = 1; + }; + } + ]; + }; + }; + }; + }) + (mkComponent cfg.bsf "bsf" { + bsf = lib.mkDefault { + sbi = { + server = [ + { + address = "127.0.0.15"; + port = 7777; + } + ]; + client = { + scp = [ + { + uri = "http://127.0.0.200:7777"; + } + ]; + }; + }; + }; + }) + + (mkComponent cfg.mme "mme" { + mme = lib.mkDefault { + freeDiameter = "${cfg.mme.package}/etc/freeDiameter/mme.conf"; + s1ap.server = [ + { + address = "127.0.0.2"; + } + ]; + gtpc = { + server = [ + { + address = "127.0.0.2"; + } + ]; + client = { + sgwc = [ + { + address = "127.0.0.3"; + } + ]; + smf = [ + { + address = "127.0.0.4"; + } + ]; + }; + }; + metrics.server = [ + { + address = "127.0.0.2"; + port = 9090; + } + ]; + gummei = [ + { + plmn_id = { + mcc = 999; + mnc = 42; + }; + mme_gid = 2; + mme_code = 1; + } + ]; + tai = [ + { + plmn_id = { + mcc = 999; + mnc = 42; + }; + tac = 1; + } + ]; + security = { + integrity_order = [ + "EIA2" + "EIA1" + "EIA0" + ]; + ciphering_order = [ + "EEA0" + "EEA1" + "EEA2" + ]; + }; + network_name = { + full = "Open5GS"; + short = "Next"; + }; + mme_name = "open5gs-mme0"; + time = null; + }; + }) + (mkComponent cfg.hss "hss" { + hss = lib.mkDefault { + freeDiameter = "${cfg.hss.package}/etc/freeDiameter/hss.conf"; + }; + }) + (mkComponent cfg.pcrf "pcrf" { + pcrf = lib.mkDefault { + freeDiameter = "${cfg.pcrf.package}/etc/freeDiameter/pcrf.conf"; + }; + }) + (mkComponent cfg.sgwc "sgwc" { + sgwc = lib.mkDefault { + gtpc.server = [ + { + address = "127.0.0.3"; + } + ]; + pfcp = { + server = [ + { + address = "127.0.0.3"; + } + ]; + client = { + sgwu = [ + { + address = "127.0.0.6"; + } + ]; + }; + }; + }; + }) + (mkComponent cfg.sgwu "sgwu" { + sgwu = lib.mkDefault { + pfcp = { + server = [ + { + address = "127.0.0.6"; + } + ]; + client = null; + }; + gtpu.server = [ + { + address = "127.0.0.6"; + } + ]; + }; + }) + ]); +} diff --git a/ops/nixos/nausicaa/default.nix b/ops/nixos/nausicaa/default.nix index cc73b41a2f..a81cc6c049 100644 --- a/ops/nixos/nausicaa/default.nix +++ b/ops/nixos/nausicaa/default.nix @@ -318,6 +318,7 @@ in { }; my.services.open5gs.enable = true; + my.services.open5gs.webui.secretKeyFile = pkgs.writeText "open5gs-webui-not-so-secret-key" "not-very-secret"; # This value determines the NixOS release with which your system is to be # compatible, in order to avoid breaking some software such as database