| name | bootstrap-linux-host-user |
| description | Securely initialize or update a key-only user on one or more existing Linux hosts over SSH. Use when Codex needs to create a Linux account, install an authorized SSH public key, add existing supplementary groups, grant explicitly requested passwordless sudo, migrate an unsafe password-based host bootstrap flow, or batch-initialize user access on arbitrary Linux servers without embedding personal data or private keys. |
Bootstrap Linux Host User
Use the bundled script to create or update one key-only Linux account over an existing privileged SSH connection. Keep all host addresses, usernames, public keys, private-key paths, and other identifiers outside the skill.
Safety contract
- Ask for filesystem paths to the public key, bootstrap identity, and host inventory. Never ask the user to paste key contents into chat.
- Never copy, upload, archive, inspect, print, or commit a private key. Pass its local path directly to
ssh -i.
- Accept only one valid SSH public-key line. Reject private-key markers and multi-line input.
- Create no password and lock password authentication for the managed account. Do not use
sshpass, chpasswd, or a default password.
- Preserve existing
authorized_keys entries and add the requested key only when absent.
- Use strict known-host checking by default. Never remove known-host entries or set
StrictHostKeyChecking=no. Use --accept-new-host-key only for a genuinely new host whose fingerprint can be verified out of band.
- Default to no sudo access. Use
--sudo-mode passwordless only when the user explicitly requests administrative access.
- Write sudo policy only to a dedicated
/etc/sudoers.d/90-host-user-bootstrap-<user> file and validate it with visudo before installation. Never edit /etc/sudoers directly.
- Require
--apply for remote mutation. First run without it, present the redacted plan, and apply only after the user requested or confirmed the changes.
- Do not disable root login or remove an existing account automatically. Verify the new account in a separate SSH session before proposing further hardening.
- Do not include disk formatting or mounting in this workflow. Treat storage initialization as a separate, destructive task.
Collect inputs
Obtain:
- one
--host or a --hosts-file with one hostname/IP per line
- the existing privileged
--login-user
- optional bootstrap
--identity private-key path; omit it to use the local SSH agent
- the new or existing
--user
- the matching
--public-key file path
- optional existing
--group values
- whether sudo is
none or explicitly passwordless
- optional SSH port and ProxyJump target
Do not store these values in the skill directory. Use assets/hosts.example only as a format example.
Preview
Run without --apply. The command validates inputs and reports only redacted target counts and operations:
python3 scripts/bootstrap_host_user.py \
--host 192.0.2.10 \
--login-user root \
--identity /absolute/path/to/bootstrap-private-key \
--user service-user \
--public-key /absolute/path/to/service-user.pub \
--sudo-mode none
For multiple hosts:
python3 scripts/bootstrap_host_user.py \
--hosts-file /absolute/path/to/hosts.txt \
--login-user root \
--identity /absolute/path/to/bootstrap-private-key \
--user service-user \
--public-key /absolute/path/to/service-user.pub \
--group docker \
--sudo-mode passwordless
If the existing SSH login is not root, it must already support non-interactive sudo -n. The script must never collect or transmit a sudo password.
Apply and verify
After reviewing the preview, repeat the exact command with --apply. Use --accept-new-host-key only when appropriate; otherwise require an existing trusted known-host entry.
The script redacts hosts, usernames, identity paths, and key material from output by default. Do not use --show-identifiers when capturing logs or responding to the user.
Verify through a separate connection using the private key corresponding to the installed public key:
ssh -i /absolute/path/to/managed-user-private-key service-user@192.0.2.10 \
'id && test -r ~/.ssh/authorized_keys'
When passwordless sudo was explicitly selected, additionally verify sudo -n true. Report verification results without reproducing host addresses, usernames, filesystem paths, key fingerprints, or key contents unless the user specifically asks to see them.
Failure handling
- On a changed host key, stop and ask the user to verify the new fingerprint out of band. Do not delete the old known-host record automatically.
- On
sudo -n failure, retry only with a privileged login account. Do not add password flags or prompt automation.
- On missing groups, correct the requested group list; do not create system groups implicitly.
- On partial batch failure, report target indexes and counts, not identifiers, then rerun idempotently for the failed targets after fixing the cause.
- On unsupported SSH key type or private-key input, stop and request the correct
.pub path.