---
name: container-setup
description: Prepare and validate a CitusIO container node using its bundled tier configuration, shared namespaces and explicit daemon and gateway roles.
---

# Set up a container node

Read [offline kit extraction and configuration](../references/offline-deployment.md)
first. The image's `requirements` command emits the tier-specific requirements;
`deployment` emits the matching Compose/configuration tar archive. Those
artifacts are generated from this image's assembled files. The examples below
explain the topology they implement; preserve their namespace and identity
boundaries when adapting them.

`setup` emits the full guide as text and `compose` emits the exact Compose file.
Use `deployment` for the complete kit, including files referenced by Compose.
Read [private input formats](../references/private-inputs.md) when supplying
credentials, policy, audit key and trust material; no website or source checkout
is needed to learn their formats.

Every tier bundles the web panel. Read
[panel-operations](../panel-operations/SKILL.md) for the kit's panel URL, access
boundary, tier-specific views and authorized command workflows. The gateway
serves it alongside the API; no separate UI service is needed.

After startup, inspect `/api/v1/admin/identity` and the live dashboard before
planning admin actions. The bundled [task catalog](../contracts/agent-tasks.json)
describes the stable API; it does not grant installed availability or authority.
Require availability version 1 and matching node, routing generation, writer
term, ring generation and configuration digest. A compiled tier is a ceiling;
the selected runtime profile can expose less. Missing or mismatched scope blocks
commands. Use [admin operation guidance](../references/agent-administration.md)
for exact inputs, role checks and read-only recovery.

Inspect the exact image, its lane marker and `/etc/nginz-iot/iotd.toml`,
`/etc/nginz/nginz.conf`, and any policy, rule, schema or bridge files they
reference. Customer lane documentation is at
`/usr/share/doc/nginz-iot/lane/PRODUCT.md` and `packaging.md` beside it. The
internal all-in-one image has no customer lane document. Examples are starting
points; resolve every environment/secret reference and selected external
service before launch. Never print secret values in a deployment report.

Record the deployment's image ID, roles, protocol/port exposure, mounted files,
named volumes, credentials and dependencies in a private manifest. Preload the
product and any provider/client images in an offline environment; use exact
local IDs or verified references and `--pull=never`. Broker and sink connectivity
still need their declared local network paths.

## Build the node topology

Run separate containers with explicit commands `iotd`, `gateway`, and `bridge`
when selected. Use the same unprivileged `iot` identity (UID/GID 10001), a shared
`/run/nginz-iot` volume, and persistent mounts for configured data paths. Check
policy/secret access for actual nginx workers as well as the container user.

Make `iotd` the namespace owner. In Compose, use `ipc: shareable` on `iotd` and
`ipc: service:iotd`, `pid: service:iotd`, `network_mode: service:iotd` on the other
roles. With Docker CLI, join all three using `--ipc=container:NAME`,
`--pid=container:NAME`, `--network=container:NAME`. Publish nginx listener ports
from the owner. Configure sufficient shared memory; the shipped Evaluation
profile uses `512m`. Match ring namespace, dimensions, generation, writer term
and worker count between authority and gateway. IPC alone is insufficient.

Free's legacy Evaluation profile defaults to accepted-memory behavior and may
be used in production. Core and higher default
durable configurations require PostgreSQL. Read the `durable-recovery` skill
listed in the image TOC before provisioning a durable deployment. Resolve
bridge/sink prerequisites for the chosen higher-tier profile as well.

Every customer tier includes the public Bridge SDK and sample adapter. Read
the installed examples under `/usr/local/share/nginz-iot/bridge-sdk/examples/`
and use `/usr/local/include/nginz_iot/` for the adapter ABI. Supplying an adapter
does not enable higher-tier broker/rule/gateway behavior. Reference adapters
and the full rules-based pipeline are selected through the integration skill
when that skill is present in this image.

## Validate, then start

In an owned isolated validation environment with the intended mounts, identity,
secrets and namespaces, run the exact image's native commands:

```sh
nginz-iotd --config /etc/nginz-iot/iotd.toml --test-config
nginz-iot -t -p /var/lib/nginz-iot/ -c /etc/nginz/nginz.conf
```

For a selected bridge, validate its target config with
`nginz-iot-bridge --config PATH --test-config`. Keep raw native diagnostics
private. A syntax pass does not prove external availability or delivery.

Keep first provisioning separate from startup. Start the namespace owner,
wait for daemon readiness, then dependent roles. The default gateway gate
requires `route_to_node=true`; `live` is only for an externally fenced standby
whose traffic probe still checks route readiness. Read
[container-operations](../container-operations/SKILL.md) for verification and
diagnostics. Save the deployment's first unfinished checkpoint for handoff.
