41 articles
Universal (RM551E & RM520N)

System Architecture & CGI Execution Model

Deep dive into QManager's stateless CGI design, uhttpd/lighttpd daemon bindings, and minimal resource footprint.

5 min read · Updated

System Architecture & CGI Execution Model

Designed from the ground up for low-power embedded platforms with limited memory.

Stateless Execution Model#

Traditional web applications require heavy Node.js or Python runtimes that consume 150MB+ RAM. On an embedded router with 128MB or 256MB total RAM, this is unacceptable.

QManager adopts a stateless, micro-CGI architecture:

  • The Next.js frontend is fully compiled into static HTML/CSS/JavaScript and pre-rendered.
  • Web requests are served by ultra-lightweight web daemons: uhttpd on OpenWRT (written in C) or lighttpd on RM520N.
  • API endpoints are lightweight POSIX shell scripts (/bin/sh).
  • When a client sends a POST request, the web server executes the specific script, returns JSON, and immediately terminates.

POSIX Shell CGI Backend#

Located in /www/cgi-bin/quecmanager/ (on OpenWRT) or /usrdata/qmanager/www/cgi-bin/quecmanager/ (on RM520N Native Linux):

  • Zero external interpreter dependencies.
  • Uses jsonfilter or lightweight jq/awk/sed to parse and output JSON.
  • Average response time: < 15ms.

Daemon IPC & Shared Memory#

For operations requiring persistent state (like telemetry history or AT serial locking via qcmd), QManager utilizes shared memory in tmpfs (/tmp/ and /tmp/qmlive/). Multiple processes read and write via atomic file swaps and POSIX flock without incurring NAND flash wear.

RootFS Overlays & Entware Bind Mounts (sdxpinn-mount-fix)#

Deploying complex userland tooling on embedded modem flash partitions requires solving storage and filesystem constraints:

1. RM551E / SDXPINN OpenWRT Overlay Mechanics#

On the Quectel RM551E, the base operating system runs from a read-only compressed SquashFS partition. Writable directories are provided via an OverlayFS layer backed by the persistent /usrdata partition. Upstream research by Cameron Thompson (iamromulan) developed the sdxpinn-mount-fix script:

  • In factory firmware, early boot initialization mounted /usrdata after fstab services, resulting in a read-only rootfs fallback.
  • The sdxpinn-mount-fix intercepts early init to mount the persistent flash block directly before procd begins spawning services, ensuring persistent packages, custom scripts, and QManager assets survive modem reboots without filesystem corruption.

2. SDXLEMUR Linux: Entware /usrdata/opt Bind Mount#

On the RM520N-GL running Poky Linux, the root directory (/) has only ~5 MB of free space, while /usrdata has over 350 MB:

  • The standard Entware package manager expects binaries and libraries located in /opt.
  • QManager solves this by creating a directory at /usrdata/opt and mounting it over /opt via systemd bind-mount during boot:
    Shell
    mount --bind /usrdata/opt /opt
  • This enables full access to opkg, lighttpd, and standard GNU utilities without filling up the modem's root filesystem.

NAND Wear Protection: Volatile journald Logging#

Industrial cellular modems use SLC or MLC NAND flash chips with finite erase cycles. Writing continuous debug and polling logs to disk will prematurely wear out flash sectors within months.

QManager configures systemd's logging daemon (/etc/systemd/journald.conf) into volatile RAM mode:

INI
[Journal]
Storage=volatile
RuntimeMaxUse=16M
  • All system and daemon logs reside strictly in memory (RAM).
  • Total log buffer size is capped at 16 MB.
  • High-frequency live polling logs are discarded automatically when memory limits are reached, resulting in zero NAND flash write cycles during normal 24/7 telemetry collection.

Status of the overhaul-SDXLEMUR Branch#

In the upstream community (e.g. Cameron Thompson's repositories), researchers explored the overhaul-SDXLEMUR project—an effort to replace the Qualcomm Poky/Yocto Linux userland with a clean Debian or Alpine ARM rootfs.