CertGrid CertGrid
Hands-on Lab·Podman

Podman Remote Client Setup

`podman system connection add` succeeds without testing anything, then the first real command fails with an ssh handshake error. Authorise the key and `podman --remote run` starts a container on the other machine while the local `podman ps` stays empty.

Registries and Remote Hosts Guide 38 of 47 Intermediate

Written against the versions above. Podman follows the distribution here rather than a vendor repository, so the version you get is the one Ubuntu shipped. The commands are stable across 5.x.

The 2 hosts these commands ran on: podman01, podman02.
Server NameIP AddressOSRolesCPURAMHDD
PODMAN01192.168.0.21Ubuntu 26.04 LTSPrimary Container Host2 Core4 GB50 GB
PODMAN02192.168.0.22Ubuntu 26.04 LTSRootless and Remote Client Host2 Core4 GB50 GB

Before you start

  1. A client with nothing configured

    On podman02, podman system connection ls is empty and podman ps shows the local engine's containers - none.

    The remote client is not a separate program. It is the same podman binary with --remote, or with a default connection configured, talking to the API socket from guide 70 over ssh. Nothing needs installing beyond Podman itself.

    It needs an ssh key, so create one if the client has none. This is the part worth pausing on: the transport is ssh, so everything you know about ssh authentication applies, and none of it is Podman's problem to solve.

    bash Example session
    podman system connection lsName        URI         Identity    Default     ReadWritepodman psCONTAINER ID  IMAGE       COMMAND     CREATED     STATUS      PORTS       NAMEStest -f ~/.ssh/id_ed25519 || ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_ed25519Generating public/private ed25519 key pair.Your identification has been saved in /home/sysadmin/.ssh/id_ed25519Your public key has been saved in /home/sysadmin/.ssh/id_ed25519.pubThe key fingerprint is:SHA256:RO+bjvsSckWSgkgs+oVKv3wH8oQ6b5emUnjVJnS0G+0 sysadmin@podman02The key's randomart image is:+--[ED25519 256]--+| o.. .....       ||. o ...o=..      ||.. .. o+.+.      ||... .o ++..      ||.oo.o o.SE.      ||...* o. o  o     ||  = = oo .o      || + + * ..o       ||  =o= . o+o      |+----[SHA256]-----+

    Expected resultNo connections, no containers, and a key present on the client.

    Success conditionThe client has an ssh key and no connections yet.

  2. Adding a connection proves nothing

    podman system connection add --identity ~/.ssh/id_ed25519 lab01 \
      ssh://sysadmin@192.168.0.21/run/user/1000/podman/podman.sock

    It succeeds silently, and connection ls lists it as default and read-write. Everything looks configured.

    Then the first real command fails:

    Error: unable to connect to Podman socket: failed to connect: ssh: handshake
    failed: ssh: unable to authenticate, attempted methods [none publickey],
    no supported methods remain

    connection add does not test the connection. It writes a configuration entry, and any error waits until you use it. Worth knowing so you test immediately with podman --remote info rather than discovering it inside a deploy.

    There is also a distracting provider: qemu line above the error. That is Podman's machine subsystem being mentioned because it assumes an unreachable socket might be a podman machine VM. On Linux it is noise - ignore it and read the ssh error.

    The missing step is ordinary ssh: append the client's public key to ~/.ssh/authorized_keys on the server. Podman does not do it for you and cannot.

    bash Example session
    podman system connection add --identity ~/.ssh/id_ed25519 lab01 ssh://sysadmin@192.168.0.21/run/user/1000/podman/podman.sockpodman system connection lsName        URI         Identity    Default     ReadWritepodman --remote info --format 'host={{.Host.Hostname}} rootless={{.Host.Security.Rootless}}'OS: linux/amd64buildOrigin: Ubuntuprovider: qemuversion: 5.7.0 Cannot connect to Podman. Please verify your connection to the Linux system using `podman system connection list`, or try `podman machine init` and `podman machine start` to manage a new Linux VMError: unable to connect to Podman socket: failed to connect: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain: ssh://sysadmin@192.168.0.21:22/run/user/1000/podman/podman.sock[exit 125]

    Expected resultA listed connection, then an ssh authentication failure on first use.

    Success conditionYou know the difference between a configured connection and a working one.

  3. With the key authorised

    podman --remote info now answers with host=podman01 - the client is reporting the server's hostname, and rootless=true because it is talking to podman01's rootless socket as podman01's user.

    Then the demonstration worth doing:

    podman02 $ podman --remote run -d --name from-afar -p 8094:80 nginx:alpine
    podman02 $ podman --remote ps      -> from-afar  Up
    podman02 $ podman ps               -> (empty)
    podman01 $ podman ps               -> from-afar  Up
    podman01 $ curl localhost:8094     -> http=200

    The container is entirely on podman01. podman02's own engine has nothing, and the published port is on podman01 - so curl works there and would not on the client.

    That is the mental model: --remote is a client, not a tunnel. The image is pulled by the server from the server's network, the container runs in the server's namespaces, volumes resolve on the server's disk. A -v ~/src:/src means the server's ~/src, which is the single most common surprise here.

    Drop the --remote by making a connection default - podman system connection default lab01 - and plain podman commands go remote. Convenient, and worth thinking twice about: your podman rm -af now runs somewhere else.

    bash Example session
    podman --remote info --format 'host={{.Host.Hostname}} rootless={{.Host.Security.Rootless}}'host=podman01 rootless=truepodman --remote run -d --name from-afar -p 8094:80 docker.io/library/nginx:alpinecb39211e1a35dee93f31465b39b35e331283d27983d2594856cad6657f5ce5b0podman --remote ps --format 'table {{.Names}} {{.Status}}'NAMES       STATUSfrom-afar   Up 1 secondpodman ps --format 'table {{.Names}} {{.Status}}'NAMES       STATUScurl -s -o /dev/null -w 'http=%{http_code}\n' http://localhost:8094http=200podman --remote rm -f from-afarfrom-afar

    Expected resulthost=podman01, a container visible remotely and on the server but not locally, and http=200 from the server.

    Success conditionYou started a container on another machine and know where its files would live.

Troubleshooting

Official sources