Polycrate API for Teams: Centralized Monitoring and Remote Triggering
TL;DR The Polycrate API transforms individual workspaces into a team platform: all workspaces, …
Diese Serie zeigt Schritt für Schritt, wie Ansible mit Polycrate zu einer strukturierten, teilbaren und compliance-fähigen Automatisierungsplattform wird – von den Grundlagen bis zu Enterprise-Szenarien.
apt upgrade) including service restarts and distribute sensor and logging configurations across your device fleet.serial: 10, you can safely roll out updates in waves, for example, 50 Raspberry Pis in groups of 10—ideal for factory halls, smart home fleets, or Industry 4.0 setups.Imagine a typical factory hall:
All doing “something important”: collecting data, sending it to the cloud, triggering alarms. But:
This is not only inconvenient but risky:
Ansible is excellent for such tasks. But:
Many IoT and OT teams struggle to set up Ansible properly: Python versions, collections, SSH configuration, ansible.cfg, and so on.
This is where Polycrate comes in: You get a standardized Ansible environment in a container—without the installation marathon on your laptop. You focus on your devices, not your tooling.
Raspberry Pis are indispensable in IoT and edge projects. They are ideal targets for Ansible:
Important: The architecture (armv7, arm64) doesn’t matter to Ansible. Ansible controls the devices via SSH, and the modules run directly on the target system. So you need:
With “plain” Ansible, this means for you:
community.general)ansible.cfg and inventoriesAnd then it works differently on your colleague’s laptop than on yours because versions vary slightly.
With Polycrate, it looks different:
More about Ansible integration can be found in the Polycrate documentation on Ansible integration.
We start with a simple Polycrate workspace for a small fleet of Raspberry Pis.
Assume your workspace is in a Git repository and is called acme-corp-automation. In the root directory of the workspace is your inventory as a YAML file inventory.yml:
# inventory.yml (Ansible YAML inventory)
all:
children:
edge:
hosts:
pi-01.acme-corp.com:
ansible_user: pi
pi-02.acme-corp.com:
ansible_user: pi
pi-03.acme-corp.com:
ansible_user: pi
pi-04.acme-corp.com:
ansible_user: pi
pi-05.acme-corp.com:
ansible_user: piNotes:
edge is the group you target from the block with hosts_group: edge.inventory.yml.ANSIBLE_INVENTORY to this file.edge.hosts.This gives you the “map” of your edge fleet centrally in one place.
Next, we define a block in Polycrate that uses exactly these hosts for OTA updates and configuration.
More about workspaces can be found in the documentation on Workspaces.
We now create a block that:
apt upgradeDirectory structure (simplified):
acme-corp-automation/
workspace.poly
inventory.yml
blocks/
registry.acme-corp.com/acme/iot/edge-ota/
block.poly
ota-update.yml
deploy-config.yml
sensor-config.yml.j2(After polycrate pull registry.acme-corp.com/acme/iot/edge-ota:0.1.0, the block lives at this path.)
# blocks/registry.acme-corp.com/acme/iot/edge-ota/block.poly
name: registry.acme-corp.com/acme/iot/edge-ota
version: 0.1.0
kind: generic
config:
hosts_group: edge
service_name: edge-agent
serial: 10
config_path: /etc/edge-agent/config.yml
logging_level: INFO
actions:
- name: ota-update
description: Perform apt updates on all edge nodes
playbook: ota-update.yml
- name: deploy-config
description: Distribute configuration for sensors and logging
playbook: deploy-config.ymlImportant:
config defines all changeable parameters of your block—ideal for different fleets (e.g., other services, other paths).actions are named entry points. Your colleagues will later simply run polycrate run edge-ota ota-update without needing to know Ansible CLI details.More about blocks can be found under Blocks and Actions.
The associated Ansible playbook ota-update.yml is located in the same block directory:
# blocks/registry.acme-corp.com/acme/iot/edge-ota/ota-update.yml
- name: OTA Updates for Edge Nodes
hosts: "{{ block.config.hosts_group }}"
serial: "{{ block.config.serial }}"
become: true
gather_facts: false
tasks:
- name: Update package index
ansible.builtin.apt:
update_cache: true
cache_valid_time: 3600
- name: Update system packages
ansible.builtin.apt:
upgrade: safe
notify: Restart Edge Service
handlers:
- name: Restart Edge Service
ansible.builtin.service:
name: "{{ block.config.service_name }}"
state: restartedKey points:
hosts: "{{ block.config.hosts_group }}"edge group from your inventory.yml. You can reconfigure it in the block if needed.serial: "{{ block.config.serial }}"apt tasks are idempotent: If a device is already up to date, Ansible does nothing further.notify handler).With “plain” Ansible, you would need to:
ansible-playbook CLI (-i inventory.yml ota-update.yml)With Polycrate, it’s enough:
polycrate run edge-ota ota-updateThe command:
inventory.ymlNo local Ansible installation, no Python conflicts, no “works only on my laptop”.
Updates are only half the battle. Equally important is central configuration:
DEBUG vs. INFO)With Polycrate, you control this via the same block—a second action distributes a configuration file.
# blocks/registry.acme-corp.com/acme/iot/edge-ota/deploy-config.yml
- name: Distribute Configuration for Edge Nodes
hosts: "{{ block.config.hosts_group }}"
become: true
gather_facts: false
tasks:
- name: Create configuration directory
ansible.builtin.file:
path: "{{ block.config.config_path | dirname }}"
state: directory
owner: root
group: root
mode: "0755"
- name: Deploy configuration file from template
ansible.builtin.template:
src: sensor-config.yml.j2
dest: "{{ block.config.config_path }}"
owner: root
group: root
mode: "0644"
notify: Restart Edge Service
handlers:
- name: Restart Edge Service
ansible.builtin.service:
name: "{{ block.config.service_name }}"
state: restarted# blocks/registry.acme-corp.com/acme/iot/edge-ota/sensor-config.yml.j2
sensors:
sampling_interval_ms: 1000
logging:
level: "{{ block.config.logging_level }}"
destination: syslog
edge:
node_name: "{{ inventory_hostname }}"Here you see Jinja2 templates in action:
{{ block.config.logging_level }}block.config in your block.poly.INFO to DEBUG there, the new setting will be rolled out to all devices.{{ inventory_hostname }}pi-01.acme-corp.com etc.).Execution is again simple:
polycrate run edge-ota deploy-configWith two actions in one block, you now have:
Everything is versioned, well-structured, and can be shared with your team—this is the “Sharable Automation” concept of Polycrate.
To let Polycrate know which block to use in this workspace, you enter it in the workspace.poly:
# workspace.poly
name: acme-corp-automation
organization: acme
blocks:
- name: edge-ota
from: registry.acme-corp.com/acme/iot/edge-ota:0.1.0
config:
hosts_group: edge
service_name: edge-agent
serial: 10
config_path: /etc/edge-agent/config.yml
logging_level: INFOExplanations:
from: registry.acme-corp.com/acme/iot/edge-ota:0.1.0polycrate pull …, it lives under blocks/registry.acme-corp.com/acme/iot/edge-ota/.config:block.poly. This way, you can create a second block entry with a different service name for another hall.You can push your own blocks to the same registry and share them with other teams—or make them accessible via PolyHub. Polycrate supports you in this; see Registry documentation and PolyHub documentation.
Especially in OT environments, workspaces often contain sensitive data:
Polycrate comes with built-in workspace encryption using age. You don’t need to run an external secret store like HashiCorp Vault, but you can use it additionally if you wish.
Typical process:
You place secret files under artifacts/secrets/, for example:
artifacts/secrets/
id_ed25519
id_ed25519.pubYou encrypt the workspace:
polycrate workspace encryptBefore working, decrypt again:
polycrate workspace decryptPolycrate integrates these secrets automatically so you can reference them in playbooks via workspace.secrets without hard-coding paths.
Read more in the documentation on workspace encryption and SSH integration.
That bridges IoT practice and compliance requirements (e.g., internal policies, ISO 27001, or industry-specific rules).
To make the difference clear, consider what you would have to do with “plain” Ansible:
ansible.cfg, inventory.yml, playbooks, and secretsWith Polycrate:
polycrate run edge-ota ota-update or polycrate run edge-ota deploy-configThe rest runs in the container—including Ansible, Python, and additional tools. You get:
Best practices for structuring blocks and workspaces are in Best practices.
No. Ansible is agentless. On the devices you need:
pi with sudo)Polycrate does not change that—it only ensures Ansible runs on your side cleanly. You don’t install anything extra on the edge nodes.
Ansible marks the host as unreachable but does not abort the entire rollout—especially combined with serial.
With serial: 10, for example, 10 hosts are processed at a time. If one fails, the other nine continue. The unreachable host stays visible in the report and can be targeted again later.
Because the playbooks are idempotent, you can run the same Polycrate command again once connectivity returns. Ansible then only applies what is still missing.
Yes. Typical scenarios:
Because Polycrate is container-based, you get the same environment everywhere. You can start small—for example with only an OTA block—and add more blocks (monitoring, security, backups) later.
More questions? See our FAQ.
In this article you saw how to turn a messy collection of edge nodes into a manageable fleet:
For many IoT and OT teams, this step is critical:
Away from “someone SSHs in and fixes it somehow”—toward traceable, versioned, repeatable flows that still work in a year and can be audited.
At ayedo we support you with:
If you want to structure and automate your own edge fleet safely, a focused workshop is a good start—overview and registration: Workshops.
TL;DR The Polycrate API transforms individual workspaces into a team platform: all workspaces, …
TL;DR Polycrate not only logs Action Runs (Ansible playbooks) but also SSH sessions, workspace …
TL;DR A well-named, clearly structured Polycrate workspace is half the battle: a consistent name …