Currency note. Figures were collected from Chinese public channels in October 2026. Where a price was quoted in CNY, the USD figure is converted at the fixed October 2026 reference rate of 1 USD ≈ 6.71 CNY. Hardware prices are indicative of order of magnitude and are not a sourcing recommendation.
"Data must not leave the plant." It shows up in industrial IoT tenders as a single line, usually in the third clause of the technical specification, with no further explanation. The integrator wins the bid, buys an industrial PC, installs the on-premises version of the IoT platform, passes acceptance, and the job looks done.
The problem is that the sentence describes where data sits. It says nothing about how data moves inside the plant. Once you place a seven-container platform on the shop-floor network, questions do not disappear because the data stays local — is MQTT in cleartext, who can reach the object-storage console, how large will the history table be in twelve months. Centralising data tends to enlarge the internal attack surface, not shrink it.
This article walks through a ThinkLink Edge (TKE) deployment in the order it actually happens. The focus is not the install command — it is the set of things that are usually discovered after the install, and that should have been settled before the machine was ordered.
1. Before You Buy Anything: Three Questions That Decide Whether You Need TKE
ThinkLink ships in three deployment forms: public-cloud SaaS (Cloud), self-hosted on a local server (TKE / ThinkLink Edge), and embedded inside a gateway (TKG). All three share the same thing models, RPC definitions and trigger logic, and assets can be migrated between them. That is what makes it safe to defer the decision — up to a point.
| Dimension | Cloud | TKE (Edge) | TKG (in-gateway) |
|---|---|---|---|
| Where it runs | Public-cloud SaaS | Local server / industrial PC, self-hosted | Inside a ManThink gateway (e.g. GDO51 / GDI51) |
| Device ceiling | 1,000 (free, permanently) | 1,000 | 100 |
| Data throughput | ~100k messages/day | No stated ceiling | ~10k messages/day |
| Reference hardware | Nothing to buy | 8-core / 8 GB / 64 GB storage | Integrated (GDI51 has 32 GB eMMC) |
| Connectivity | Requires public internet | Local, runs offline | Local, no public internet needed |
| Best fit | Evaluation, small pilots | Data localisation, mid-to-large enterprises, private networks | Small private deployments, brownfield retrofits, no extra server |
Three questions to answer first:
Do you actually need TKE? Under 100 devices and under 10k messages a day, TKG embeds the network server directly in the gateway — no extra server, no server procurement cycle. A great many "data must not leave the plant" requirements are really about not pushing production data out through a public internet egress, and TKG satisfies that at a completely different cost structure.
Which side of 10k messages/day are you on? That line separates TKG from TKE. 1,000 devices reporting every 10 minutes is 144,000 messages a day — above Cloud's reference density and far past TKG. 50 meters reporting hourly is 1,200 a day, which TKG handles comfortably.
Who owns this machine afterwards? TKE is a standing operational commitment: OS patches, Docker engine, seven containers, certificate renewals, backups. If the customer's IT department has not explicitly accepted ownership, you have created an unowned server, usually discovered in year two when the disk is full.
2. Hardware Selection: x64 Is a Hard Constraint, Not a Recommendation
The official documentation carries two different statements of TKE's hardware requirements, and they do not agree. Worth laying out before you commit budget.
Statement A (product comparison table): reference hardware 8 cores / 8 GB RAM / 64 GB storage, minimum 2 cores and 2 GB, architecture listed as ARM64 / x64.
Statement B (Docker deployment manual; install flow updated 2026-09-11, TLS section updated 2026-10-22):
| Item | Requirement |
|---|---|
| Privileges | root (install commands use sudo) |
| CPU architecture | x64 only (x86_64 / amd64), minimum 2 cores |
| RAM | minimum 4 GiB |
| Disk | minimum 20 GiB free on the filesystem holding /opt |
| Network | HTTPS access to package.think-link.net for online install; the offline target needs no internet |
| Explicitly unsupported | ARM, ARM64, 32-bit x86 |
The two statements disagree on three points: 2 GB or 4 GB of RAM, 64 GB or 20 GB of disk, and — most consequentially — whether ARM works at all.
Follow statement B. Three reasons:
- Statement B comes from the deployment manual itself and is what the installer actually checks against; failing it terminates the install. Statement A is a summary line in a comparison table.
- Statement B is the stricter constraint. Seven containers run concurrently — EMQX, the NS bridge, PostgreSQL, Redis, ThinkLink, ThinkOne and MinIO. Two gigabytes leaves no headroom at that scale.
- Statement B explicitly lists ARM, ARM64 and 32-bit x86 as unsupported, and separately notes the restriction applies to both the one-line online install and the scripted offline install. Wording that specific usually comes from having tried it.
This constraint collides head-on with domestic-CPU mandates. Chinese CPUs split into two camps:
| Camp | Representative parts | Works with TKE? |
|---|---|---|
| x86 | Zhaoxin KX-6000/KX-7000, Hygon 3000/5000 series | Yes — architecture is compatible |
| ARM | Phytium FT-2000/4 and D2000, Kunpeng 920, Rockchip RK3568/RK3588 | No — incompatible |
If a localisation mandate lands on the ARM camp, TKE should be ruled out during selection, not after the machine arrives and uname -m prints aarch64. The x86 camp works directly — Hygon 3350 (8 cores / 16 threads at 3.0 GHz) is x86_64.
Indicative pricing collected from public channels in October 2026:
| Configuration | Purpose | Indicative price |
|---|---|---|
| 4U rackmount, i5-6500U / 8 GB / 1 TB | Proof of concept (2 cores, sitting exactly on the minimum) | ~$477 (¥3,200) |
| Industrial PC, Hygon 3350 (8C/16T) / 16 GB / 1 TB SSD | Recommended for production | ~$1,550–1,700 (¥10,400–11,400) |
| Same, with domestic OS licence | Localisation-mandate projects | ~$1,950 (¥13,100) |
The first tier is a POC machine only. The i5-6500U is two cores / four threads, exactly the stated minimum; CPU becomes the bottleneck before the disk does.
3. The Disk Calculation: 20 GiB Is the Entry Ticket, Not the Plan
The 20 GiB check is the installer's admission gate. Real consumption comes from three sources.
Seven container images. The offline bundle accepted on 2026-09-11 for version 2.00.062 is about 2.45 GB, holding the application archive, the Compose file and seven image archives — nine files total. Later versions will differ.
Database growth. At 1,000 devices reporting every 10 minutes, that is 144,000 rows a day. At roughly 1 KB per row including indexes, about 144 MB/day, or ~52 GB a year. Add PostgreSQL WAL, index bloat and history-query overhead and the usual practice is to provision two to three times that.
MinIO object storage. Reports and images live in the Docker named volume minio_data. This swings wildly depending on whether the business generates reports and how often.
Sum them and 20 GiB covers a few months. Go to a 1 TB SSD for production. The price delta sits in the table above and is trivial against total project value; the alternative is an online capacity expansion in year two.
One detail that is easy to miss: object files live in a Docker named volume, so routine backups must cover that volume; backing up the /opt directory alone does not substitute for object data. A backup script that only walks a directory path will silently lose every report file.
4. Port Planning: "Not Leaving the Plant" Is Not the Same as "Not on a Network"
This is the section worth reading twice. On-premises deployment solves data residency. A default install then opens a full set of ports on the host, and a meaningful share of them are cleartext.
Complete the HTTP install first, then configure HTTPS with tkl-tls 2.0.0 — that is the documented order. Host inbound ports:
| Port | Protocol | Purpose | Notes |
|---|---|---|---|
| 80 (or 8080) | TCP | ThinkLink web / API over HTTP | Original entry; if 80 is taken the installer interactively offers 8080; retained after TLS |
| 443 | TCP | ThinkLink web / API over HTTPS | Enabled once tkl-tls 2.0.0 configures the in-container Nginx |
| 1700 | UDP | LoRaWAN GWMP gateway uplink | Open per gateway access needs |
| 1883 | TCP | Device MQTT (cleartext) | Open per device access needs |
| 8883 | TCP | Device MQTTS | Not published by default; configure and verify separately in EMQX |
| 8083 | TCP | MQTT over WebSocket | Open per client needs |
| 8084 | TCP | MQTT over WSS | Path /mqtt; requires its own certificate |
| 18083 | TCP | EMQX dashboard over HTTP | Retained; not automatically upgraded to HTTPS |
| 18084 | TCP | EMQX dashboard over HTTPS | Enabled by tkl-tls 2.0.0 |
| 9000 | TCP | MinIO S3 API | Restrict source addresses |
| 9001 | TCP | MinIO console | Trusted administrator networks only |
Details that belong in the plan:
Port conflicts are handled inconsistently. If 80 is taken, the installer asks whether to use 8080 and leaves the occupying service alone. But if 9000 or 9001 is taken, the installer stops outright and will not pick an alternative. A target machine already running another storage service will stall mid-install.
5432 and 6379 never need to be exposed. PostgreSQL and Redis ports are container-internal only.
Management HTTPS is not device MQTTS. tkl-tls produces 443 and 18084. Device-side 8883 and 8084 are unpublished by default and need certificates uploaded in EMQX, mappings opened and connectivity verified. Replacing the certificate in the management UI does not replace device listener certificates — those are two separate configurations.
An open port is not an enabled TLS listener. Worth copying the manual's reminder straight into the acceptance sheet.
The EMQX console at 18083 stays HTTP. The HTTPS console is 18084; the old entry is retained. Locking down 18083 while forgetting 18084 accomplishes nothing.
5. On-Premises Deployment ≠ Regulatory Compliance
This is the most common misreading of "data must not leave the plant."
Moving the platform inside the plant addresses storage location. The path from sensor to platform is still network transmission, still subject to whatever the applicable rules require of transmission.
China's Interim Measures for Data Security Management in the Industry and Information Technology Sector (MIIT Network Security Circular No. 166, issued 2022-12-08, effective 2023-01-01) classifies sector data into three tiers — general, important and core — and states in Article 17:
Data processors shall formulate security policies and adopt protective measures based on the type, level and application scenario of transmitted data. When transmitting important data or core data, they shall adopt verification technology, cryptographic technology, secure transmission channels or secure transmission protocols.
Read that against the port table above. Under a default install, device MQTT runs cleartext on 1883, HTTP runs on 80, and MinIO's S3 API on 9000. If this system carries data classified as important, on-premises deployment alone does not satisfy Article 17 — the transmission channels have to be closed as well, meaning web/API on 443 and device MQTT on 8883.
The Network Data Security Regulations (State Council Decree No. 790, published 2024-09-24, effective 2025-01-01, nine chapters and 64 articles) establishes the classification-and-grading regime one level up, with a dedicated chapter on important data.
Two further clauses land on concrete operations:
- Article 15: storing important and core data requires secure storage using verification and cryptographic technologies, plus data disaster-recovery backup and storage-media security management, with periodic data recovery testing.
- Article 25: processors must log data processing, permission management and operator actions, retaining logs for no less than six months.
For European readers the pressure arrives from a different direction. The EU Data Act's design obligation for data access (Article 3(1)) took effect on 2026-09-12, with cloud switching charges falling to zero on 2027-01-12. Different instrument, same structural conclusion: the ability to move a deployment — including moving it onto your own hardware — is becoming a compliance matter, not an architecture preference.
The three clauses together form a chain: local deployment is step one, TLS is step two, backup and log retention are step three. Declaring compliance after step one is what gets caught in an audit.
6. Two Install Paths: Online One-Liner and Scripted Offline
Online
On a connected server, no arguments needed:
curl --tlsv1.2 --tls-max 1.2 -fsSL https://package.think-link.net/install.sh | sudo bash
The installer: detects OS, CPU, RAM, disk and ports → installs Docker on supported systems (reusing any working Docker) → downloads the application archive, the Compose file and seven image archives (nine files) → installs to the target directory, loads images and starts Compose → checks ThinkLink HTTP, MinIO readiness and bucket initialisation → records version and access information.
MinIO creates a private bucket named thinklink on first start.
Scripted offline
The documentation summarises it as "download online → transfer and verify → install offline."
Step one, on a connected machine. The download mode must run from a local script file, never through curl | bash, because the bundle has to carry the same complete installer:
curl --fail --silent --show-error --proto '=https' \ --tlsv1.2 --tls-max 1.2 --connect-timeout 10 --max-time 60 \ https://package.think-link.net/install.sh -o thinklink-install.sh
bash thinklink-install.sh --help bash thinklink-install.sh --download-only ./thinklink-offline
Run --help first and confirm it lists --download-only, --verify-only and --offline. The target directory must not yet exist and its parent must; do not mkdir it beforehand.
The delivered directory holds 13 checksummed files:
| File | Role |
|---|---|
| application.tar | Application archive |
| docker-compose.yml | Compose definition |
| tkl-emqx.tar / tkl-nsbrg.tar / tkl-postgres.tar | EMQX, NS bridge, PostgreSQL images |
| tkl-redis.tar / tkl-thinklink.tar / tkl-thinkone.tar | Redis, ThinkLink, ThinkOne images |
| tkl-minio.tar | MinIO image |
| install.sh / install-offline.sh | Installer scripts |
| release.json | Release id, version, channel, architecture |
| SHA256SUMS | Covers 9 artifacts, 2 scripts, the version record and the readme |
| README.txt | In-bundle notes |
Step two, transfer and verify. Move the directory intact — it is created with mode 0700 and should stay read-restricted afterwards. On the target:
cd thinklink-offline bash install.sh --verify-only .
This mode needs no root, no Docker and makes no network requests. It checks file integrity, manifest paths and version format, and only proceeds if all pass. SHA-256 verifies transfer integrity; it is not a publisher signature and does not independently prove provenance — a candid note in the manual, and a reminder that supply-chain trust still rests on the delivery channel.
Step three, install. Run sudo bash install-offline.sh in the bundle directory, adding --yes for unattended runs (it skips only the final confirmation prompt, not verification or port checks).
The offline target must already have Docker Engine and Docker Compose V2, because the bundle does not include Docker or OS dependencies. Check first:
uname -m sudo docker version sudo docker compose version
uname -m must print x86_64. Anything else: stop.
Three limits of the offline path
- New installations only — no automatic upgrade, no rollback on failure. If it detects an existing install or leftover data, it leaves the scene intact for you to investigate rather than cleaning up and retrying. Upgrades need new artifacts, a backup and a version-matched upgrade plan.
- Do not mix download batches. The package service checks upstream at 00:00 Beijing time daily and updates artifacts. Mixing batches produces
OFFLINE_IMAGES_MISSING— Compose and images out of sync. - No resumable downloads across processes. A failure means re-downloading the whole 2.45 GB. On an expired URL or single-file failure, the script refreshes the address within the same session and retries once.
7. The One Red Line When Running Alongside Cloud
Most projects pass through a transition period with a foot in both camps — legacy devices in the cloud, new devices on-premises, both live.
The documentation is unambiguous:
Do not enable the same LoRaWAN device profile on two platforms at once. If TKE and the cloud platform both respond to Join or Confirm messages, join failures and downlink conflicts can result. When switching platforms, disable or delete the profile on the one you are not using.
This is a functional constraint, not a performance tip. A Join Request is forwarded to every NS registered for that DevEUI. Both answer with a Join Accept; the device accepts one, but the other NS now believes the device joined and holds frame counters — subsequent downlinks go to the wrong path.
During transition, the profile is enabled on exactly one side. Not "both on, whoever answers first."
8. Cloud → Edge Migration: Three Traps in the Excel Import/Export
ThinkLink moves bulk data through Excel across six module types: device configurations, LoRaWAN profiles, thing models, RPC commands, linkage/trigger models and device templates. The workflow is identical on Cloud, TKE and TKG — the only difference being that TKE/TKG have their own local admin account, unrelated to the cloud one.
- In the cloud, open the target module (e.g. LoRaWAN Profiles)
- Select the entries to sync (none selected = export all)
- Click Export and download the generated spreadsheet
- Repeat 2–3 for each data type (thing models, RPC commands, …)
- Switch to TKE and open the matching module
- Click Import and choose the spreadsheet
- Confirm the import completed without errors
- Importing public models requires logging in as admin
Three traps:
Trap one: DevEUI is globally unique, so cross-organisation migration is delete-then-import. A given DevEUI belongs to one organisation within a platform. Moving a profile from organisation A to B requires deleting it in A first; otherwise the import fails outright.
| Data type | Delete first? | Why |
|---|---|---|
| LoRaWAN Profiles | Yes | DevEUI is globally unique |
| Thing models / RPC commands / device templates | No | Same ID means overwrite; not uniqueness-constrained |
Trap two: a matching ID means full overwrite, and it cannot be rolled back. The rule is "create if the ID is absent, overwrite completely if present." That is a replacement, not a merge. Stale field values in the spreadsheet will overwrite live configuration on the target.
There is exactly one mitigation: export first, before importing, and keep that spreadsheet as the backup. Validate format on a small batch before the first large import.
Trap three: there is no undo. With a backup, re-import it. Without one, rebuild the configuration by hand. Review the ID column row by row so the file contains only what you intend to create or update.
9. Backups: Three Layers That Do Not Substitute for One Another
| Layer | Location | Method |
|---|---|---|
| Configuration and install record | Install directory under /opt |
File-level backup |
| Database | PostgreSQL container volume | Volume snapshot or logical dump |
| Object files | Docker named volume minio_data |
Volume-level backup |
Backing up /opt alone does not substitute for object data. A container restart preserves existing buckets and objects; host disk failure does not.
Article 15 of Circular 166 requires disaster-recovery backup and periodic recovery testing. Note the second half — a backup that has never been restored is a hypothesis. One way to exercise the whole chain during acceptance is generating and downloading a report:
sudo docker compose -f exec -T minio /thinklink-minio check-ready
That command checks whether the image's built-in initialisation completed; pair it with a container status check.
10. Error Codes Worth Recognising
The manual lists the full set. These are the ones that surface during deployment:
| Message | Meaning and handling |
|---|---|
OFFLINE_OUTPUT_EXISTS |
Download directory already exists — pick one that does not; do not overwrite the old bundle |
SCRIPT_FILE_REQUIRED |
Download mode must run from a local script file, not curl \| bash |
ARTIFACT_DOWNLOAD_FAILED |
Check network and disk space, re-download the whole set |
DOWNLOAD_REFRESH_INVALID |
Version or artifacts changed while refreshing — re-download the full bundle |
OFFLINE_BUNDLE_INVALID / OFFLINE_CHECKSUM_FAILED |
Re-transfer the complete directory; do not edit the manifest to bypass |
OFFLINE_DOCKER_REQUIRED |
Install offline dependencies, start Docker, verify Compose V2 |
OFFLINE_EXISTING_INSTALL |
Existing install or data present — prepare a backup and upgrade plan first |
PORT_IN_USE / ALTERNATE_PORT_IN_USE |
Resolve the conflict, arrange a usable port, retry |
OFFLINE_IMAGES_MISSING |
Compose and images out of sync — supply a matching full bundle |
HEALTH_CHECK_FAILED |
Check container status and logs; preserve install data while investigating |
Two for day-to-day work:
sudo docker compose -f ps sudo docker compose -f logs
Check logs for connection strings and credentials before sharing them externally — a reminder the manual makes on its own.
11. Acceptance Checklist
In the order of this article, a TKE deployment ready to hand over:
| # | Item | Pass criterion |
|---|---|---|
| 1 | uname -m prints x86_64 |
Non-x64 fails outright |
| 2 | CPU ≥ 2 cores, RAM ≥ 4 GiB, /opt ≥ 20 GiB |
Production: 8 cores / 16 GB / 1 TB |
| 3 | Pre-flight port check on 80/8080, 9000, 9001, 1700, 1883 | A 9000/9001 conflict aborts the install |
| 4 | All seven containers running | docker compose ps |
| 5 | Private MinIO bucket ready, anonymous access refused | check-ready plus an anonymous access attempt |
| 6 | Web/API on HTTPS 443, EMQX console on 18084 | tkl-tls 2.0.0 |
| 7 | Device MQTT on 8883 (where required) | Configured and verified separately in EMQX |
| 8 | MinIO 9000/9001 reachable only from trusted networks | Firewall rules |
| 9 | No device profile enabled on both cloud and TKE | Profile inventory cross-check |
| 10 | Export taken before import | Backup file retained |
| 11 | Backup scope covers the minio_data volume |
Backup script review |
| 12 | One recovery test completed | Recovery drill record |
| 13 | Default passwords changed (ThinkLink / EMQX / MinIO) | Business client configs updated to match |
| 14 | Full offline bundle + release.json + SHA256SUMS retained |
Version traceability |
Item 5's "anonymous access to the private bucket refused" was explicitly covered in the vendor's own 2026-09-11 acceptance record, and it belongs on your checklist too. A private bucket that is anonymously readable is every report file sitting in an internal share.
12. Closing
"Data must not leave the plant" is a requirement about storage location, and it triggers three consequences: you buy the machine, you close the transmission channels, and you run the backups. Only the first of those is a procurement problem.
Two points this article has argued repeatedly:
On-premises is not the same as compliant. Article 17 of Circular 166 requires secure transmission channels or protocols for important data. A default TKE install runs MQTT in cleartext on 1883 and HTTP on 80. tkl-tls is not an optional hardening step; it is what closes that clause.
Confirm the x64 constraint before the purchase order. The vendor's own documentation carries two conflicting statements about TKE's hardware requirements, and they disagree on whether ARM works. Taking the deployment manual as authoritative: it does not. If a localisation mandate has already settled on Phytium or Kunpeng, raise it at proposal stage rather than when uname -m prints aarch64.
TKE's value is that it bundles the network server, thing models, trigger logic, alarms and object storage into one Compose command while preserving a migration path to and from both the cloud and the in-gateway form. The price is that someone now owns it. Deciding who, before buying anything, matters more than the spec sheet.
Next in the series (Issue 24): the data is local; now let the rest of the building read it — BACnet/IP and Modbus TCP integration on ThinkLink, from field mapping to commissioning with YABE.
Sources
- ThinkLink documentation, Docker Deployment (TKE) — install flow updated 2026-09-11, TLS and port notes updated 2026-10-22: https://www.think-link.net/docs/zh/QuickStart/Deployment/ThinkLinkDocker.html
- ThinkLink documentation, ThinkLink (TKL) Introduction: https://www.think-link.net/docs/zh/QuickStart/ThinkLinkIntroduction.html
- ThinkLink documentation, Batch Data Management Guide: https://www.think-link.net/docs/zh/AN/BatchDataManagementGuide.html
- ThinkLink documentation, ThinkLink in Gateway (TKG): https://www.think-link.net/docs/zh/QuickStart/Deployment/ThinkLinkGateway.html
- MIIT, Interim Measures for Data Security Management in the Industry and Information Technology Sector, Network Security Circular No. 166, effective 2023-01-01
- State Council, Network Data Security Regulations, Decree No. 790, effective 2025-01-01