Practical runbook for making the controlplane jail reachable by SSH and usable as an operator node • 09.03.2026
controlplane as the neutral hostname label. A fully qualified domain is optional for this jail and should not be treated as a bootstrap requirement.
The earlier bootstrap notes assumed too much. We assumed the clawdie user already existed inside the jail, assumed packages were already present, and assumed a domain-style hostname like ai.clawdie.si was necessary. In practice, none of those should be assumptions.
| Item | Final decision |
|---|---|
| Jail name | controlplane |
| Canonical hostname | controlplane |
| IP | 10.0.0.100 |
| SSH daemon | Use base FreeBSD sshd first |
| Operator user | clawdie in wheel and operator |
| Sudo model | /usr/local/etc/sudoers.d/wheel-nopasswd |
sshd and verify it is listening.ls, cat, grep, id, or groups. The first write should come only after the current shape is confirmed.
These were the minimum proven commands on the host.
jexec controlplane pkg update
jexec controlplane pkg upgrade -y
jexec controlplane pkg install -y bash sudo tmux curl python3
jexec controlplane pw usershow clawdie >/dev/null 2>&1 || jexec controlplane pw useradd clawdie -m -s /usr/local/bin/bash
Then prepare the home and group membership:
jexec controlplane install -d -o clawdie -g clawdie -m 700 /home/clawdie/.ssh
jexec controlplane pw groupmod wheel -m clawdie
jexec controlplane pw groupmod operator -m clawdie
The operator expectation is explicit now: clawdie should land in a working bash shell, not in /bin/sh.
jexec controlplane id clawdie
uid=1001(clawdie) gid=1001(clawdie) groups=0(wheel),5(operator),1001(clawdie)
Check the built-in FreeBSD SSH service before considering extra packages.
jexec controlplane which ssh
jexec controlplane which sshd
jexec controlplane ls -l /etc/rc.d/sshd
Then enable it:
jexec controlplane sysrc sshd_enable=YES
jexec controlplane service sshd start
jexec controlplane service sshd status
Generating RSA host key.
3072 SHA256:Z0m3th1n6-F4k3-RS4-K3y controlplane (RSA)
Generating ECDSA host key.
256 SHA256:Z0m3th1n6-F4k3-3CDS4-K3y controlplane (ECDSA)
Generating ED25519 host key.
256 SHA256:Z0m3th1n6-F4k3-3D25519-K3y controlplane (ED25519)
Performing sanity check on sshd configuration.
Starting sshd.
sshd is running as pid 38xxx.
At this stage the jail is reachable, but key authentication is not configured yet, so SSH falls back to password login.
[clawdie@osa ~/clawdie-ai]$ ping 10.0.0.100
PING 10.0.0.100 (10.0.0.100): 56 data bytes
64 bytes from 10.0.0.100: icmp_seq=0 ttl=64 time=0.42 ms
64 bytes from 10.0.0.100: icmp_seq=1 ttl=64 time=0.36 ms
^C
[clawdie@osa ~/clawdie-ai]$ ssh 10.0.0.100
The authenticity of host '10.0.0.100 (10.0.0.100)' can't be established.
ED25519 key fingerprint is SHA256:Z0m3th1n6-F4k3-3D25519-K3y.
Warning: Permanently added '10.0.0.100' (ED25519) to the list of known hosts.
(clawdie@10.0.0.100) Password for clawdie@controlplane:
That password prompt is expected until a public key lands in /home/clawdie/.ssh/authorized_keys inside the jail.
This is the exact pattern worth keeping. Read the live files first, then add the smallest possible change.
ls /usr/local/etc/sudoers.d
jexec controlplane cat /usr/local/etc/sudoers
The critical line already existed:
@includedir /usr/local/etc/sudoers.d
That made the drop-in path safe:
jexec controlplane ls /usr/local/etc/sudoers.d
jexec controlplane sh -c "printf '%s\n' '%wheel ALL=(ALL:ALL) NOPASSWD: ALL' > /usr/local/etc/sudoers.d/wheel-nopasswd"
jexec controlplane chmod 440 /usr/local/etc/sudoers.d/wheel-nopasswd
jexec controlplane visudo -c
/usr/local/etc/sudoers: parsed OK
/usr/local/etc/sudoers.d/wheel-nopasswd: parsed OK
clawdie is not really in wheel, sudo will still ask for a password even though the drop-in parses correctly.
The first login showed the actual issue clearly:
clawdie@controlplane:~ $ id
uid=1001(clawdie) gid=1001(clawdie) groups=5(operator),1001(clawdie)
After adding wheel and logging in again, the state became correct:
clawdie@controlplane:~ $ id
uid=1001(clawdie) gid=1001(clawdie) groups=0(wheel),5(operator),1001(clawdie)
clawdie@controlplane:~ $ sudo -i
root@controlplane:~ # id
uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)
clawdie was really in wheel, the NOPASSWD rule worked as expected.
The quick path used here was host-to-jail bootstrap first, then later a dedicated automation key can be generated inside controlplane for Ansible.
ssh-copy-id -i /home/clawdie/.ssh/id_ed25519.pub clawdie@10.0.0.100
ssh -o PasswordAuthentication=no clawdie@10.0.0.100
Once that works, password auth can be phased out in sshd_config.
controlplane is now the canonical hostname in bootstrap examples.ai.clawdie.si is no longer treated as mandatory jail identity.jexec controlplane pkg update
jexec controlplane pkg upgrade -y
jexec controlplane pkg install -y bash sudo tmux curl python3
jexec controlplane pw usershow clawdie >/dev/null 2>&1 || jexec controlplane pw useradd clawdie -m -s /usr/local/bin/bash
jexec controlplane install -d -o clawdie -g clawdie -m 700 /home/clawdie/.ssh
jexec controlplane pw groupmod wheel -m clawdie
jexec controlplane pw groupmod operator -m clawdie
jexec controlplane sysrc sshd_enable=YES
jexec controlplane service sshd start
jexec controlplane cat /usr/local/etc/sudoers
jexec controlplane sh -c "printf '%s\n' '%wheel ALL=(ALL:ALL) NOPASSWD: ALL' > /usr/local/etc/sudoers.d/wheel-nopasswd"
jexec controlplane chmod 440 /usr/local/etc/sudoers.d/wheel-nopasswd
jexec controlplane visudo -c