Quickstart: Full Lab Stack Without RF (30 minutes)¶
This tutorial gets a complete private LTE network running on your laptop in about 30 minutes. Nothing is transmitted: the eNB and UE talk to each other over srsRAN's ZMQ virtual radio, inside Docker, end to end.
Prerequisites¶
| Requirement | Minimum | Notes |
|---|---|---|
| Docker Engine | 24+ | Docker Compose v2 included |
| RAM | 4 GB | make compact-up for 4 GB; 8–16 GB comfortable for make lab-up |
| Disk | 10 GB free | Container images |
| Go | 1.22+ | Only needed to build fairwave-cli |
| OS | Linux, macOS, or Windows (WSL2) | Lab stack runs in containers |
You do not need an SDR, a SIM card, a license, or any RF gear for this tutorial.
1. Clone and bootstrap¶
Expected output (abridged):
[fairwave] checking prerequisites... ok (docker 26.1.4, 16 GB RAM)
[fairwave] pulling images (open5gs, srsran, fairwave-control)...
[fairwave] initializing mongo seed data (plmn 999-99, tac 7)...
[fairwave] bootstrap complete in 42s
bootstrap.sh verifies the environment and writes the local lab config under deploy/config/.
2. Build the CLI¶
Expected output:
If you do not want to build from source, a signed release binary is available in the v0.1.0 release assets (see release signing).
3. Bring the lab up¶
Expected output (abridged):
[+] Running 6/6
Container fairwave-mongo-1 Started
Container fairwave-open5gs-1 Started
Container fairwave-enb-1 Started
Container fairwave-ue-1 Started
Container fairwave-control-plane-1 Started
lab stack up: control-plane http://127.0.0.1:8080/v1/healthz
This starts Mongo, Open5GS, the ZMQ eNB, the ZMQ UE, and the control plane. No SDR is touched. Verify:
STATE: on-air
PLMN: 999-99 TAC: 7
eNB: connected (zmq virtual radio)
UE: registered
APNs: internet, ims
4. Mint a lab SIM¶
Expected output:
issued 1 lab SIM
IMSI 9999912345678901 (lab)
ICCID 8999990123456789012
output sims/2026-08-02/ (sims.csv, sims.json, hss-hook.sh)
NOTE Ki/OPc written to local files only; never committed.
The provisioner writes Ki/OPc material locally, hashes them at rest, and renders a HSS load script. The lab profile is auto-loaded into the Open5GS HSS in lab mode via the provisioner hook.
5. Verify the attach¶
make lab-up runs the assert script (tests/e2e-sim/assert-lab-up.sh), which verifies:
- Open5GS MME + HSS running
- eNB S1-MME connected to the MME
- UE RRC connection + random access on the lab PLMN
- UE NAS authentication + security mode (milenage against HSS)
- MME creates the default EPS bearer and allocates a UE IP
Watch it live:
docker compose -f deploy/docker-compose.yml logs ue1 | grep -E "RRC|Attach|Security"
docker compose -f deploy/docker-compose.yml logs open5gs | grep -E "Bearer added|Attach accept"
Expected lines (EPC side completes in all environments):
[ue1] RRC Connected
[ue1] Random Access Complete. c-rnti=0x48, ta=0
[ue1] Received Security Mode Command ... eia: 128-EIA2
[open5gs] Attach accept
[open5gs] Bearer added (EBI=5 IMSI=999991234567001)
[!NOTE] The final hop - UE IP visible on
tun_srsueand ping through it - needs stable ZMQ timing. It passes on native Linux. Under Docker Desktop (Windows/macOS) the UE PHY can lose subframe sync and the attach accept is not delivered over the virtual radio, even though the EPC-side attach completes. See lab attach deep dive for details and the host recommendation.
6. Tear down¶
The lab leaves no persistent RF state behind. To wipe subscriber data entirely, run docker compose -f deploy/docker-compose.yml down -v (or make lab-down which does the same).
What you just ran¶
| Layer | Component |
|---|---|
| EPC | Open5GS (MME/SGW/PGW/HSS) |
| Radio | srsRAN eNB on ZMQ virtual radio |
| Handset | srsUE on ZMQ virtual radio |
| Control plane | fairwave-control + fairwave-agent |
| Operator UI | Available at http://127.0.0.1:8081 |
Next steps¶
- Deep dive: lab attach internals and troubleshooting.
- Issue your first SIM properly: SIM issuance tutorial.
- Two nodes, one mesh: two-box peering.
- Change PLMN, TAC, bands: customization.