Installing Ice Flow
Ice Flow runs as a long-lived service that connects to a running Symphony instance over NATS. Install it on a host that can reach both Symphony and the Iceberg catalogs and storage systems it will manage.
Choose the method that matches how Symphony itself is deployed in your environment:
- RPM—the recommended approach for bare-metal or VM deployments on RHEL 9+, Fedora, or SLES. The RPM installs a systemd service, default configuration, and log directory.
- Docker—run Ice Flow as a container. Suitable for hosts that already run other containerised Cirata services.
- Kubernetes (Helm)—deploy into an existing Kubernetes cluster using the Ice Flow Helm chart. Suited for deployments where Symphony itself runs in Kubernetes.
Obtaining the Software
Ice Flow is distributed as three artifacts. Contact your Cirata representative or visit the Cirata customer portal to obtain the artifact for your platform:
- RPM—
cirata-iceflow-<version>.x86_64.rpm - Docker—
cirata/iceflow:<version>(container image) - Kubernetes—
iceflow-<version>.tgz(Helm chart)
Prerequisites
All installation methods require:
- A running Symphony instance, reachable from the Ice Flow host on the
NATS port (default
4222). - A token for Ice Flow to authenticate with Symphony, issued from the Symphony Account → API Keys page. Two flavours are supported and Ice Flow's preferred flow differs by deployment method—see Choosing a Token Flow below.
- Java 17 on the host (RPM and bare-metal installs only; the Docker image and Helm chart bundle their own JRE).
- Network reachability from the Ice Flow host to each Iceberg catalog endpoint and storage system it will manage.
For Kerberos-secured Iceberg catalogs, the host also needs a working
krb5.conf and either keytabs on disk or keytabs uploaded through the
Symphony UI. See Configure Kerberos.
Choosing a Token Flow
The Symphony SDK accepts the token through one of two environment variables. Pick the flow that matches the deployment:
REGISTRATION_TOKEN— preferred for RPM and other long-lived hosts. Issue a one-time registration token from Account → API Keys, hand it to Ice Flow once, and the SDK exchanges it on first start for a permanent API key carrying the extension's declared capabilities. The provisioned key is written to the OS credential store (or~/.config/cirata/as a fallback) and reused on every subsequent start—no further token handling is required.SYMPHONY_TOKEN— recommended for Docker and Kubernetes. Issue a permanent API key directly and inject the token via the container environment or a KubernetesSecret. No credential storage is involved, which suits ephemeral pods where the OS credential store is unavailable and any locally written file is lost on restart.
SYMPHONY_TOKEN is also a valid carrier for a registration token: when the
JWT carries registration capabilities the SDK auto-detects this and runs the
provisioning flow described above. The two variables can therefore hold the
same value; what differs is whether you want the resulting permanent key
stored locally or kept as the one source of truth in your secret store.
See Authentication in the platform documentation for the full token-resolution order and the credential storage paths.
Choosing a Method
| Environment | Recommended method |
|---|---|
| Bare-metal or VM on RHEL/Fedora/SLES | RPM |
| Host running other Cirata containers | Docker |
| Existing Kubernetes cluster | Kubernetes (Helm) |
RPM Installation
See Obtaining the Software for how to get the
cirata-iceflow-<version>.x86_64.rpm package.
1. Install the package
sudo dnf install cirata-iceflow-<version>.x86_64.rpm
On SLES, use zypper:
sudo zypper install cirata-iceflow-<version>.x86_64.rpm
The package will:
- Create a
ciratasystem user and group - Install the JAR to
/opt/cirata/symphony/extensions/iceflow/cirata-iceflow.jar - Install a systemd service unit at
/usr/lib/systemd/system/cirata-iceflow.service - Create the configuration directory at
/etc/cirata/symphony/extensions/iceflow/ - Create the log directory at
/var/log/cirata/symphony/extensions/iceflow/
2. Set the token
The RPM ships an environment file at
/etc/cirata/symphony/extensions/iceflow/iceflow.env (owned by root:cirata,
mode 0640). Edit it and supply the token using the registration token
flow preferred for long-lived hosts:
sudo vi /etc/cirata/symphony/extensions/iceflow/iceflow.env
Add a line for the registration token:
REGISTRATION_TOKEN=<paste your one-time registration token here>
On first start, the SDK exchanges this token for a permanent API key and
stores it under the cirata user's ~/.config/cirata/ directory. The
permanent key is reused on every subsequent start; the registration token is
consumed and need not be kept.
The iceflow.env file already includes a SYMPHONY_TOKEN= line for
backwards compatibility. If you already hold a permanent API key (for
example, one provisioned from a different host), paste it into
SYMPHONY_TOKEN instead; the SDK accepts either variable and auto-detects
when SYMPHONY_TOKEN carries a registration token.
Adjust JVM heap (JVM_XMS, JVM_XMX) and the Kerberos JGSS open flag
(JVM_KRB5_OPEN) in the same file if needed.
3. (Optional) Add JDBC drivers
For JDBC catalogs, drop the driver JAR alongside the extension JAR:
sudo cp postgresql-42.7.5.jar /opt/cirata/symphony/extensions/iceflow/
Then set -Djdbc.extra.driver.jars=<path> via an application.properties
override or a JVM_EXTRA_ARGS entry in iceflow.env. See
Configuration Reference.
4. Start the service
sudo systemctl enable --now cirata-iceflow
5. Verify
# Service is active
sudo systemctl status cirata-iceflow
# Logs show successful registration
sudo journalctl -u cirata-iceflow -f
Then open Symphony in a browser. The Extensions page should list iceflow as connected, and the Iceberg menu group should appear in the navigation.
File Locations
| Path | Purpose |
|---|---|
/opt/cirata/symphony/extensions/iceflow/cirata-iceflow.jar | Extension JAR |
/etc/cirata/symphony/extensions/iceflow/iceflow.env | Runtime environment (token, JVM heap) |
/etc/cirata/symphony/extensions/iceflow/application.properties | Spring Boot properties |
/etc/cirata/symphony/extensions/iceflow/logback.xml | Logging configuration |
/var/log/cirata/symphony/extensions/iceflow/ | Log directory |
/usr/lib/systemd/system/cirata-iceflow.service | systemd unit |
/opt/cirata/.config/cirata/ | SDK-provisioned credential store (registration-token flow) |
Docker Installation
1. Load the image
docker pull cirata/iceflow:<version>
If you received the image as a tar file, load it instead:
docker load -i cirata-iceflow-<version>.tar
2. Run the container
Inject a pre-provisioned permanent API key via SYMPHONY_TOKEN. This is the
recommended flow for containers: it keeps the secret in your existing
secret store and avoids the SDK writing a credential file inside the
ephemeral container filesystem.
docker run -d \
--name cirata-iceflow \
--restart unless-stopped \
-e SYMPHONY_TOKEN=<paste your permanent API key here> \
-v iceflow-logs:/var/log/cirata \
cirata/iceflow:<version>
For Compose, the shipped ci/docker-compose.deploy.yml is a working starting
point:
services:
iceflow:
image: cirata/iceflow:${IMAGE_TAG}
container_name: cirata-iceflow
restart: unless-stopped
network_mode: "host"
environment:
SYMPHONY_TOKEN: ${SYMPHONY_TOKEN}
JAVA_OPTS: "-Xms512m -Xmx2g"
LOG_DIR: /var/log/cirata
volumes:
- iceflow-logs:/var/log/cirata
volumes:
iceflow-logs:
Start it:
IMAGE_TAG=<version> SYMPHONY_TOKEN=<token> docker compose up -d
The shipped image supports REGISTRATION_TOKEN as well—the application
configuration resolves ${REGISTRATION_TOKEN:${SYMPHONY_TOKEN}}. Use the
registration-token flow when iterating in a development workflow, but for
production containers prefer a pre-provisioned SYMPHONY_TOKEN so the
container does not re-provision (and write a credential file) on every
restart. To make a registration-provisioned token survive container
restarts, mount ~/.config/cirata/ on a persistent volume.
3. Verify
docker ps --filter name=cirata-iceflow
docker logs -f cirata-iceflow
The container is healthy when the Extensions page in Symphony lists iceflow as connected.
Kubernetes Installation
The Helm chart is published as iceflow-<version>.tgz. It deploys a single
Deployment running the cirata/iceflow image with SYMPHONY_TOKEN sourced
from a Kubernetes Secret. A pre-provisioned permanent API key is the
recommended flow here: pod filesystems are ephemeral, so keeping the
secret in the cluster's secret store avoids re-provisioning every time the
pod restarts.
1. Create a Secret with the API token
kubectl create secret generic iceflow-symphony-token \
--from-literal=symphony-token=<paste your permanent API key here>
The secret may instead hold a registration token. The SDK detects this from
the JWT's capabilities and provisions a permanent key on first start. To
keep that provisioned key across pod restarts without re-running the
exchange every time, mount ~/.config/cirata/ on a PersistentVolume.
2. Install the chart
helm install my-iceflow iceflow-<version>.tgz \
--set symphony.existingSecret=iceflow-symphony-token \
--set symphony.hostname=symphony.example.com
Set symphony.hostname to the public hostname embedded in the token's aud
claim. When Symphony runs in the same cluster, set symphony.serviceName
or symphony.address so the pod resolves the hostname to the in-cluster
service:
helm install my-iceflow iceflow-<version>.tgz \
--set symphony.existingSecret=iceflow-symphony-token \
--set symphony.hostname=symphony.example.com \
--set symphony.serviceName=symphony-service
For the full list of Helm values—image, JVM, resource limits, health probes, custom CA—see Configuration Reference.
3. Verify
kubectl get pods -l app.kubernetes.io/instance=my-iceflow
kubectl logs -l app.kubernetes.io/instance=my-iceflow -f
The deployment is healthy when the pod is Running and the Extensions
page in Symphony lists iceflow as connected.
Verification
Regardless of method, a successful install presents three signals:
- The Ice Flow process is running on the host or in the cluster
(
systemctl status cirata-iceflow,docker ps, orkubectl get pods). - The extension logs report successful registration with Symphony (look
for entries that mention
Connectedorapikey). - The Symphony Extensions page lists iceflow as connected and the Iceberg menu group appears in the navigation.
Once these are green, continue with Getting Started to add a warehouse, a catalog, and your first replication.
Troubleshooting Installation
- No token available—the extension exits at startup. The SDK looks for a
permanent API key in the OS credential store first, then
SYMPHONY_TOKEN, thenREGISTRATION_TOKEN. Set one of those iniceflow.env(RPM), the container environment (Docker), or the referenced Secret (Kubernetes). See Choosing a Token Flow. Connection refusedagainst the Symphony hostname—the host or pod cannot reach the NATS port (4222). Confirm DNS resolves the hostname in the token'saudclaim, and that nothing blocks outbound TCP on port4222.- Token rejected—the token was revoked or issued for a different Symphony deployment. Re-issue from Account → API Keys and update the configuration.
- Java not found (RPM only)—the package requires
java-17-openjdk-headless. Install it viasudo dnf install java-17-openjdk-headless. - In-cluster hostname does not resolve (Kubernetes)—set
symphony.serviceNameso the chart injects ahostAlias, or setsymphony.addressto bypass the JWT hostname entirely. See Configuration Reference. - Extension not visible in the UI—wait 30–60 seconds for registration, then refresh. If still missing, check the extension logs for registration errors.
For deeper diagnostics, see Troubleshooting.
See Also
- Getting Started—first warehouse, catalog, and replication
- Configuration Reference—environment variables, JVM flags, and deployment options
- Configure Kerberos—per-catalog Kerberos authentication
- Upgrades—upgrade Ice Flow in place
- Uninstallation—stop and remove Ice Flow