Bridge a D-Bus Connection with systemd-stdio-bridge

systemd-stdio-bridge is the remote end of a D-Bus connection carried over standard input and output, exactly what an SSH hop or a container needs. This guide covers the system bus, a user bus, containers and an explicit bus address, while keeping the bridge's binary traffic away from your terminal. Allow about fifteen minutes.

The bridge is not a general-purpose text command: when it is running normally, its standard streams carry D-Bus messages, not anything readable.

1. Check the installed bridge

Confirm which executable will run. This is an ordinary, read-only check that needs no elevated privileges.

$ command -v systemd-stdio-bridge
/usr/bin/systemd-stdio-bridge
$ dpkg-query -W -f='${Package} ${Version}\n' systemd
systemd 255.4-1ubuntu8.17
$ systemd-stdio-bridge --version
systemd 255 (255.4-1ubuntu8.17)

The installed manual describes the program as a proxy between standard input/output and a D-Bus bus. It expects the first connection on those streams and opens a second connection to the selected bus, returning zero on success and a non-zero status on failure.

Checkpoint: the path is the systemd executable you intended to use, and its package version is recorded. If command -v finds nothing, stop and install or repair the normal systemd package through your distribution's package manager.

2. Keep the bridge inside a transport

Warning: do not start the bridge by itself in an interactive terminal and then type into it. Its streams are a protocol endpoint, not a command prompt: a text terminal cannot provide a useful D-Bus client connection, and binary output may make the terminal display confusing characters.

The normal shape is a client on one side and systemd-stdio-bridge on the other. For an SSH hop, a D-Bus-aware client starts the remote command over SSH, leaving SSH to carry the remote process's standard streams.

$ ssh USER@HOST systemd-stdio-bridge --system

This line is a transport building block, not a complete D-Bus query by itself. Replace USER@HOST with a real SSH target and invoke it through the client that requested the remote D-Bus connection; the bridge reads and writes the connection, it does not print a human-readable session transcript.

There is no persistent configuration to undo here. When the client closes the connection, SSH and the bridge exit. If you have accidentally started a foreground bridge, use Ctrl-C in that terminal: this stops that process but does not change the bus or its services.

3. Select the system or user bus

The default is the local system bus, equivalent to --system. Make that choice explicit in scripts and remote commands so a later reader does not have to remember the default.

$ ssh USER@HOST systemd-stdio-bridge --system

Use --user instead when the bridge should connect to the calling user's service manager and user bus.

$ ssh USER@HOST systemd-stdio-bridge --user

These options select the bus the bridge opens on its local side. They do not change the identity of the SSH connection, grant access to another account, or turn a system service into a user service. The remote account still needs permission to connect to the selected bus.

Checkpoint: choose exactly one of --system and --user. Omit both and the installed command falls back to the system bus. A failed connection is usually a bus availability, session environment or authorisation problem, not a reason to add sudo blindly.

4. Target a local container

Use --machine=CONTAINER, or its short form -M CONTAINER, to connect to a local container. With no user prefix, the manual says the connection is made as root in the named container.

$ systemd-stdio-bridge --machine=CONTAINER_NAME

Put a user name before @ to select the account instead, for example --machine=alice@CONTAINER_NAME. The special name .host means the local host, which is useful when selecting a particular user's user bus.

$ systemd-stdio-bridge --user [email protected]

Do not confuse --machine with an SSH destination: it addresses a local container through systemd's machine interface. The container or host must exist and be reachable by the local systemd environment before a D-Bus client can use the bridge.

Because these commands only open a bus connection, they do not create or remove a container. A failed attempt has no service-management rollback to perform. If the target is missing, check the machine name with your normal systemd machine-management tools before retrying.

5. Supply an explicit bus address

--bus-path=PATH, also written -p PATH, overrides the default bus address unix:path=/run/dbus/system_bus_socket. Use it when the service is deliberately exposed at a different D-Bus address.

$ systemd-stdio-bridge --bus-path='unix:path=/run/dbus/system_bus_socket'

That command just spells out the installed default; it does not make the bridge useful as a standalone terminal process. In a real transport command, keep the address as one shell argument.

$ ssh USER@HOST systemd-stdio-bridge --bus-path='unix:path=/run/dbus/system_bus_socket'

Warning: only use an address from a trusted configuration source. A bus address can select a different socket or transport, and connecting to the wrong bus can expose the client to an unexpected service namespace. Do not paste an untrusted address into a privileged service or automation job.

6. Verify option parsing without opening a bus

The help path is the safest local smoke test, since it exits before trying to proxy a connection.

$ systemd-stdio-bridge --help
systemd-stdio-bridge [OPTIONS...]

Forward messages between a pipe or socket and a D-Bus bus.

  -h --help              Show this help
     --version           Show package version
  -p --bus-path=PATH     Path to the bus address (default: unix:path=/run/dbus/system_bus_socket)
     --system            Connect to system bus
     --user              Connect to user bus
  -M --machine=CONTAINER Name of local container to connect to

If an automated check needs to test failure handling, use a temporary, deliberately invalid bus path through a D-Bus client that supplies the bridge's standard streams. Do not redirect a normal terminal into the bridge and read the result as a D-Bus test. Record the client's exit status and its diagnostic; the bridge's own contract only promises zero for success and non-zero for failure, not one fixed error number or wording.

Done means