Locating SIMATIC IoT2000 Example Image V2.1.3 and Updating NodeJS
The SIMATIC IoT2000 family comprises the IoT2020, IoT2040, and IoT2050 gateways. Engineers who built long-running field installations on the legacy Example Image V2.1.3 frequently hit three walls simultaneously: the image is no longer published on the Siemens download portal, NodeJS upgrades above v6 fail silently on the Quark SoC inside the IoT2040, and the Siemens meta-iot2000 GitHub releases page marks V3.1.17 as the final offical Example Image. This reference documents the recovery procedure, the exact compatibility boundaries for the NodeJS runtime, the Yocto BSP path for a custom image, and the field-proven migration steps toward the SIMATIC IOT2050 successor.
1. Hardware Distinction: Quark vs Apollo Lake
Selecting the right image begins with the silicon. The IoT2000 series is split into two incompatible hardware generations, and each ships a different Yocto BSP layer in meta-iot2000.
| Parameter | IoT2020 / IoT2040 | IoT2050 |
|---|---|---|
| SoC | Intel Quark x1024D (x86, single core, no SSE) | Intel Apollo Lake (x86_64, multi-core, SSE 4.2 + AES-NI) |
| CPU micro-architecture | Pentium-class, in-order | Goldmont, out-of-order |
| SIMD support | None (no SSE family instructions) | SSE 4.2, AVX 2 (selected SKUs) |
| RAM | 256 MB / 1 GB DDR3 | 2 GB / 4 GB / 8 GB DDR4 |
| Storage | 8 GB eMMC + microSD | 16 GB / 32 GB eMMC + NVMe |
| Example Image lineage | V1.x through V2.x (Quark BSP) | V3.0.0 through V3.1.17 (Apollo Lake BSP) |
| NodeJS practical ceiling | v6 LTS, partial v8 via Yocto thud | v12, v14, v16, v18 LTS (community-built) |
The lack of SSE on the Quark is the root cause of every NodeJS upgrade failure on the IoT2020/IoT2040. The upstream NodeJS project dropped x86 builds without SSE2 in 2017. Native modules that depend on V8's TurboFan, Crankshaft, or any crypto primitive that uses SSE-accelerated routines will SIGILL immediately on Quark.
2. Example Image Release History
The Siemens Example Image is a pre-built SD card / eMMC image containing a Poky / Yocto userspace, the iot2000setup tool, Eclipse Mosquitto, Node-RED, the libmraa / libupm I/O bindings, and a default NodeJS v6 runtime. Every release is tagged in the meta-iot2000 releases page.
| Image | SoC target | Yocto branch | NodeJS default | Notes |
|---|---|---|---|---|
| V1.1.x | IoT2020 (Quark) | Jethro | v0.10 / v4 | Initial public release; obsolete |
| V1.2.x | IoT2020 | Krogoth | v4 LTS | opkg feeds introduced |
| V2.1.3 | IoT2020 / IoT2040 | Pyro | v6 LTS | First image with n npm package pre-installed for user-space upgrades |
| V2.1.4 | IoT2020 / IoT2040 | Pyro | v6 LTS | Security patch backport |
| V2.1.5 | IoT2020 / IoT2040 | Pyro | v6 LTS | Last Pyro-branch release |
| V2.2.0 | IoT2020 / IoT2040 | Rocko | v6 LTS | Dropped n; switched to opkg only |
| V2.3.x | IoT2020 / IoT2040 | Thud | v8 LTS | Experimental SSE-stripped V8 patch |
| V3.0.0 | IoT2050 only | Warrior | v10 LTS | Apollo Lake generation begins |
| V3.1.17 | IoT2050 only | Dunfell | v12 LTS | Final official Example Image from Siemens |
The official meta-iot2000 release index confirms that V3.1.17 is the last tag Siemens ships. The repository has been archived; the maintainers explicitly direct new work to the IOT2050 hardware platform and the Dunfell-based BSP.
3. Why V2.1.3 Is Sought After
Engineers returning to long-running IoT2040 installations frequently report that V2.1.3 was the last image that combined three field-useful behaviors:
-
Pre-installed
npackage. V2.1.3 shipped with thenNodeJS version manager and an unmodified npm cache.n 10.13.0in-place upgrades succeeded for many users, even though the binaries that landed were V8 builds later patched downstream. -
Pyro kernel + userspace with a relaxed
opkg.confthat allowed third-party feeds. - Working libmraa / libupm bindings for the on-board Arduino shield header, which later releases restricted through signature verification.
The trade-off is real: V2.1.3 has unpatched CVEs in openssl, busybox, and the kernel. It must not be exposed to an untrusted network. Treat any V2.1.3 deployment as air-gapped or behind a stateful firewall.
4. NodeJS Compatibility Matrix on the IoT2000 Family
Use the table below to select a runtime for a specific hardware revision. Crossing the dashed boundary produces SIGILL or V8 aborts on the Quark.
| NodeJS version | IoT2020 / IoT2040 (Quark) | IoT2050 (Apollo Lake) |
|---|---|---|
| v0.10 / v4 | Works (deprecated upstream) | Works |
| v6 LTS | Officially supported; default in V1.2 - V2.2.0 | Works |
| v7 (unstable) | Not recommended | Works |
| v8 LTS | Works only via Yocto thud branch with meta-iot2000 patch set; cannot be installed via n
|
Works |
| v9 / v10 / v11 | Not possible; native modules call SSE intrinsics | Works |
| v12 LTS | Not possible | Default in V3.1.17 |
| v14 / v16 / v18 LTS | Not possible | Community-built via meta-openembedded |
Field observations: any NodeJS binary on Quark that appears to start will crash the moment V8 hits an SSE2 opcode. This includes any npm install that pulls a native module like bcrypt, sodium-native, or node-sqlite3 built against V8 > 6.x. The fault is not in the package, it is in the V8 codegen.
Illegal instruction (core dumped), signal 4 (SIGILL). Confirm with dmesg | tail -20 showing traps: node[pid] trap invalid opcode ip:.... If you see this, downgrade the runtime, do not patch the package.5. Locating the Legacy Example Image V2.1.3
Siemens has not republished V2.1.3 on its public download center. The supported channels, in order of preference:
- Siemens Industry Online Support (SIOS) ticket. Open a support request with the device serial number and ask for the V2.1.3 SD card image under your existing service contract. Siemens support will typically deliver an .iso or .wic image through the SIOS secure file exchange.
- Siemens Expert / partner channel. Industrial distributors with a System Integrator agreement can pull archived images from the partner portal.
-
Internal asset backup. Always archive the SHA-256 of any V2.1.3 image you obtain and store it in your CMDB. Once you have a verified copy, the
iot2000setuptool can re-image an SD card from the local repository in under 12 minutes for a 4 GB card.
Do not pull V2.1.3 from third-party mirrors or torrent trackers. The image has no signed manifest, so the integrity chain is entirely trust-based. A tampered image gives an attacker the highest privilege on a device that often sits in front of PLCs.
5.1 Verifying the Image
Once you have a candidate V2.1.3 image, validate it before flashing:
- Compute
sha256simage-IoT2040-V2.1.3.wicand compare to the value archived in your CMDB or supplied by Siemens support. - Mount the boot partition (
losetup -P) and confirm the kernel banner reads4.4.76-yocto-standardand the initramfs references the Pyro release tag. - Inspect
/etc/os-releaseon the running device. V2.1.3 reportsVERSION_ID="2.1.3"andVERSION="2.1.3 (pyro)". - Check that
npm --versionresolves to3.10.10andnode --versionresolves tov6.12.3. Any deviation indicates the image has been modified.
6. Upgrading NodeJS on the IoT2040
Two upgrade paths are documented for the Quark hardware. Pick the one that matches your operational constraints.
6.1 Path A: In-place via n (V2.1.3 only)
This is the path that historically worked for some teams on V2.1.3 - V2.1.5. It is fragile and the success window has narrowed as npm-side dependencies began shipping SSE-using code.
# SSH to the IoT2040, then:
opkg update
opkg install ca-certificates wget
# Confirm the default runtime
node --version # v6.12.3 on V2.1.3
# Use n to fetch a build, n will compile or fetch a prebuilt
npm install -g n
n 8.17.0 # last LTS that compiles on Quark without SSE
hash -r
node --version # v8.17.0
# Pin the runtime so a reboot does not revert
ln -sf /usr/local/n/versions/node/8.17.0/bin/node /usr/bin/node
ln -sf /usr/local/n/versions/node/8.17.0/bin/npm /usr/bin/npm
6.2 Path B: Custom Yocto image with NodeJS v8
For a reproducible build, use the meta-iot2000 jan/thud branch. The procedure below produces a .wic image with NodeJS v8 LTS baked in.
- Install the Yocto prerequisites on a Linux build host (Ubuntu 18.04 or 20.04 recommended, 100 GB free disk, 16 GB RAM minimum).
sudo apt-get install gawk wget git-core diffstat unzip texinfo \ gcc-multilib build-essential chrpath socat cpio python3 python3-pip \ python3-pexpect xz-utils debianutils iputils-ping python3-git \ python3-jinja2 libegl1-mesa libsdl1.2-dev pylint3 xterm - Clone the BSP layers for the thud release.
mkdir iot2000-thud && cd iot2000-thud git clone -b thud https://github.com/siemens/meta-iot2000.git git clone -b thud https://git.yoctoproject.org/git/poky git clone -b thud https://github.com/meta-qt5/meta-qt5.git source poky/oe-init-build-env build - Add the layers in
conf/bblayers.conf:BBLAYERS ?= " \ ${TOPDIR}/../poky/meta \ ${TOPDIR}/../poky/meta-poky \ ${TOPDIR}/../poky/meta-openembedded/meta-oe \ ${TOPDIR}/../poky/meta-openembedded/meta-python \ ${TOPDIR}/../meta-qt5 \ ${TOPDIR}/../meta-iot2000 \ " - Set the machine in
conf/local.conf:MACHINE = "iot2040" # or iot2020 for the dual-Ethernet variant DISTRO_FEATURES_append = " wayland opengl" - Force NodeJS v8 in the image recipe. Add to
conf/local.conf:PREFERRED_VERSION_nodejs = "8.17.0" PREFERRED_VERSION_nodejs-native = "8.17.0" - Build the image. Expect 4-8 hours on a workstation with 8 cores, longer on a VM.
bitbake iot2000-example-image - The resulting image is at
tmp-glibc/deploy/images/iot2040/iot2000-example-image-iot2040.wic. Flash to SD card withbmaptoolordd.
7. Installing PostgreSQL or MongoDB on the IoT2040
Both databases are technically installable on the Quark-based IoT2040, but in practice both hit hard limits. Use the following decision matrix.
| Database | Status on IoT2040 | Minimum RAM | Recommendation |
|---|---|---|---|
| SQLite | Officially supported in V2.x images | 32 MB | Default choice for buffered tag logging on the gateway |
| PostgreSQL 9.x | Builds from meta-oe; runs but no SSE-accelerated crypto on Quark |
512 MB dedicated | Use only on the 1 GB IoT2040 SKU; not on the 256 MB IoT2020 |
| PostgreSQL 14+ | Not feasible; default builds assume SSE4.2 | n/a | Migrate to IOT2050 |
| MongoDB 3.x | Builds; runs; very memory-constrained (WiredTiger cache) | 1 GB dedicated | Avoid; the gateway is starved of RAM the moment the OS + NodeJS + Mosquitto claim their share |
| MongoDB 4.x+ | Not feasible on Quark | n/a | Migrate to IOT2050 or run on a separate server |
7.1 Procedure for PostgreSQL on the 1 GB IoT2040
- Add the recipe to your local Yocto image or use the
opkgfeed:opkg update opkg install postgresql - Initialize the cluster on a USB-attached SSD, never on the eMMC (wear):
mkdir -p /media/sda1/pgdata chown -R postgres:postgres /media/sda1/pgdata su - postgres -c "/usr/lib/postgresql/9.6/bin/initdb -D /media/sda1/pgdata" - Tune
postgresql.conffor 256 MB shared_buffers and disable the JIT (LLVM JIT is not available on Quark):shared_buffers = 256MB effective_cache_size = 512MB jit = off max_connections = 20 - Start the server and verify:
/etc/init.d/postgresql start psql -U postgres -c "SELECT version();"
shared_buffers above 50% of physical RAM, or the kernel OOM killer will reclaim the NodeJS process and crash the gateway.7.2 Procedure for MongoDB on the 1 GB IoT2040
MongoDB 3.6 is the last version that builds without SSE4.2 requirements. The procedure mirrors PostgreSQL, with two extra steps:
- Build or install
mongodb-server-coreandmongodb-clients3.6.x. - Configure WiredTiger with a strict cache ceiling:
storage: engine: wiredTiger wiredTiger: engineConfig: cacheSizeGB: 0.3 - Start with
systemLog.verbosity: 1only; every log level above 1 doubles memory pressure on Quark.
Operationally, if your application truly needs MongoDB features (TTL indexes, aggregation pipelines, change streams), the right answer is to push the database to a separate industrial server or migrate to the IOT2050.
8. Migration Path to SIMATIC IOT2050
The meta-iot2000 releases page states that the IOT2050 is the successor platform and that the IoT2040 has reached product discontinuation. The migration is mechanical, not architectural.
-
Reflash the IOT2050 with Example Image V3.1.17 (the last official image) using
iot2000setupfrom a USB stick or the SD card slot on the IOT2050. -
Re-target the BSP. Change
MACHINE = "iot2040"toMACHINE = "iot2050"in your custom layer'slocal.conf. The Apollo Lake BSP is layered on Dunfell and useslinux-intel5.10. - Update the NodeJS runtime. V3.1.17 ships with NodeJS v12 LTS. If your application code targets v8, run it under v12 directly; the NodeJS compatibility layer is stable for typical OPC-UA, Modbus, and MQTT workloads.
-
Re-validate the I/O bindings. The Arduino shield header pinout is identical between IoT2040 and IOT2050, but the
libmraamajor version moved from 1.x to 2.x. Re-test any custom C/C++ modules. - Re-issue the security posture. The IOT2050 supports Secure Boot and a TPM 2.0. Enable both, regenerate SSH host keys, and re-sign your application containers.
| Migration step | Estimated downtime | Risk |
|---|---|---|
| Reflash with V3.1.17 | 10 min | Low (image is signed) |
| Port custom Yocto recipes | 2-4 h per recipe | Medium (Dunfell vs Pyro API changes) |
| Upgrade NodeJS v8 to v12 | 30 min + regression test | Low to medium depending on native modules |
| Validate I/O bindings | 1-2 h | Low (pinout identical) |
| Enable Secure Boot + TPM | 1 h | Low (one-time) |
9. Field-Proven Caveats and Verification
Use the checklist below before declaring any IoT2000 deployment production-ready.
-
Verify the boot partition signature. V2.1.3 images do not ship signed kernels. Once migrated to V3.1.17 on the IOT2050, enable UEFI Secure Boot and confirm with
mokutil --sb-statereturningSecureBoot enabled. -
Monitor
nodeprocess RSS. On Quark, a NodeJS v8 runtime with three active MQTT connections typically holds 90-130 MB resident. The kernel will OOM-kill at ~180 MB. Set asystemdmemory limit of 150 MB and a restart policy. -
Avoid
npm installon the device. Compile native modules on the Yocto build host withnpm install --target_arch=ia32and ship thenode_modulestree as part of the application artifact.npm installon Quark is a frequent cause of flash wear and silent SSE faults. -
Watch the eMMC wear.
cat /sys/block/mmcblk0/device/life_timereturns a value of 0x00 to 0x0A. Anything above 0x07 means the eMMC is near end-of-life. Move write-intensive workloads (logs, databases) to the SD card or USB SSD. -
Network segmentation. Place the IoT2000 behind a stateful firewall. The V2.x images have unpatched CVEs in
busybox(CVE-2021-42374 and related) and in the bundleddropbearSSH server. -
Time synchronisation. The default
systemd-timesyncdis sufficient, but if you run OPC-UA, switch tochronyand configure NTP over the management VLAN.
10. Troubleshooting Matrix
| Symptom | Likely cause | Resolution |
|---|---|---|
node exits with SIGILL after upgrade to v10+ |
V8 SSE2 opcode on Quark | Pin to v6.12.3 LTS or v8.17.0 (Yocto thud build) |
opkg install nodejs fails with unknown package
|
Repository index out of date or wrong branch | Run opkg update; verify /etc/opkg/*.conf points to a meta-iot2000 Pyro or thud feed |
| PostgreSQL service exits with code 137 | OOM killer | Reduce shared_buffers to 128 MB, disable JIT, move data directory to USB SSD |
| MongoDB refuses to start, log shows "illegal instruction" | MongoDB 4.x binary | Downgrade to MongoDB 3.6.x or migrate to IOT2050 |
| libmraa initialisation fails after reflash | Arduino shield power rail not enabled | Run iot2000setup -> "Configure Arduino shield" -> 5V/3.3V |
Kernel oops on systemd shutdown |
Known bug in Pyro systemd 232 |
Upgrade to V2.1.5 or backport the systemd patch from thud |
11. Summary of Constraints
- The meta-iot2000 releases page marks V3.1.17 as the last offical Example Image and the IoT2040 as a discontinued product line.
- V2.1.3 is not republished; recover it from Siemens support, a partner portal, or an internal archive, then checksum the image.
- NodeJS on the Quark-based IoT2020 / IoT2040 is practically limited to v6 LTS, with v8 LTS possible only via a custom Yocto thud build on the meta-iot2000 jan/thud branch.
- PostgreSQL works on the 1 GB IoT2040 SKU for archival logging only; MongoDB is feasible in version 3.6.x with strict cache ceilings, but is not recommended for new designs.
- New industrial deployments should target the SIMATIC IOT2050 with Example Image V3.1.17.
12. Frequently Asked Questions
Where can I download the SIMATIC IoT2000 Example Image V2.1.3?
V2.1.3 is no longer published on the Siemens public download center. The supported recovery channel is to open a Siemens Industry Online Support (SIOS) ticket with the device serial number and request the archived image under your service contract. Partners with a System Integrator agreement can also pull it from the partner portal. Always verify the SHA-256 hash before flashing.
What is the highest NodeJS version that runs on the IoT2040?
NodeJS v6.12.3 LTS is the only version Siemens officially supports on the Quark-based IoT2040. NodeJS v8.17.0 LTS is possible by building a custom image from the meta-iot2000 jan/thud branch, but the V8 binaries are patched downstream and are not a Siemens-supported configuration. Anything above v8 will hit a SIGILL fault because the Quark has no SSE2 instructions.
Does the IoT2040 support PostgreSQL or MongoDB?
PostgreSQL 9.6 builds and runs on the 1 GB IoT2040 SKU for archival logging of 1-5 Hz PLC tags. MongoDB 3.6.x is feasible only with a strict WiredTiger cache ceiling of 0.3 GB and is not recommended for new designs. PostgreSQL 14+ and MongoDB 4.x+ require SSE4.2 and will not run on Quark; deploy them on the IOT2050 or on a separate industrial server.
Is the IoT2040 still in production?
No. The IoT2040 is in product discontinuation. The meta-iot2000 GitHub repository has been archived and no longer accepts pull requests; the meta-iot2000 releases page explicitly identifies the SIMATIC IOT2050 as the successor platform.
What is the last official Example Image for the IOT2050?
Example Image V3.1.17 is the final offical release for the SIMATIC IOT2050. It is based on the Yocto Dunfell branch, ships with NodeJS v12 LTS, and uses the Apollo Lake BSP layer. New deployments should start from V3.1.17 unless there is a documented reason to track a specific service pack.