TL;DR
- Install Polycrate with a single
curlcommand – nopip, novirtualenv, no local Ansible installation required. - Initialize a workspace, understand its structure, and create your first Ansible block
webserverwithin it. - Build a meaningful Hello-World playbook that installs, starts, and checks the status of
nginxon a Linux host. - See how Polycrate always runs Ansible in a container – your team shares a clean, reproducible toolchain instead of Python chaos on every machine.
- Learn how ayedo provides a structured, shareable automation platform with Polycrate, scaling from individual admins to enterprise teams while addressing compliance requirements.
Why Start with Polycrate and Ansible?
For many admins and engineers, Ansible has long been the Swiss Army knife for automation: configurations, patches, deployments, Windows management, networking – everything is possible with playbooks.
You might know the problem from everyday life:
- Different Python versions on team laptops
ansibleinstalled only in an old virtualenv- Unclear
ansible.cfgsettings and scattered inventories - Playbook sprawl in Git repos without real structure
Polycrate addresses these issues without replacing Ansible:
- Dependency problem solved: Ansible always runs in a container, including the toolchain (Python,
ssh, optionallykubectl,helm, etc.). Your host only needs Polycrate, nothing else. - Guardrails instead of sprawl: Ansible code is organized in blocks. Each block has clear metadata (
block.poly), defined actions, and a reusable structure. - Good UX/DX: Instead of long
ansible-playbookcommands, you use simple actions likepolycrate run webserver install. Even colleagues without deep Ansible knowledge can execute this.
In this post, we will go through the following steps:
- Install Polycrate
- Initialize a workspace
- Build the first Ansible block
webserver - Execute an action and understand what happens in the background
- Brief comparison with plain Ansible
If you want to continue after this: Later posts will delve deeper into topics like block versioning, registry, and workspace encryption. You will lay the groundwork today.
Step 1: Install Polycrate
Polycrate comes with its own containerized toolchain. So you do not install Ansible directly on your system, but only the Polycrate CLI, which takes care of everything else.
The current installation instructions can be found in the
Installation Documentation.
Typically, installation on Linux and macOS boils down to a one-liner with curl. The pattern looks like this:
curl -sSfL https://<current-install-url-from-docs> | sudo bash
Important:
- Replace
<current-install-url-from-docs>with the URL from the official documentation. sudois necessary if Polycrate is to be installed system-wide (e.g., to/usr/local/bin).- After installation,
polycrateshould be in thePATH.
Then quickly check your installation:
polycrate version
You should see output similar to this:
polycrate version vX.Y.Z
Your local machine is now ready. Ansible, Python, etc., will be provided in the container, not on your host.
Step 2: Initialize Workspace
A Polycrate workspace is your project folder for automation – comparable to a Git repo, but with clear structure and metadata.
First, create a new directory and navigate into it:
mkdir acme-corp-automation
cd acme-corp-automation
Now initialize the workspace:
polycrate workspace init
Polycrate will ask you for a name for the workspace and then create the base files. The name is written into workspace.poly and serves as a logical identifier in larger setups.
Why this step is important:
- It anchors your automation in a consistent project structure.
- It is the basis for features like workspace encryption, block inheritance, and workflows.
- It ensures that Polycrate knows exactly where to look for blocks, inventories, and secrets.
Details on workspaces can be found in the
Workspace Documentation.
Step 3: Understand Workspace Structure
After polycrate workspace init, your directory typically looks like this:
.
├── workspace.poly
├── blocks/
├── artifacts/
│ └── secrets/
└── CHANGELOG.poly
The most important elements:
-
workspace.poly
Central manifest of the workspace. Here you define which blocks are active in this workspace, which workflows exist, and you can store workspace-wide configurations. -
blocks/
This is where your local blocks are located. Each block is a subfolder with at least oneblock.polyand the associated files (e.g., Ansible playbooks). -
artifacts/secrets/
Storage location for sensitive files, e.g., kubeconfigs or later encrypted secrets. Polycrate supports workspace encryption withage, allowing you to work securely even in regulated environments (see Workspace Encryption). -
CHANGELOG.poly
Optional but helpful for traceability. Here you can document changes to blocks and workflows – useful for compliance and audits.
Take a quick look at workspace.poly. Right after the init, it might look like this:
name: acme-corp-automation
We will soon expand this file with our first block.
Step 4: Create Inventory for Your Webserver
Before we build the first block, Ansible needs a target host. Polycrate always uses a YAML inventory in the workspace root as the default.
Create a file inventory.yml in the workspace root:
touch inventory.yml
Fill it in like this:
all:
hosts:
web01.acme-corp.com:
ansible_user: ubuntu
Explanations:
all.hosts.web01.acme-corp.comis your target host. Replace it with the real FQDN or IP of your server.ansible_useris the SSH user, e.g.,ubuntufor Ubuntu cloud images.
How exactly Polycrate gets your SSH keys and connections into the container is described in the
SSH Documentation. For this tutorial, we assume you can set up SSH access to the host.
Important: The inventory is always located in the workspace root and named inventory.yml. Polycrate automatically sets the environment variable ANSIBLE_INVENTORY to this file.
Step 5: Create First Block webserver
Now it gets concrete. We are building a block that:
- Installs
nginxon your host - Ensures the service is running
- Checks and outputs the status
5.1 Create Block Folder
Create the block folder:
mkdir -p blocks/webserver
cd blocks/webserver
5.2 Block Metadata: block.poly
In each block, there is a block.poly that describes:
- What the block is called
- What configuration it expects
- What actions it offers and which playbooks they execute
Create blocks/webserver/block.poly with the following content:
name: webserver
kind: ansible
config:
package_name: "nginx"
actions:
- name: install
description: "Installs nginx, starts the service, and checks the status"
playbook: install.yml
Key points:
-
name
The logical name of the block. We will later reference it in the workspace aswebserver. -
kind: ansible
Tells Polycrate that this block executes Ansible playbooks. -
config
Configurable values of the block. Here, for example, which package is installed. Later, you can also define port numbers, paths, etc., and use them in the playbook as Jinja2 variables. -
actions
List of actions this block offers. Each action has at least: name: Identifier forpolycrate run <block> <action>description: Documentationplaybook: the Ansible playbook to execute (relative to the block folder)
More on blocks: Block Documentation and
Best Practices.
5.3 Ansible Playbook: install.yml
Now comes our first meaningful Hello-World playbook. Create blocks/webserver/install.yml:
- name: Deploy webserver with nginx
hosts: all
become: true
gather_facts: true
vars:
webserver_package: "{{ block.config.package_name }}"
tasks:
- name: Update package cache (Debian/Ubuntu)
ansible.builtin.apt:
update_cache: true
when: ansible_os_family == "Debian"
- name: Install nginx
ansible.builtin.package:
name: "{{ webserver_package }}"
state: present
- name: Ensure nginx service is running and enabled
ansible.builtin.service:
name: "{{ webserver_package }}"
state: started
enabled: true
- name: Retrieve nginx status
ansible.builtin.command: systemctl status "{{ webserver_package }}"
register: nginx_status
changed_when: false
- name: Output nginx status
ansible.builtin.debug:
msg: "{{ nginx_status.stdout_lines }}"
What happens here?
-
hosts: all
All hosts frominventory.yml. Polycrate ensures the inventory is available in the container. -
become: true
Ansible usessudoto install packages and manage services. -
vars.webserver_package
Value fromblock.config.package_name(ourconfigblock fromblock.poly). This allows you to use the same block for different web server packages later without changing the playbook. -
Tasks:
- Update package cache (Debian/Ubuntu-specific)
- Install
nginx(or the configured package name) - Ensure the service is running and enabled
- Retrieve and output
systemctl status– so you can see in the output if everything is okay
Ansible is idempotent: If nginx is already installed and started, no unnecessary changes are made. Polycrate fully benefits from this strength.
Step 6: Register Block in Workspace
To let Polycrate know that this block exists, you need to register it in the workspace.
Navigate back to the workspace root:
cd ../../
Open workspace.poly and add the block entry:
name: acme-corp-automation
blocks:
- name: webserver
from: webserver
config:
package_name: "nginx"
Explanation:
-
blocks
List of all block instances in this workspace. -
name: webserver
Name of the instance in the workspace. It doesn't have to be, but can be the same as the block name. -
from: webserver
Path to your local block. For blocks from a registry (e.g., PolyHub), a URL with an explicit version would be here, e.g.,
from: cargo.ayedo.cloud/ayedo/infra/nginx:0.3.1
– we will cover versioning and sharing in a later post in this series. -
config
Workspace-specific configuration for this instance. These values end up in the playbook asblock.config.*.
Polycrate deliberately separates:
- Block definition (
block.polyin the block folder) - Block instance in the workspace (
blocks:inworkspace.poly)
This allows you to use the same block multiple times with different configurations.
Step 7: Execute Action
Now comes the moment of truth: We execute our block.
In the workspace root:
polycrate run webserver install
What happens:
- Polycrate reads
workspace.polyand finds the block `webs