Skip to content

Ansible ​

DockPod ships Ansible content alongside the Terraform provider. The two are deliberately not the same thing.

Owns
Terraformwhat exists — apps, domains, databases, links, as declared state with drift detection
Ansiblewhat happens — installing and updating DockPod across hosts, and the actions Terraform refuses to take

Terraform's provider will not trigger a build, for good reason: an apply that only touches configuration shouldn't swap your containers as a side effect. That leaves deploys, rollbacks, scaling, database backups and host cleanup with no declarative home — and installing DockPod itself has none either, since Terraform would need remote-exec for it.

Don't put both in charge of the same thing

If you define the same app in Terraform and in an Ansible playbook, you have two sources of truth. Terraform keeps state and Ansible doesn't, so every playbook run will show up as drift on the next terraform plan. Pick one owner per resource.

What's in the box ​

ansible/
  roles/dockpod/        install or update the binary + systemd unit
  playbooks/install.yml
  playbooks/configure.yml      domains, env vars, links — then ONE deploy
  playbooks/maintenance.yml    build-cache prune, database backups

It's a role plus ansible.builtin.uri tasks — not a Galaxy collection. No Python modules, no namespace to install. That's a deliberate first step: it works today and adds no second language to maintain. A proper hymns.dockpod collection is the right shape if demand shows up, and it's a real commitment on top of the panel and the Terraform provider.

Requires Ansible 2.15+. Verified against ansible-core 2.15.13.

Install or update ​

bash
cp inventory.example.ini inventory.ini   # then edit it
ansible-playbook playbooks/install.yml

The role reads the installed version with dockpod -version and only downloads when it differs, so running it against an up-to-date host does nothing. It also runs the downloaded binary before replacing the live one and refuses it if the reported version doesn't match — a truncated or wrong-architecture download arrives with a 200 and a plausible size, and executing it is the only check that catches that.

Pin a version instead of following Latest:

yaml
# group_vars/dockpod_hosts.yml
dockpod_version: v1.19.0

For rootless Podman, whose socket isn't in the auto-detect list:

yaml
dockpod_socket: /run/user/1000/podman/podman.sock

What the role deliberately doesn't do ​

It doesn't reproduce install.sh's host preparation: container engine install, swap sizing, sysctl/ulimit tuning, fail2ban, or the UFW/firewalld rules that stop a published container port bypassing the host firewall. Two copies of security-relevant logic would drift apart, and the Ansible copy would be the one that loses.

Run the installer once on a new host and let Ansible take over after:

bash
curl -fsSL https://dockpod.io/install.sh | bash

Or set dockpod_bootstrap_with_installer: true and the role will do that on a host with no binary yet.

Drive the API ​

bash
export DOCKPOD_API_KEY=dp_mcp_xxxxxxxxxxxxxxxxxxxx
ansible-playbook playbooks/configure.yml

Every task authenticates with a bearer token against the documented REST API.

Batch the config, deploy once ​

This is the pattern worth copying, and the reason Ansible fits DockPod well since v1.19.0:

yaml
- name: Add missing domains        # saved, not deployed
- name: Correct domains that differ # saved, not deployed
- name: Set environment variables   # saved, not deployed

- name: Deploy once to apply everything pending
  ansible.builtin.uri:
    url: "{{ dockpod_url }}/api/deploy/apps/{{ app.id }}/deploy"
    method: POST
  when: app_after.json.pending_changes | length > 0

Because configuration changes now record themselves instead of deploying (see Saving vs. Applying), a playbook that sets up three domains and a database link costs one deploy instead of four. Before v1.19.0 each task triggered its own — and on dockerfile, nixpacks or railpack apps each of those was a full image rebuild.

The when guard means a playbook run that changes nothing deploys nothing, which is what makes it safe to run on a schedule.

Correcting a domain rather than recreating it ​

configure.yml uses PATCH for a domain that exists but differs, not delete-and-recreate. Recreating drops the hostname's routing in between — and flipping redirect_www used to require exactly that, which is why the PATCH endpoint exists.

Maintenance ​

bash
ansible-playbook playbooks/maintenance.yml

Prunes the build cache and backs up every running provisioned database.

Build cache is the thing that actually grows on a host that keeps building — one real host accumulated 58.4GB from 199 builds over three months, while the image and volume prunes recovered 10KB between them. Nothing is lost: those are intermediate layers of builds that already finished, so the only cost is one slower build afterwards. See Scheduled Tasks.

If you'd rather DockPod did this on its own schedule than have Ansible drive it, the same operations exist as Scheduled Tasks (Pro) and the build-cache prune has a free manual button on the Images page.

Released under a commercial-friendly freemium license.