← Back to Projects

infrastructure · cli

rostr

One inventory, several standard artifacts, no new runtime dependency.

rostr keeps server knowledge in a versioned YAML inventory layer and derives SSH configuration, Ansible inventory, and a small host list from it. The tool shortens paths without replacing SSH or Ansible.

real command sequence · host counts omitted
$ rostr validate
 Inventory is valid

$ rostr sync
 SSH config updated
 Ansible inventory updated
 hosts.txt updated
The generator writes ordinary files. None of the outputs requires a running rostr process.

Context

Three copies of the same knowledge

Before rostr, server data lived in SSH configuration, Ansible inventories, and personal memory at the same time. New hosts, changed users, or a different operating state had to be reconciled in several places. Drift was rarely visible immediately.

Constraint

The shortcut must not become lock-in

The CLI could make access easier, but it could not place a proprietary runtime between the operator and the infrastructure. Inventory stays YAML, automation stays normal Ansible, and stacks stay Docker Compose. Generated files are output, not another manually maintained source.

Architecture

One readable source, deterministic derivations

During sync, rostr reads the inventory groups, applies defaults, validates fields, and writes three operational views. Tags and operating systems also become Ansible groups. Targets can be explicitly excluded from Ansible management.

01versioned YAML inventorygroups · hosts · defaults · tags · management state
rostr syncread · normalize · validate · write deterministically
  1. 02SSH configdirect access and jump aliases
  2. 03Ansible inventorygroups by area, tag, and OS
  3. 04hosts.txtsmall human-readable overview
Publicly abstracted. Relationships and file types match the current code; real hosts, addresses, and access paths are not shown.

Decisions

What is intentionally built this way

  1. 01

    Standard formats remain independent

    SSH, Ansible, and Compose must remain directly usable. rostr is a helper and control surface, not a required runtime layer.

    Tradeoff: Some workflows stay less polished because the standard tool remains the final authority.

  2. 02

    Generated output is never edited by hand

    Changes belong in the inventory. A new sync may replace every output completely.

    Tradeoff: Local exceptions must become inventory data or explicit generator logic.

  3. 03

    An inventory target is not automatically Ansible-managed

    An explicit management state keeps systems out of generated Ansible inventory when playbooks have no mandate there.

    Tradeoff: That boundary must be deliberately set and reviewed when a host is recorded.

  4. 04

    Fork instead of a complete rewrite

    The useful inventory and CLI base came from the MIT-licensed upstream. The private fork extends it into a personal infrastructure control repository.

    Tradeoff: Upstream provenance and private operating scope must remain separately and honestly described.

Implementation artifacts

Small excerpts that prove the behavior

inventory/groups/example.yaml
group:
  name: Production
  code: production
servers:
  - hostname: app-primary
    ip: 192.0.2.10
    os: ubuntu-24.04
    tags: [web, docker]
    ansible_managed: true
    active: true
Illustrative, anonymized excerpt with real field names. The address is reserved for documentation and belongs to no real system.
generated/ssh_config
# Auto-generated by rostr
Host app-primary
    HostName 192.0.2.10
    User deploy
The generated SSH file is ordinary OpenSSH configuration and remains useful without the CLI.
current repository slice · sensitive content omitted
rostr/
├─ src/rostr/   CLI
├─ inventory/   source
├─ ansible/     standalone
├─ stacks/      standalone
└─ generated/   output only

State and lessons

Less drift, more visible boundaries

What changed

One inventory change can refresh the operational views together. The same repository context also carries independently runnable Ansible playbooks used, among other work, for the dedicated-server rebuild in June 2026.

Drift is an architecture problem.

What remains imperfect

  • A single source can still become stale. Generation removes duplication, not the obligation to maintain it.
  • The private fork grew from an inventory CLI into a broader control repository. That extra surface demands more discipline around ownership and tests.
  • Local SSH-agent and include configuration remains necessary for some convenience paths. The generated standard files can still be inspected separately.