TractorStackdocs
Docs menu

Docs / Make changes safely

The site runner

Planned design. TractorStack is in development. This page describes how it is designed to work; nothing here is available to install yet. See the roadmap for the status of each part.

Planned Committed, and built after the first stage. Everything below is the planned design.

Somewhere on each site, something has to run the commands that change infrastructure. The on-site runner for OpenTofu and Ansible is that machine: a small VM or server that runs GitLab Runner, picks up jobs from your self-hosted GitLab, and does the work in short-lived containers. Its main job beyond running commands is secrets management in the plainest sense: the credentials for your hypervisor, switches and servers live on this machine and nowhere else.

The on-site runner for OpenTofu and Ansible

The site runner is planned as a dedicated, hardened VM with GitLab Runner installed and registered to the environment’s project or group. When a merge request pipeline starts, GitLab hands the job to the runner, and the runner starts a fresh container from a pinned image that contains OpenTofu, Ansible and the collections the environment needs. When the job ends, the container is removed. Nothing from one job is left behind for the next, apart from what was written on purpose to state or artifacts.

A runner usually serves one site. A site with separate test and production environments can have one runner for each, so a test job never holds production credentials.

What it talks to

DirectionToWhy
OutboundYour GitLab serverPick up jobs, send logs and results
OutboundProxmox VE API, or your other hypervisor’s APIOpenTofu creates and changes VMs, storage and networks
OutboundManaged hosts over SSHAnsible configures them
OutboundPostgreSQLRead and lock OpenTofu state
OutboundLocal registry and mirrorsPull job images, providers and packages
InboundNothingGitLab Runner polls for work, so no port needs to be open towards it

Proxmox VE is the primary target. On vSphere or another hypervisor the runner talks to that platform’s API instead, and on bare-metal sites it may only need SSH to existing machines. Either way, the firewall rules are narrow and written in the repository like everything else.

Credentials stay on site

Even if your GitLab server sits in another building, it holds code and approvals, not the keys to the hypervisor. See secrets and credentials for how keys are rotated.

Planned job image

An illustrative .gitlab-ci.yml fragment, not from a release:

# Planned example only
plan:
  image: registry.plant-a.internal/tractorstack/runner:1.0.3
  tags: [plant-a-prod]
  script:
    - tofu -chdir=tofu init
    - tofu -chdir=tofu plan -out=plan.bin
    - ansible-playbook ansible/site.yml --check --diff
  artifacts:
    paths: [tofu/plan.bin]
    expire_in: 1 day

The tags line makes sure only this site’s runner picks up the job. On offline sites, the image and everything in it come from local mirrors.

Runner sizing, the secret store and the container executor are still being chosen. The rules above (short-lived jobs, no inbound ports, credentials on site) are the parts we expect to keep.

Last updated 25 October 2026 · Questions or corrections: sales@infratractor.com