v0.4.0pre-1.0 · interfaces still moving
Ansible playbooks,
without the Python.
Parallax is a single Go binary that runs the playbooks, inventories and vaults you already have. Nothing to install on the targets — modules are compiled and shipped as static binaries.
curl -fsSLo parallax https://gitlab.com/api/v4/projects/23297967/packages/generic/parallax/v0.4.0/parallax-linux-amd64 && chmod +x parallax
Release v0.4.0 for Linux amd64. macOS, Windows and arm64 builds are on the releases page.
or from a checkout
git clone https://gitlab.com/digitalxero/parallax.git && cd parallax && go install ./cmd/parallax
- name: Configure web servers
hosts: web
gather_facts: true
vars:
docroot: /tmp/parallax-demo/www
tasks:
- name: Ensure document root exists
file:
path: "{{ docroot }}/{{ inventory_hostname }}"
state: directory
mode: "0755"
- name: Render the index page
copy:
dest: "{{ docroot }}/{{ inventory_hostname }}/index.html"
content: "hello from {{ inventory_hostname }}\n"
mode: "0644"
- name: Check the page is readable
stat:
path: "{{ docroot }}/{{ inventory_hostname }}/index.html"PLAY [Configure web servers] ***************************************************
TASK [Gathering Facts] *********************************************************
ok: [web1]
ok: [web2]
TASK [Ensure document root exists] *********************************************
changed: [web1]
changed: [web2]
TASK [Render the index page] ***************************************************
changed: [web1]
changed: [web2]
TASK [Check the page is readable] **********************************************
ok: [web2]
ok: [web1]
PLAY RECAP *********************************************************************
web1 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web2 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Verbatim output of
site/transcripts/play.yml,
re-recorded by task site:capture. The playbook on the left is the file that produced the output on the right.
How it works
- 01
Your playbook is parsed as-is
The same YAML, the same inventory files, the same vault. Parallax reads Ansible's formats directly — there is no conversion step and no separate project file to maintain.
- 02
Each module is compiled to a static binary
A task's module is built once for the target's OS and architecture, then cached on the controller. Subsequent runs reuse the cached binary instead of rebuilding it.
- 03
The binary is shipped over the existing connection and run
It is copied over SSH, executed, and removed. The target needs a shell and nothing else — no Python interpreter, no pip packages, no long-lived agent to install, patch or monitor.
Connections are pooled and reused across tasks. Architecture →
What we've actually measured
Parallax compiles each module to a static binary once and caches it. In our benchmark a warm cache hit was measured at more than 100× faster than recompiling the module. That is the conservative bound we are willing to put on a homepage; the full figures are in the linked results.
This is a synthetic Go benchmark using mock 1 MB binaries and a simulated 100 ms compile. It compares Parallax's cache to Parallax's own compiler. It is not a comparison against Ansible, and it does not measure a real playbook run. Methodology and full results →
We have no published end-to-end benchmark of Parallax against Ansible on the same playbook and host count, and no template rendering benchmark. Until those exist we would rather show you one number we can defend than three we cannot.
How it compares
Where Parallax wins, where it matches, and where Ansible is still the better tool.
| Capability | Ansible | Parallax |
|---|---|---|
| Controller runtime (Parallax ahead) | Python 3.x plus pip-installed dependencies | One static binary |
| Target requirements (Parallax ahead) | A Python interpreter on every managed host | None — modules ship as compiled binaries |
| Playbooks, inventory, vault (equivalent) | YAML, INI/YAML inventory, AES256 vault (1.1 & 1.2) | Same formats, read directly |
| Templating (mostly compatible, with caveats) | Jinja2 | gonja — Jinja2-compatible, not byte-identical |
| Connection types (mostly compatible, with caveats) | Large plugin ecosystem | ssh, local, docker, winrm |
| Handlers (equivalent) | Notified at end of play, or now with meta: flush_handlers | Same, including mid-play flush |
| Module library (Ansible ahead) | Thousands, via Galaxy collections | 133 built in |
| Role & collection distribution (Ansible ahead) | ansible-galaxy install | Vendor roles yourself; no Galaxy client |
| Custom modules and plugins (Ansible ahead) | Write in Python | Write in Go; existing Python plugins must be ported |
| Maturity (Ansible ahead) | Stable, over a decade of production use | v0.4.0, pre-1.0 |
What Parallax doesn't do yet
Read this before you plan a migration. These are the things that will stop a real playbook, not hypotheticals.
- Unsupported modules fail the play
- There is no Python fallback. A task using a module outside the
133 built in — anything from
community.docker,kubernetes.core,amazon.awsand most other collections — fails with couldn't resolve module/action. Check your playbooks against the module reference first. - No Galaxy client
- There is no
ansible-galaxyequivalent. Roles are read from disk, so anything you depend on has to be vendored into your repository or installed out of band.galaxy_infoin role metadata is parsed but not acted on. - Python plugins must be ported
- Custom modules, filters, lookups, callbacks and connection plugins are Go. Parallax loads them over go-plugin RPC; it cannot execute your existing Python ones. See the plugin porting guide.
- Templating is compatible, not identical
- gonja implements Jinja2 but is a separate engine. Common filters and control flow behave the same; unusual whitespace control, obscure filters and Python-specific expressions inside templates may not.
- Pre-1.0
- v0.4.0. The module SDK interfaces are still changing, so out-of-tree plugins may need updating between releases.
Everything on this list was verified against the binary at v0.3.0.
Try it
The playbook below is the one recorded at the top of this page. Both hosts use the local connection, so it runs on your machine with nothing else set up.
- 01 · Install
Install
curl -fsSLo parallax https://gitlab.com/api/v4/projects/23297967/packages/generic/parallax/v0.4.0/parallax-linux-amd64 && chmod +x parallaxor from a checkout
git clone https://gitlab.com/digitalxero/parallax.git && cd parallax && go install ./cmd/parallax - 02 · Files
Save an inventory and a playbook
inventory.ini[web] web1 ansible_connection=local web2 ansible_connection=localplay.yml- name: Configure web servers hosts: web gather_facts: true vars: docroot: /tmp/parallax-demo/www tasks: - name: Ensure document root exists file: path: "{{ docroot }}/{{ inventory_hostname }}" state: directory mode: "0755" - name: Render the index page copy: dest: "{{ docroot }}/{{ inventory_hostname }}/index.html" content: "hello from {{ inventory_hostname }}\n" mode: "0644" - name: Check the page is readable stat: path: "{{ docroot }}/{{ inventory_hostname }}/index.html" - 03 · Run
Run it
parallax play -i inventory.ini play.yml