Skip to content

Releases: conn3xorg/conn3x

v0.6.4

Choose a tag to compare

@github-actions github-actions released this 27 Oct 12:09
Immutable release. Only release title and notes can be modified.
aad2e98

v0.6.4 makes refresh stop waiting on a host that moved, stops edits to one file from overwriting each other, and lets a step with an empty for_each plan cleanly. Two contributors cleaned up command help and the file docs.

Fixes

  • Moving sshd to another port no longer needs -refresh=false. Refresh reads each step with the connection recorded at the last apply, so after you moved sshd and changed port to match, the plan waited three minutes on the old port and then failed. Now refresh waits at most 10 seconds for a host. If nothing answers, the host's steps keep what the last apply recorded, you get a Host not reachable during refresh warning, and the plan goes on with the address in your configuration. A wrong host key or a rejected login still fails the refresh. conn3x drift treats an unreachable host as an error, so a host that's down never reports "No drift". (#131, fixes #130)
  • Command help says conn3x throughout. A few help texts inherited from OpenTofu still said "tofu plan" or "tofu apply". Now none do, and a test checks every command's help. (#137, fixes #134)
  • line and block edits to one file no longer lose each other's changes. Several edits to the same file on a host, such as a line step with for_each, ran at once, and each could write over the others. The apply reported every line added while the file kept one, and the next plan showed the rest as changes. Edits to one file on a host now take turns. (#141, fixes #139)
  • A step with an empty for_each has no instances, as OpenTofu's own for_each does. It used to fail the plan with Invalid for_each argument ... cannot be determined until apply, so an optional list a caller left empty broke the run. (#142)

Docs

  • The file module page says what happens when the login user can't read a file, and how to fix it. (#138, fixes #135)

Thanks

  • @dannyward630, for the last tofu mentions in command help, and the test that keeps them out (#137).
  • @coderbhawesh, for documenting the unreadable-file error on the file and template pages (#138).

Verify a download

cosign verify-blob \
  --certificate-identity 'https://github.com/conn3xorg/conn3x/.github/workflows/release.yml@refs/heads/main' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --bundle checksums.txt.sigstore.json checksums.txt
sha256sum --check --ignore-missing checksums.txt

Full changes: v0.6.3...v0.6.4

v0.6.3

Choose a tag to compare

@github-actions github-actions released this 26 Oct 15:23
Immutable release. Only release title and notes can be modified.
bcebdba

v0.6.3 fixes two races that could fail an apply on one host, makes a moved host's plan tell the truth, and adds two checks from contributors.

Fixes

  • Packages and services on one host take turns. Steps on one host run in parallel, and two of them could trip over each other. Installing related packages together, such as zip and unzip, could fail on dnf with Transaction test error: package unzip is already installed, because one install pulled in what the other had just put on the host. Several new services could each run systemctl daemon-reload at once, and one read back mid-reload failed with did not reach the wanted state. Package installs on a host now go one at a time, and so do service changes. Other hosts, and other kinds of step, still run in parallel. (#125, #126)
  • A new port that reaches another machine. Changing only a host's port planned an update, even when the new port reached a different machine behind the same address, so on_remove never ran on the old one. Conn3x now compares the host keys recorded for the two addresses, in host_key or known_hosts. If they share none, the plan replaces the host's steps. If they share one, it's the same machine, such as sshd moving to another port, and nothing is replaced. (#124, fixes #87)
  • A circuit declared in two files is now one Duplicate circuit error that names both files, instead of a run of duplicate-resource errors. (#120)
  • A readable HMAC key file. If your group or other users can read ~/.config/conn3x/hmac.key, plans and refreshes of content_wo files warn and print the chmod 600 command that fixes it. A key in CONN3X_HMAC_KEY isn't checked. (#95)

Thanks

Verify a download

cosign verify-blob \
  --certificate-identity 'https://github.com/conn3xorg/conn3x/.github/workflows/release.yml@refs/heads/main' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --bundle checksums.txt.sigstore.json checksums.txt
sha256sum --check --ignore-missing checksums.txt

Full changes: v0.6.2...v0.6.3

v0.6.2

Choose a tag to compare

@github-actions github-actions released this 26 Oct 07:34
Immutable release. Only release title and notes can be modified.
7743594

v0.6.2 fixes applies that fail on busy hosts, and two confusing reads and errors.

Fixes

  • Many steps on one host at once. Conn3x runs up to 10 resources in parallel, and each command opens an SSH session on the host's one connection. OpenSSH allows 10 sessions per connection by default, so with 10 or more in flight an apply could fail with ssh: rejected: connect failed ("open failed"). Commands now queue for a session, at most 8 at a time per connection, and Conn3x lowers that on its own for a server set to allow fewer. Set CONN3X_SSH_MAX_SESSIONS to change the limit. (#122)
  • Unreadable files: a file the login user can't read is an error that names the user, instead of reading as empty and planning a change that apply then fails to make. (#118)
  • Steps: a step with a module and another block, such as lifecycle, now names the block it doesn't take, pointing at it, instead of saying it needs exactly one module. (#116)

Thanks

Verify a download

cosign verify-blob \
  --certificate-identity 'https://github.com/conn3xorg/conn3x/.github/workflows/release.yml@refs/heads/main' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --bundle checksums.txt.sigstore.json checksums.txt
sha256sum --check --ignore-missing checksums.txt

Full changes: v0.6.1...v0.6.2

v0.6.1

Choose a tag to compare

@github-actions github-actions released this 26 Oct 04:07
Immutable release. Only release title and notes can be modified.
da6d5d7

v0.6.1 is a release of fixes: bastions named in your SSH config, handlers that run only when something changed, a CLI that speaks Conn3x everywhere, and the first change from an outside contributor.

There's no v0.6.0 release: its build showed a change that would have rejected host objects carrying fields of their own, which the docs recommend, so it was fixed first.

Fixes

SSH and circuits

  • ssh_config_file: a ProxyJump that names another Host entry is looked up in the same file, with its own HostName, User, Port and IdentityFile. A jump host whose name doesn't resolve fails at once instead of after the 3-minute timeout. (#112)
  • Handlers no longer run when the only change to a step is a setting that doesn't touch the host, such as on_remove, the ssh timeout or become_password_file. (#112)
  • each in the ssh block means the host in a step with for_each, as it does in every other step. (#110)
  • Host objects that set an ssh setting only the ssh block takes, such as become or timeout, are an error that names the setting, instead of being ignored. Fields of your own, such as role, are still allowed. (#110, #115)

CLI

  • conn3x drift works with a relative -chdir, and rejects -json with a pointer to conn3x plan -refresh-only -json instead of ignoring it. (#106)
  • conn3x fmt formats .circuit.hcl files. (#106)
  • conn3x version -json prints JSON, with a conn3x_version field. The version line in every -json stream names the Conn3x release, and the OpenTofu version no longer ends in -dev. (#106, #107)
  • conn3x init -json no longer prints the encryption warning as plain text. (#106)
  • Help and error text say conn3x instead of tofu everywhere, and convert ansible without a playbook says one is required. (#106)

Converter

  • conn3x convert ansible leaves a file task with state: link that sets owner, group or mode as a TODO that says why, instead of writing a link step that fails validation. (#103)

Docs

  • Every module page has examples and notes: how it reads, plans and applies, what removal does, and which Ansible modules convert to it. Paired arguments are marked "One of". (#98, #100, #101, #102)
  • Tutorials, from trying Conn3x locally to migrating a playbook.
  • A CLI reference with a page for every command, and the circuit language split into one page per topic.

Thanks

  • @Dodothereal, for marking both sides of an argument pair as "One of" in the module reference (#98). The first outside contribution to Conn3x.

Verify a download

cosign verify-blob \
  --certificate-identity 'https://github.com/conn3xorg/conn3x/.github/workflows/release.yml@refs/heads/main' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --bundle checksums.txt.sigstore.json checksums.txt
sha256sum --check --ignore-missing checksums.txt

Full changes: v0.5.0...v0.6.1

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 26 Oct 00:15
Immutable release. Only release title and notes can be modified.
d8401e8

v0.5.0 adds a module for the system locale and makes every file Conn3x writes safe against a power cut.

New

  • The locale module. Set the system LANG:

    step "lang" {
      locale {
        name = "en_GB.UTF-8"
      }
    }

    Conn3x uses update-locale on Debian and Ubuntu, and localectl or /etc/locale.conf on the Red Hat family, and reads the setting back from the same place. A locale that isn't installed is generated where locale-gen exists. On the Red Hat family, the error names the glibc-langpack package to add first. Tested on Rocky Linux 10, Fedora 45, Ubuntu 24.04 and Debian 13.

Fixes

  • Writes survive a power cut. file, template and download steps write to a temporary file and rename it into place. They now flush the new content to disk before the rename and the directory after it, so a crash right after an apply leaves the old file or the new one, never an empty one.

Docs

  • Module pages now carry examples and notes: how each module reads, plans and applies, what removal does, and which Ansible modules convert to it. file and package are first, and every example is checked against Conn3x in CI.
  • Host facts are now documented.

Verify a download

cosign verify-blob \
  --certificate-identity 'https://github.com/conn3xorg/conn3x/.github/workflows/release.yml@refs/heads/main' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --bundle checksums.txt.sigstore.json checksums.txt
sha256sum --check --ignore-missing checksums.txt

Full changes: v0.4.0...v0.5.0

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 25 Oct 22:31
Immutable release. Only release title and notes can be modified.
c91e616

Ansible users loop over things constantly. v0.4.0 lets a step do the same.

New

  • Repeat a step with for_each. A step can now run once per item, on every host:

    step "tools" {
      for_each = ["git", "jq", "tree"]
      package {
        name = item.value
      }
    }

    item.key and item.value are the current item, and each.key is still the host. for_each takes a list or set of strings, or a map. Drop an item and the next plan removes just that item from every host. Repeating a step has the details.

  • The Ansible converter translates simple loops. A task with loop: [a, b] over plain values, using {{ item }}, now becomes a step with for_each. Loops over variables, items with fields, loop_control and when still come out as TODO(convert) with the reason.

  • conn3x init suggests state encryption. When neither the configuration nor TF_ENCRYPTION encrypts state, init ends with a warning and a link to OpenTofu's state encryption. Conn3x state holds what it reads from your servers, so it's worth turning on.

Fixes

  • Handlers run when a hand edit is put back. If someone edited a file by hand, apply restored it but didn't run the handler, so a service could keep running the edited config. Every host step now has a revision that changes whenever Conn3x changes something on the host, and handlers watch it.

Upgrading

The first plan after upgrading shows each handler as updated in place while it records the new triggers. Nothing runs on your hosts, and the plan after that is empty.

Verify a download

cosign verify-blob \
  --certificate-identity 'https://github.com/conn3xorg/conn3x/.github/workflows/release.yml@refs/heads/main' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --bundle checksums.txt.sigstore.json checksums.txt
sha256sum --check --ignore-missing checksums.txt

Full changes: v0.3.0...v0.4.0

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 25 Oct 20:44
Immutable release. Only release title and notes can be modified.
4e63276

A database password has no business sitting in a state file. v0.3.0 keeps it out.

New

  • Secrets in files stay out of state. Give a file content_wo instead of content, or set write_only = true on a template, and the content reaches the host but not the plan or the state:

    variable "db_password" {
      type      = string
      ephemeral = true
    }
    
    step "db_password" {
      file {
        path       = "/etc/app/db-password"
        content_wo = var.db_password
      }
    }

    State records content_hmac, an HMAC-SHA256 of the file, so a hand edit on the host still shows up in the next plan, and apply puts your value back. Write-only files default to mode 0600.

    The HMAC key lives outside state too, in CONN3X_HMAC_KEY or ~/.config/conn3x/hmac.key, which Conn3x creates the first time it writes a secret. Share it with everything that runs against the same state, CI included. Secrets in files has the details, including how to pass the value in so it stays out of saved plans.

Fixes

  • Hosts behind one address. Two hosts reached through the same address on different ports got the same resource IDs. IDs now include the port when it isn't 22. Resources already in state keep their IDs, so upgrading plans no changes.
  • Module reference examples. Where two arguments are alternatives, such as firewalld's port and service, the example now sets one, so it validates.

Verify a download

cosign verify-blob \
  --certificate-identity 'https://github.com/conn3xorg/conn3x/.github/workflows/release.yml@refs/heads/main' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --bundle checksums.txt.sigstore.json checksums.txt
sha256sum --check --ignore-missing checksums.txt

Full changes: v0.2.2...v0.3.0

v0.2.2

Choose a tag to compare

@github-actions github-actions released this 25 Oct 18:03
Immutable release. Only release title and notes can be modified.
27a3fee

Your servers don't all sit on the open internet, and they don't all log in the same way. v0.2.2 stops pretending they do.

New

  • Jump hosts. If you reach the database through a bastion, say so in the ssh block:

    ssh {
      user       = "deploy"
      jump_hosts = ["deploy@bastion.example.com"]
    }

    Add more entries and Conn3x hops through each in turn. Every jump host's key is checked against known_hosts, the same as the target's.

  • Your SSH config. Already have Host web1 in ~/.ssh/config? Point Conn3x at the file with ssh_config_file = "~/.ssh/config" and use the alias as the address. It picks up HostName, User, Port, IdentityFile, ProxyJump and UserKnownHostsFile. Anything you set in the ssh block still wins, and Conn3x reads nothing until you set the option.

  • A login per host. A host in a circuit can now be an object instead of a bare address:

    hosts = {
      web = "10.0.0.4"
      db  = { address = "10.0.0.5", port = 2222, user = "admin" }
    }

    Its user, port, private_key_file, host_key and jump_hosts override the circuit's ssh block for that host alone. One circuit now covers a mixed fleet, and your inventory can be an ordinary variable or local.

  • Homebrew. brew install conn3xorg/tap/conn3x works on macOS.

Changed

user is no longer required in the ssh block when your SSH config supplies it. If neither one sets it, the error says exactly that. Plain-address hosts and v0.1 configurations work unchanged.

Verify a download

cosign verify-blob \
  --certificate-identity 'https://github.com/conn3xorg/conn3x/.github/workflows/release.yml@refs/heads/main' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --bundle checksums.txt.sigstore.json checksums.txt
sha256sum --check --ignore-missing checksums.txt

Full changes: v0.1.1...v0.2.2

There are no v0.2.0 or v0.2.1 releases. Both builds failed at the Homebrew step, and their tags stay because tags here are never moved or deleted.

v0.1.1

Choose a tag to compare

@github-actions github-actions released this 25 Oct 04:59
Immutable release. Only release title and notes can be modified.
3c4cd88

A fix for Fedora, found by adding Fedora 45 to the test hosts.

Fixes

  • Packages installed under another name. On Fedora, asking for wget installs wget2-wget, which provides it. v0.1.0 then checked for a package called wget, didn't find one, and failed the apply. Conn3x now also looks for what provides the name, so the step succeeds and the next plan is empty.

Testing

Fedora 45 now runs the full end-to-end suite on every change, alongside Rocky Linux 10, Ubuntu 24.04 and Debian 13.

Verify a download

cosign verify-blob \
  --certificate-identity 'https://github.com/conn3xorg/conn3x/.github/workflows/release.yml@refs/heads/main' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --bundle checksums.txt.sigstore.json checksums.txt
sha256sum --check --ignore-missing checksums.txt

Full changes: v0.1.0...v0.1.1

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 25 Oct 04:16
Immutable release. Only release title and notes can be modified.
a553351

Conn3x creates your servers and configures them in one plan. This is the first release.

If you run Terraform or OpenTofu to make machines and Ansible to set them up, you know the seam between them: an inventory script that turns state into hosts, a second run that might fail halfway, and two places to look when something drifts. Conn3x closes it. You write circuits, which are playbooks in HCL, beside your resources. One conn3x plan then shows the droplet about to be created next to the exact packages, files and services headed for it, wired to an IP address that doesn't exist yet.

What's in v0.1

  • One plan, one state, both layers. Every Terraform and OpenTofu provider works unchanged, because Conn3x is built on OpenTofu v1.13.2.
  • About 30 modules for the everyday work: files, templates, line and block edits, directories and links, packages and repositories, services and timers, cron, users, groups and SSH keys, sysctl, mounts, hostname and time zone, firewalld and ufw, SELinux booleans and file contexts, checksummed downloads, archives, git, guarded commands, reboots and wait_for, plus a conn3x_host data source for facts.
  • Diffs you can trust. Every plan reads the hosts first and shows what would change, line by line for files.
  • conn3x drift reports what changed by hand since the last apply, in the cloud and on the hosts, and exits 2 when it finds something.
  • conn3x convert ansible turns playbooks and inventories into circuits. Anything it can't prove means the same thing stays in the output, commented, with the reason.
  • Nothing on your servers. No agent, no Python. Conn3x connects over SSH, checks host keys every time, and runs plain shell commands as root or through sudo.

It runs on Linux and macOS, and configures Rocky, RHEL, AlmaLinux, Fedora, Debian and Ubuntu. The modules are tested end to end on Rocky 10, Ubuntu 24.04 and Debian 13. The ones that need a real kernel, such as SELinux, firewalls, sysctl, mounts and reboots, run against real DigitalOcean droplets instead, every night.

Start here: Install · Get started in 15 minutes · Migrate from Ansible

It's early, and we want to hear where it falls short. Questions and ideas go in Discussions, and bugs in Issues.

Verify a download

cosign verify-blob \
  --certificate-identity 'https://github.com/conn3xorg/conn3x/.github/workflows/release.yml@refs/heads/main' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --bundle checksums.txt.sigstore.json checksums.txt
sha256sum --check --ignore-missing checksums.txt

The archives also carry GitHub build provenance: gh attestation verify <archive> --repo conn3xorg/conn3x.

Full history: https://github.com/conn3xorg/conn3x/commits/v0.1.0