Skip to main content

Open5GS — The Reference Core Provider

Open5GS is the default core provider (INSTALL_RACORA_CORE=open5gs, global.core.provider: open5gs). It is why a fresh install brings up a network that real phones can attach to with no external dependency. The image is built from unmodified upstream Open5GS source (AGPL-3.0) in the ocudu repository; the chart is racora-core-open5gs (values).

What It Deploys​

One hostNetwork pod in 5g-core running Open5GS's 5gc entry point (the AMF, SMF, UPF, NRF, SCP, AUSF, UDM, UDR, PCF, NSSF and BSF), MongoDB and the Open5GS WebUI, a Service amf exposing NGAP over SCTP on 38412 and GTP-U on 2152, and a PersistentVolumeClaim open5gs-mongodb for the subscriber database. The claim names no StorageClass, so the cluster's default one provisions it (k3s ships local-path); a cluster you run needs a default StorageClass for this provider. The pod is a singleton rolled with the Recreate strategy: a host-network process cannot be surged. MongoDB binds 127.0.0.1:27017. The WebUI binds port 9999 on the address the node's hostname resolves to: on a stock Ubuntu host that is the loopback alias 127.0.1.1, so it is reachable from the control node or over ssh -L 9999:127.0.1.1:9999 <control node>; on a host whose hostname resolves to a LAN address it listens there, with its own login. ss -ltnp | grep 9999 on the node shows which.

It is pinned with the CU planes (controlPlanePin: true on the k3s platform; your own nodeSelector on a cluster you run, see Install onto an Existing Kubernetes Cluster).

The Identity It Serves​

The PLMN comes from global.network.plmn: the chart splits it into the image's MCC and MNC. Tracking areas 7, 8 and 9 and slice sst 1 are fixed in the image's configuration; the chart refuses a global.network that asks for others at render time, so the mismatch never reaches NG Setup. The default identity (PLMN 90170, TAC 7, sst 1) is what the reference deployment runs.

UE Addresses and Egress​

The UPF hands attached UEs addresses in ueIpBase.0/24 (default 10.45.0). Internet egress goes through the control node: the egress-nat host unit masquerades the UE pool RACORA_UE_CIDR (INSTALL_RACORA_UE_CIDR on the installer, default 10.45.0.0/16, kept across re-runs). Change ueIpBase and the pool together: set racora-core-open5gs.ueIpBase in your values (the HelmChartConfig on k3s) and re-run the server install with INSTALL_RACORA_UE_CIDR=<pool>, which rewrites /etc/racora/core-support.env and restarts the egress unit; a pool that does not contain the UPF's range gets no egress.

Subscribers​

A Subscriber is provisioned into the pod's mongodb by the core controller, through the provider's adapter: the image's own provisioning helpers, run inside the pod, upsert the IMSI with its keys, QoS class and DNN (default internet). An IMSI that is already in the database is adopted: its entry is replaced by what the Subscriber declares. Deleting a Subscriber removes its entry. The database lives on the open5gs-mongodb claim (persistence.enabled, default on, helm.sh/resource-policy: keep), so provisioned SIMs survive pod rolls and upgrades. What an uninstall does with the claim is on Uninstall Racora; a kubectl -n 5g-core delete pvc open5gs-mongodb wipes it deliberately.

The chart also seeds one bootstrap subscriber at every start (subscriber.* values: the image's built-in test SIM). It is provider configuration, not a Subscriber resource; Racora never removes it, and it never conflicts with subscribers you declare.

Back Up and Restore the Database​

The Subscriber objects and the Secrets they reference are the record of what you declared: re-applying them re-provisions every SIM into a fresh database, so keep them with the rest of your manifests. Entries added through the WebUI live only in the database, open5gs in the pod's mongodb; the image carries the MongoDB tools, so dump and restore them through the pod:

kubectl -n 5g-core exec deploy/open5gs -- mongodump --db open5gs --archive > open5gs.archive
kubectl -n 5g-core exec -i deploy/open5gs -- mongorestore --archive --drop < open5gs.archive

Entries added directly through the Open5GS WebUI are left alone as well: the core controller manages only the subscribers it was asked to declare.

What It Needs from the Host​

The control node must allow hostNetwork and privileged pods in 5g-core (no baseline or restricted Pod Security level there), and three host units. The pod runs on the host's network, so it depends on host-level networking that no chart can set up:

UnitWhen it runsWhat it does
fix-resolved-loopbackbefore the cluster runtime, after network-pre.targetOpen5GS creates dummy interfaces lo2 to lo22 with 127.0.0.x/24 addresses, which on the host network take over the addresses systemd-resolved listens on. The unit claims 127.0.0.53 and 127.0.0.54 on lo with /32 masks first, so name resolution keeps working.
nat-sanitizebefore the cluster runtime, and again whenever it restartsOpen5GS's own network setup inserts native nftables masquerade rules without counters on every start, and they accumulate. kube-proxy manages the nat table with iptables-nft and exits on a chain it cannot parse, so the unit removes those rules before kube-proxy starts.
egress-natafter the cluster runtime, and again whenever it restartsadds the source NAT that gives attached UEs internet access: a MASQUERADE for the UE pool leaving through anything but ogstun, plus IP forwarding. It reads the pool from /etc/racora/core-support.env (RACORA_UE_CIDR, the installer's INSTALL_RACORA_UE_CIDR), waits up to about 60 s for a KUBE-POSTROUTING or FLANNEL-POSTRTG chain so its rule lands after the CNI's own, and adds the rule either way.

The scripts live in /opt/racora/core-support/, the pool in /etc/racora/core-support.env, and the three .service files are templates on the cluster runtime's systemd unit (k3s.service on the k3s platform, kubelet.service on a cluster you run). The k3s platform installs all of it on the control node and records the units in /etc/racora/install.env, so the uninstall removes exactly those. On a cluster you run, the steps are on Install onto an Existing Kubernetes Cluster. On a cluster whose CNI provides neither chain (Cilium with kube-proxy replacement), egress-nat.sh adds its rule after the wait; a CNI that restores the nat table later can flush it.

Uninstall​

ran scope removes the pod, the Service and the provider declaration with the release, and the 5g-core namespace with the subscriber claim unless --keep-data keeps it. host scope disables and removes the three units and the pool file, then runs the provider's teardown, which deletes the ogstun TUN device, the lo2 to lo22 interfaces and the UE-pool NAT the core left on the host, so a later install starts clean.