Your First Productive Polycrate Workspace: A Checklist for Getting Started
TL;DR A well-named, clearly structured Polycrate workspace is half the battle: a consistent name …
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.
Polycrate builds on Ansible but gives automation a clearer form. Three concepts are central:
block.poly, playbooks, templates, and artifacts.configure, patch, deploy) that executes exactly one playbook.Important: Polycrate always runs Ansible in a container. This solves the classic dependency problem:
Instead of complex Ansible CLI calls like:
ansible-playbook -i inventory.yml site.yml -e "env=prod" --tags "patch"you start a defined action:
polycrate run linux-baseline patchThe action knows its playbook, configuration, and container context. This is good DX/UX – even colleagues without deep Ansible knowledge can safely execute automations.
Blocks are described in detail in the official documentation on Polycrate Blocks .
Let’s look at a specific block that deploys Linux baseline configuration and patches. Directory structure in the workspace:
acme-corp-automation/
workspace.poly
inventory.yml
blocks/
linux-baseline/
block.poly
patch.yml
harden.yml
templates/
motd.j2
artifacts/
baseline-report.md# blocks/linux-baseline/block.poly
name: linux-baseline
version: 0.1.0
kind: generic
config:
os:
family: linux
reboot_after_patch: true
packages:
common:
- vim
- curl
- htop
motd:
enabled: true
text: "Managed by Polycrate – ACME Corp"
actions:
- name: patch
playbook: patch.yml
description: "Installs updates and optionally reboots"
- name: harden
playbook: harden.yml
description: "Applies basic hardening (SSH, Sysctl, MOTD)"Key points:
config: Default values of the block. These are later overridden or supplemented in the workspace.actions: Each action refers to exactly one playbook in the same directory.version: Version of the block template – important once the block is shared via a registry.The inventory is always in the workspace root as a YAML file inventory.yml. Polycrate automatically sets ANSIBLE_INVENTORY.
# inventory.yml
all:
hosts:
server01.acme-corp.com:
ansible_user: ubuntu
server02.acme-corp.com:
ansible_user: ubuntuThe inventory is YAML in the workspace root (not a classic INI-style hosts file).
The patch.yml accesses the block configuration:
# blocks/linux-baseline/patch.yml
- name: Patch Linux with Polycrate
hosts: all
become: true
gather_facts: true
vars:
reboot_after_patch: "{{ block.config.os.reboot_after_patch }}"
tasks:
- name: Update APT Cache
ansible.builtin.apt:
update_cache: true
when: ansible_facts.os_family == "Debian"
- name: Upgrade all packages (Debian/Ubuntu)
ansible.builtin.apt:
upgrade: dist
autoremove: true
when: ansible_facts.os_family == "Debian"
- name: Install YUM/DNF updates (RHEL/CentOS)
ansible.builtin.yum:
name: "*"
state: latest
when: ansible_facts.os_family in ["RedHat", "Rocky", "AlmaLinux", "CentOS"]
- name: Optional reboot after patches
ansible.builtin.reboot:
msg: "Reboot triggered by Polycrate linux-baseline.patch"
reboot_timeout: 600
when: reboot_after_patch | boolThe magic happens at block.config.os.reboot_after_patch: This variable does not come from vars_files or -e, but directly from block.poly or workspace configuration.
For a block to be truly reusable, it needs meaningful defaults – but also the ability to be overridden project-specifically. This is where Polycrate’s config inheritance (deep-merge) comes in.
As seen above:
config:
os:
family: linux
reboot_after_patch: true
packages:
common:
- vim
- curl
- htop
motd:
enabled: true
text: "Managed by Polycrate – ACME Corp"In the workspace, define how the block should look specifically for ACME Corp:
# workspace.poly
name: acme-corp-automation
organization: acme
blocks:
- name: linux-baseline
from: cargo.ayedo.cloud/ayedo/infra/linux-baseline:0.3.1
config:
os:
reboot_after_patch: false
packages:
common:
- vim
- curl
- htop
- jq
motd:
text: "ACME Corp – Managed Linux Server"Important:
from: is the OCI registry reference including the version tag (:0.3.1). Once the block is available locally (on the first polycrate run … you can confirm automatic installation from the registry; polycrate blocks pull remains optional), it lives under blocks/cargo.ayedo.cloud/ayedo/infra/linux-baseline/ (the path under blocks/ mirrors the URL).config:, you override and extend the block defaults.Polycrate deeply merges block config and workspace config. This means:
For our example, the effective configuration at runtime is:
# Effective block.config.* in the action linux-baseline.patch
os:
family: linux # from block.poly
reboot_after_patch: false # overridden in workspace
packages:
common: # list completely replaced
- vim
- curl
- htop
- jq
motd:
enabled: true # from block.poly
text: "ACME Corp – Managed Linux Server" # overridden in workspaceThis achieves:
More details on inheritance can be found in the documentation on Inheritance in Polycrate .
Polycrate provides a range of variables in every action without you having to explicitly pass them:
block.config.* – the merged block configuration (as shown above)workspace.* – information and configuration of your workspaceaction.* – metadata about the currently running actionAn extended example:
# blocks/linux-baseline/harden.yml
- name: Linux Baseline Hardening with Polycrate
hosts: all
become: true
gather_facts: false
tasks:
- name: Disable SSH Root Login
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^PermitRootLogin'
line: 'PermitRootLogin no'
create: false
backup: true
- name: Set MOTD if enabled
ansible.builtin.copy:
content: "{{ block.config.motd.text }}"
dest: /etc/motd
when: block.config.motd.enabled | bool
- name: Log Workspace Name
ansible.builtin.lineinfile:
path: /var/log/polycrate.log
line: "Hardened by workspace {{ workspace.name }} via action {{ action.name }}"
create: yesHere, all three levels come together:
block.config.motd.* – block or workspace-specific configurationworkspace.name – e.g., acme-corp-automationaction.name – e.g., hardenWhen working with secrets (e.g., SSH keys, certificates), these typically reside under artifacts/secrets/ in the workspace and are protected by the integrated Workspace Encryption
with age. In the playbook, they are available via workspace.secrets['filename'].
You can start the harden action above simply by:
cd acme-corp-automation
polycrate run linux-baseline hardenPolycrate ensures:
ANSIBLE_INVENTORY) are setblock, workspace, action are provided in the playharden.yml in the block directory, typically blocks/cargo.ayedo.cloud/ayedo/infra/linux-baseline/ once the block is available locally) is executed against the defined inventoryWith plain Ansible, you would need to:
ansible.cfg and inventory pathsWith Polycrate, this context is modeled in block and workspace.
More on Ansible integration is described in the official Ansible Integration of Polycrate .
You use the same registry reference (cargo.ayedo.cloud/...) to share and version blocks—in your team or via PolyHub
.
Polycrate uses OCI registries—the same protocol as Docker/OCI container images. The from line in the workspace is the canonical source; the version is always a tag at the end (:0.3.1).
Key points:
:latest—you want reproducible automation and controlled updates.blocks/<name>/—once published, you still reference it in workspace.poly with the full registry URL (see Inheritance
).As a block author, you want to share your work:
# In the block directory
cd acme-corp-automation/blocks/linux-baseline
# Push to the registry (version is in block.poly)
polycrate blocks push cargo.ayedo.cloud/acme/infra/linux-baselineOn another system or in another workspace, you can then use the same block:
# Make block available locally from registry (optional – often the first polycrate run is enough)
polycrate blocks pull cargo.ayedo.cloud/acme/infra/linux-baseline:0.1.0You often do not need an explicit polycrate blocks pull: if the block is missing locally, Polycrate detects that on the first polycrate run … and asks whether to install the block automatically. Then reference it in workspace.poly with this URL. This is shareable automation in its purest form: built once, usable many times – in your team.
TL;DR A well-named, clearly structured Polycrate workspace is half the battle: a consistent name …
TL;DR Plain Ansible is a powerful tool for ad-hoc automation, quick scripts, and simple setups – but …
TL;DR Most environments are hybrid: Windows servers for AD, file services, and specialized …