Configuring Ports
Define which services your app exposes for remote access by creating a port-template.yml file in the .ironflock/ directory.
Basic Example
ports:
- name: Web Interface
port: 5000
main: true
protocol: httpsThis makes port 5000 available for remote access. Installing the app on a production device switches its tunnel on; users with the network privilege can switch it off and on from the app settings on their device.
Full Example
ports:
- name: Web Interface
port: 1100
main: true
protocol: http
- name: Video Stream
port: 1200
protocol: http
- name: Remote Desktop
port: 5900
protocol: tcp
- name: LoRaWAN Gateway
port: 1700
protocol: udpField Reference
| Field | Required | Description |
|---|---|---|
name | Yes | Label shown in the device’s app settings |
port | Yes | Local port number the service listens on |
main | No | If true, this port is used for the quick-access icon on the device’s app list |
protocol | No | http (default), https, tcp, or udp |
remote_port_environment | No | TCP and UDP only: an additional variable name under which the device agent announces the tunnel’s remote port, alongside REMOTE_PORT_FOR_<port>. Device agents before 0.19.8 announce it only under this name |
Injected Environment Variables
For every port you declare, the platform injects environment variables into your app’s containers so your code can discover where the service is actually reachable — without hardcoding addresses:
| Variable | Description |
|---|---|
DEVICE_LAN_IP | The device’s IP address on the local network |
DEVICE_PORT_FOR_<port> | The port on the device where your declared port is published on the local network |
REMOTE_PORT_FOR_<port> | The public port allocated by the tunnel server while the tunnel is active (TCP and UDP; device agent 0.19.8 and later). 0 means not assigned yet |
REMOTE_PORT_FOR_<port>_CLOUD | The internet-facing port when the device runs on an IronFlock instance that forwards tunnels through the cloud (TCP and UDP) |
TUNNEL_DOMAIN | The domain the device’s tunnel URLs are composed on: app.ironflock.com in the cloud, the appliance’s domain on an on-premises appliance, and localhost on an edge device of an appliance installed without a domain (plain mode) |
INSTANCE_KEY | Set only on a device that belongs to an on-premises appliance (instance): the key its cloud-forwarded tunnel URLs carry |
<port> is the port number you declared in port-template.yml. For the Remote Desktop example above, the app would receive DEVICE_PORT_FOR_5900 and — while its tunnel is active — REMOTE_PORT_FOR_5900. The IronFlock SDKs compose a port’s remote access URL from these variables with getRemoteAccessUrlForPort. The platform does not set CLOUD_TUNNEL_DOMAIN: cloud-forwarded URLs use app.ironflock.com unless your app sets that variable itself.
Tunnels exist for production installs only. A development (DEV) container gets no tunnel and no remote port of its own — reach it on the device’s local network instead (DEVICE_LAN_IP, DEVICE_PORT_FOR_<port>).
Apps may run concurrently on the same device, so declared ports are mapped to a free port on the device automatically. Always compose local-network addresses from the injected values instead of assuming the declared port:
import os
lan_ip = os.environ.get("DEVICE_LAN_IP")
lan_port = os.environ.get("DEVICE_PORT_FOR_5900")
# service is reachable on the local network at {lan_ip}:{lan_port}The variables are set when the container starts. Tunnel ports can change while the app is running (for example when a tunnel reconnects), so the tunnel port variables (REMOTE_PORT_FOR_<port>, its _CLOUD companion and a custom remote_port_environment name) are additionally kept up to date as files under /data/env/<VARIABLE_NAME>.txt — the IronFlock SDKs read these automatically. The other variables change only when the container restarts.
The device agent removes a _CLOUD file when the cloud port goes away (cloud forwarding turned off). While the agent’s files are present, a missing or empty _CLOUD file therefore means there is no cloud port, and the SDKs do not fall back to the stale value the container started with.
The agent makes /data/env readable by root only. A container that runs as another user cannot read these files: it sees only the values it started with — no tunnel port that changed since — and the SDKs log a warning once.
How Protocols Work
HTTP / HTTPS
For web-based services. IronFlock creates a URL on the tunnel domain that proxies traffic to the device’s local port. Users open the URL in their browser. It is private: only users signed in to IronFlock with access to the device can open it, unless the port is switched Public.
TCP
For protocols like VNC (Remote Desktop) or direct socket connections. IronFlock allocates a remote port on the tunnel server and exposes it to your app as REMOTE_PORT_FOR_<port>; the service is then reachable at tcp://<TUNNEL_DOMAIN>:<remote port>.
UDP
For protocols like LoRaWAN communication or VPN tunnels. Similar to TCP — a remote port is allocated and exposed as REMOTE_PORT_FOR_<port>.
Embedding in Boards
You can embed a device’s remote access tunnel directly into a board using the Embed Widget. This creates a seamless experience where users can:
- Monitor global data from all devices
- Interact with individual devices through embedded web UIs
All within the same dashboard.
Installing an app on a production device switches the tunnel of every port in its
port-template.ymlon. HTTP and HTTPS tunnels stay private - only users signed in to IronFlock with access to the device can open them - unless a port is switched Public. TCP and UDP tunnels are raw ports on the tunnel server with no login in front, so the app must authenticate its clients itself. Users with the network privilege on the device can switch tunnels off and on again; see Managing Tunnels.