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 …