Marius replied to the below article:

Marius @Marius@marius.federated.id

After a couple of days percolating the idea, I made a couple of improvements to the tooling around #GoActivityPub services towards the goal of having a cool SSH based admin interface for them.

The first one was to add support for running the SSH server in parallel to the HTTP one, and respond to the same logic for starting and shutting down. This led to a refactoring the HTTP server initialization that was part of the signal wrapper module into its own separate module.

Before moving to an actual REPL interface I have added a basic middleware for Wish to handle commands passed through the ssh connection. The difficult part was to actually interface the existing types I was using for CLI commands, on top of Kong with the ssh middleware, which by itself was trivially simple. This led to quite a heavy refactoring of the packages, forced by Go’s prohibition of dependency cycles.

In the end it’s possible to pass a command to the ssh connection and it gets executed just as if it was run through the control binary on the host machine.

Another largish change this required was into passing io.Writer (and soon io.Reader) instances that corresponded to the output and error outputs (and soon input like I said). This was needed because by default commands executed by Kong use the default standard os.Stdout and os.Stderr and the commands themselves output text. This needs to get refactored into something better but for now it’s workable. So now we can pass the PTY from the ssh session to the commands and output gets sent to the correct place.

One downside to all of this, besides the forced package refactoring, is that the dependencies for the FedBOX service, which is the main place where I’m testing all of this, have increased somewhat with the inclusion of the Charm and Wish related modules. At least I added all this functionality behind a build tag.

To give an idea about what this allows me to do is that now I can operate the production, erm, testing, FedBOX server directly from my machine without needing to ssh to the box that hosts it just by configuring my local ssh client to use the host machine as a jump server:

Host admin.fedbox
    # Currently we use the full IRI for the Service actor
    # of FedBOX as a user
    User https://fedbox.example.com
    # The private key extracted from the Service actor
    IdentityFile ~/.ssh/admin.fedbox.example.com
    # The host server
    ProxyJump example.com:22
    # The local address on the host for FedBOX SSH
    Hostname 127.0.0.1
    # The local port on the host for FedBOX SSH
    Port 40022

To run a command now I just need to do the following:

$ ssh admin.fedbox oauth client list
0 beefaa5a-d00d-4767-94d9-f00ba4d6396d - http://127.0.0.1
1 18e8beef-1d2e-449d-a4d6-5f507f00bac1 - https://client.example.com/callback
Read more →
0

I think I can leave the SSH related part of the code be for a while, as I have managed to get the last piece required to have a robust method for issuing commands to a FedBOX server after installation.

This was the capability of accepting masked input for passwords or other small secret strings.

It took me a while to find the solution, but it was as simple as invoking the ssh client with a forced TTY allocation: ssh -t .... Generally ssh, and my own code in FedBOX, was assuming that if a command is passed the session does not need to be interactive, so reading input was not working properly.

The next step is to actually think about the API for the commands with the final goal being to improve the setup of mocked instances for integration tests.

A back of the napkin list would be:

  • Bootstrapping for a specific host - here we were missing bootstraping a specific host, not just the configured base URL.
  • Setting passwords for actors.
  • Adding OAuth2 client (or rely on dynamic client creation).
  • Adding actors.
  • Adding objects.
  • Running activities processing - this might actually be the best way for setting up a mock instance, because it allows us full control over the Activity, and it uses the correct code paths for object/activity creation.
0

If you have a fediverse account, you can quote this note from your own instance. Search https://marius.federated.id/posts/2026/january/ssh-input-woes on your instance and quote it. (Note that quoting is not supported in Mastodon.)