Skip to content

conn3x generate step

conn3x generate step reads one object on a host and prints a step for it, with import = true at the top. Paste the step into a circuit and plan: the plan imports it with nothing to change. It doesn’t need a circuit or a working directory, and it changes nothing on the host.

This command is Conn3x only. For adopting a whole server, see Adopt servers you already run.

Terminal window
conn3x generate step -host <HOST> [options] <MODULE> [NAME=VALUE ...]

MODULE is the step’s module, such as file or service. The NAME=VALUE pairs are the arguments that identify the object: a file’s path, a package’s or service’s name, and so on.

$ conn3x generate step -host 203.0.113.10 -user root file path=/etc/motd
step "etc_motd" {
import = true
file {
path = "/etc/motd"
group = "wheel"
mode = "0640"
owner = "root"
content = <<EOT
Welcome $${user}
EOT
}
}
Option What it does
-host Host name or address to read from. Required.
-user User to log in as.
-port SSH port. Defaults to 22.
-private-key-file Private key to log in with. Defaults to the SSH agent.
-known-hosts-file known_hosts file to check the host against. Defaults to ~/.ssh/known_hosts.
-become Read as root through sudo, as become in a circuit’s ssh block. Most of what you’d adopt, such as /etc/nginx, units and users, needs it unless you log in as root.
-name The step’s name. Defaults to one made from the object: etc_motd for path=/etc/motd, nginx for name=nginx, or the module’s name for hostname, timezone and locale.
-write-only For a file: print content_wo with a placeholder, and keep the content on the host.

The host is checked against known_hosts the same way plan checks it. There’s no option to skip the check.

A string argument takes its text as written, so version=1.10 and mode=0640 stay as they are. Put it in double quotes if your shell would otherwise split it. Number, bool and list arguments are read as HCL, such as uid=1000, enabled=true or groups=["ops"].

An argument the module doesn’t have, a computed one, or one that’s never read from the host (content, content_wo, validate, on_remove) is an error, reported before anything connects.

generate step reads the object the same way a step’s import does, with the same import ID and the same read, so what it prints is what import = true would adopt. Arguments a module only reads back when they’re set, such as a file’s owner and group or a service’s state and enabled, come out as the host has them.

It covers the modules a step can import. For those whose reads only say whether the host matches, such as cron, sysctl and the firewall rules, there’s nothing more to read: the step holds the arguments you give, once the host is shown to have the object.

A file’s content is printed as a heredoc, with ${ and %{ escaped as $${ and %%{ so it stays literal. Content without a final newline, or with a line that would end the heredoc, is printed as a quoted string instead.

The step gets content_wo = "REPLACE ME", and a comment saying why, when:

  • the content isn’t UTF-8 text,
  • it’s over 64 KiB, or
  • you passed -write-only. Then the content is never read into the output, so a secret stays on the host.

Replace the placeholder with the real content, or a reference to it, before you plan.

Code Meaning
0 It printed a step.
1 An error, including a host that doesn’t have the object: 203.0.113.10 doesn't have file /etc/not-here.