The reminder I want to leave myself is not another command list. It is to check where the command is going before deciding what its result means.
The administrative shell and Cowrie's emulated shell had different SSH ports. The replacement administrative port was tested before Cowrie took the usual SSH port. That kept the doors separate, but it did not make an unqualified SSH connection an administrative connection.
The trap in my notes is exiting out of the real shell and reconnecting without specifying the administrative port. That connection lands in the honeypot. Something that looks like a shell is not enough to establish that I am working on the real server.
For future me, the checks belong before the work: confirm the identity and hostname, and check which process owns the listening socket. Do not start interpreting a command's result until the environment is clear.
The editor is not bash
The fake-filesystem work added another place to get this wrong. fsctl is an interactive editor, not a bash session. I pasted commands meant for that editor into the real shell, where they reached the actual server instead.
The ownership syntax caught me too. The usual combined owner-and-group form failed in fsctl; separate owner and group commands were the correction. A fake identity in the filesystem did not make that identity a real host account.
That is worth remembering before trying the same syntax again. Establish the interpreter, then use its commands. Familiar-looking paths and command names do not make the environments interchangeable.
The fake file itself also needs more than a name in a directory listing. Its directory entry and its loaded backing content are separate requirements, and the recorded size needs to match the content's byte count. Cowrie's configuration must point at the editable filesystem copy. A visible entry alone is not the finished file.
A stop message is not a stopped process
The process-control mistake had the same shape: trusting the surface instead of checking underneath it. A successful Cowrie stop message could leave a stale process holding the ports. The original forking unit also let systemd track the wrong PID and report the service dead while Cowrie was still serving traffic.
The documented correction was foreground execution under Type=simple. The check I want to retain is agreement between the live process PID, the socket owner's PID and systemd's main PID. The service label alone had already been misleading.
Before changing anything, ask where I am. After changing it, check what actually owns the resource. That is the part of this reference I want to remember, rather than just the command that appeared to work.