Ansible collection

The official chrisvanmeer.orbitron collection manages Orbitron with Ansible itself. One playbook run takes an empty host to a serving mirror: install the daemon, renderconfig.yml, bootstrap an admin token, declare roles & collections to mirror (with wait-for-sync), and take care of day-two operations like purging and pruning. Everything is idempotent โ€” rerunning an unchanged, fully mirrored playbook reports no changes.

Install the collection

GALAXYterminalbash
# latest
$ ansible-galaxy collection install chrisvanmeer.orbitron

# pin a version for reproducible runs
# (this binary embeds and caches v2.1.4 out of the box)
$ ansible-galaxy collection install chrisvanmeer.orbitron:2.1.4

The source lives in the repository, and the collection is published on Ansible Galaxy.

From empty host to serving cache

The two roles chain together: orbitron installs and operates the daemon, thenorbitron_mirror declares what to mirror and waits until it is synced.

PLAYBOOKorbitron_daemon.ymlyaml
---
- name: Install Orbitron and mirror a set of collections
  hosts: mirrors
  become: true

  roles:
    - role: chrisvanmeer.orbitron.orbitron
    - role: chrisvanmeer.orbitron.orbitron_mirror
      vars:
        orbitron_mirror_url: "http://127.0.0.1:8080"
        orbitron_mirror_token: "{{ orbitron_admin_token }}"
        orbitron_mirror_roles:
          - name: geerlingguy.nginx
            version: "3.3.1"
        orbitron_mirror_collections:
          - name: community.general
            version: "8.4.0"
          - name: community.docker
            version: "3.6.0"

The orbitron role โ€” install & lifecycle

Resolves and downloads the release binary, bootstraps the system user, directories, systemd unit and logrotate through --install, renders /etc/orbitron/config.yml, ensures the service runs and is healthy, and generates (or reuses) an initial admin token. Leftovers are removed cleanly with orbitron_state: absent.

ROLEorbitron_daemon.ymlyaml
- hosts: mirrors
  become: true
  roles:
    - role: chrisvanmeer.orbitron.orbitron
      vars:
        # leave orbitron_version unset to install the latest release
        orbitron_version: v1.3.2
        orbitron_listen_addr: 0.0.0.0:8080
        orbitron_token_ttl_days: 90
        # optional: forward proxy for outbound Galaxy / git traffic
        orbitron_http_proxy: http://squid.internal:3128
        # optional: prune versions not served within 60 days (dry-run by default)
        orbitron_prune_days: 60
        orbitron_prune_dry_run: true

After the run, orbitron_admin_token holds the effective admin token (yourorbitron_token vault value, or one generated and persisted to/root/.orbitron_token with mode 0600), and orbitron_version the installed release. Air-gapped installs point orbitron_binary_src at a pre-downloaded binary and optionally orbitron_checksum at its SHA-256.

The orbitron_mirror role โ€” declarative mirroring

Declares role & collection requirements โ€” either as the structuredorbitron_mirror_roles / orbitron_mirror_collections lists, or as requirements-file paths (orbitron_mirror_role_manifest_path /orbitron_mirror_collection_manifest_path) โ€” then waits for the sync (orbitron_mirror_wait_sync: true). Idempotent by version: pinned versions already mirrored report ok; force a full re-check withorbitron_mirror_sync_force: true.

Modules

Seven HTTP modules wrap the management API 1:1:

  • orbitron_info โ€” Read-only facts: health, storage inventory, manifests, sync status and tokens.
  • orbitron_token โ€” Create, rotate and revoke admin tokens โ€” idempotent by label, with optional TTLs.
  • orbitron_manifest โ€” Store role/collection requirements manifests โ€” idempotent by content hash.
  • orbitron_sync โ€” Trigger a full re-sync and optionally wait for it to finish.
  • orbitron_purge โ€” Remove one cached role or collection version.
  • orbitron_prune โ€” Access-based prune with a retention window โ€” dry-run preview by default.
  • orbitron_dump โ€” Download the whole cache as a .tar.gz backup โ€” streams to the controller, reports size + SHA-256.

Every module accepts url (default http://127.0.0.1:8080),token (also available via the ORBITRON_TOKEN environment variable),validate_certs and timeout. orbitron_dump addsdest, compress and a dedicated read_timeout, because a full-cache dump regularly pauses longer than a normal API call.

Day-two operations

TASKSday_two.ymlyaml
- name: Store a requirements manifest (idempotent by content hash)
  chrisvanmeer.orbitron.orbitron_manifest:
    token: "{{ orbitron_admin_token }}"
    type: collections
    collections:
      - name: ansible.posix
        version: all

- name: Trigger a full re-sync and wait for it
  chrisvanmeer.orbitron.orbitron_sync:
    token: "{{ orbitron_admin_token }}"
    wait: true

- name: Preview pruning โ€” versions not served in 60 days (dry-run by default)
  chrisvanmeer.orbitron.orbitron_prune:
    token: "{{ orbitron_admin_token }}"
    days: 60

- name: Drop a stale cached role version
  chrisvanmeer.orbitron.orbitron_purge:
    token: "{{ orbitron_admin_token }}"
    kind: role
    name: geerlingguy.nginx
    version: 3.3.0

- name: Back up the whole cache
  chrisvanmeer.orbitron.orbitron_dump:
    token: "{{ orbitron_admin_token }}"
    dest: /var/backups/orbitron/nightly.tar.gz
    read_timeout: 1800
  register: dump

Token lifecycle

TASKStokens.ymlyaml
- name: Create (or reuse) a short-lived CI token
  chrisvanmeer.orbitron.orbitron_token:
    url: "http://127.0.0.1:8080"
    token: "{{ orbitron_bootstrap_token }}"
    label: ci-builder
    ttl_days: 30
  register: ci_token
  no_log: true

- name: Gather facts and assert the mirror is healthy
  chrisvanmeer.orbitron.orbitron_info:
    token: "{{ ci_token.orbitron.token }}"
  register: info

- name: Fail when the mirror is unhealthy
  ansible.builtin.assert:
    that:
      - info.orbitron.health.status == "ok"