Skip to content

Releases

podssh v1.1.0-beta.3

podssh v1.1.0-beta.3 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 05 Nov 01:13

podssh v1.1.0-beta.3

The third beta of milestone M10, and the first one after the study of osewa
(docs/research/osewa.md): what a user feels on a slow or busy link is now
measured, and podssh's SSH client keeps a key's echo near the link's round
trip while a download runs on the same connection, against any sshd and
through each road; a session resumes in about a second after the client
moves; and a cold connect takes two round trips fewer. The relay role
gains the hardening that a tester asked for (GitHub #126 to #148). A beta is
a prerelease. Its tag never moves: a defect found in it goes into the next
beta.

What to test again

What a user feels (the study of osewa, Q99):

  • podssh ping DEST --under-load types 40 keys beside a download on the
    same connection and gives the echo's p50 and p95; --connect-runs N
    times N cold connects (T-660). scripts/feel-matrix.py runs each road
    through the four links of osewa's lab on the loopback.
  • Typing-aware SSH windows: while a key waits for its echo, a bulk
    channel's window is held to the path's round trip and 40 ms, and each
    socket that podssh dials keeps 16 KiB unsent; where nobody types, a
    window grows to the path, up to 16 MiB on --direct (T-661, T-662). The
    server's messages are of 8 KiB, and a window is topped up once a quarter
    of it is used (T-670). Measured on the loopback, a key's echo beside a
    download: about 100 ms on a cellular link where OpenSSH's is 1.6 s, and
    0.4 s on a link of 1 Mbit/s where OpenSSH's is 16 s. The download while
    typing on a long fast link is slower than before (T-670, partial).
  • Liveness in round trips: a spare link after three round trips of
    silence, 1 s to 3 s, and a check when the host wakes; a session resumed
    in 1.0 s after the client's new address, where it took 3 s (T-663).
  • A faster cold connect: the key that a host took is signed in the first
    request, the pty's request and the command's go together, and a relay
    host's TLS group is kept (T-664): two round trips fewer, faster than
    OpenSSH's own client to the same sshd on the loopback's links.
  • The resumable layer ends one direction (END), so a request, its end and
    the reply after it cross the relay role's layer road (T-632).
  • The iroh road: PODSSH_IROH_QUIC chooses QUIC's settings at both ends
    (iroh's own by default, tuned, bbr, newreno; T-665, partial: the
    default waits for an A/B run), and the SSH connections of one process to
    one node share one iroh connection, a copy's stream below a terminal's,
    once both ends agree on podssh/2 (T-666, partial).
  • The record of the keys that hosts took keeps each host's key when
    podssh each logs in to several at once (T-675).

The relay role, podssh relay serve (GitHub #126 to #148):

  • A name that the role does not dial gets one 403 that names no address
    (T-628, #126).
  • It keeps no capability after its bind (T-629, #127); a list of private
    ranges that it may dial, --routes (T-635, #133); a share of the pairs
    for each key that may mint (T-630, #128); a turn for each session on a
    node's socket (T-648, #146); a target's bytes after the client's Close,
    as the contract says (T-671); a pair that halts without ending,
    podssh relay halt and relay resume (T-647, #145).
  • podssh pipe ws-listen: answers a request that is not an upgrade with a
    page from --cover DIR, and an upgrade with no key with --raw-upgrade
    (T-639, T-645, #137, #143).
  • A retired PODSSH_* variable is refused by name (T-634, #132); a node's
    lines keep their priority in the journal (T-640, #138).

The files

File For
podssh-x86_64-unknown-linux-musl Linux on x86-64, static: no library and no loader needed
podssh-aarch64-unknown-linux-musl Linux on aarch64, static
podssh-armv7-unknown-linux-musleabihf Linux on 32-bit ARM with hard float, static
podssh-riscv64gc-unknown-linux-musl Linux on 64-bit RISC-V, static
podssh-aarch64-apple-darwin macOS on Apple silicon; it links the system's libraries only
podssh-x86_64-apple-darwin macOS on Intel
podssh-x86_64-pc-windows-msvc.exe Windows on x86-64, with a static C runtime
podssh-aarch64-pc-windows-msvc.exe Windows on ARM64, with a static C runtime
SHA256SUMS The SHA-256 of each binary
SHA256SUMS.sigstore.json The signature of SHA256SUMS: Sigstore's keyless signing, by the release workflow at this tag
provenance.sigstore.json The provenance of each binary (SLSA), signed the same way: the workflow, the tag and its commit
THIRD-PARTY-LICENSES.md The licenses of the crates in the binaries, with their texts

Check a download

T=v1.1.0-beta.3; B=podssh-x86_64-unknown-linux-musl   # or another file of the table
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/$B"
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/SHA256SUMS"
grep " $B\$" SHA256SUMS | sha256sum -c - && chmod +x "$B"
./"$B" --version   # podssh 1.1.0-beta.3 (the commit of the tag)

podssh update --version v1.1.0-beta.3 from v1.1.0-beta.2, v1.1.0-beta.1 or v1.0.1
takes it, checked by its signature; a build of a release follows releases
alone, so without --version it stays on v1.0.1. The provenance and the
signature are checked as for v1.0.0 (its notes),
with T=v1.1.0-beta.3.

How it was checked

By the operator's ruling Q88 (2026-11-03), until podssh is stable: the gate
green at the tag's commit, the release workflow by hand on it, and the short
form of its binary (scripts/release-short.sh BINARY --net); after the tag,
release-proofs.yml and update-live.yml. The whole release check and the
live runs of each road wait until then.

What a beta does not have yet

  • The whole check of a release from end to end with no human
    (scripts/release-check.sh, T-251): it waits (Q88).
  • Signatures of the platforms: the Mac binaries are not signed with an
    Apple Developer ID, and the Windows binaries carry no Authenticode
    signature, so SmartScreen may warn. The proofs above stand in for them.

Report a defect

Open an issue at https://github.com/Azathothas/podssh/issues with the
output of podssh --version and podssh doctor --json. Read that output
before you post it: it names this host's proxy and addresses, and never a
token or a password.

The licenses of the crates in the binaries, with their texts: THIRD-PARTY-LICENSES.md.

The commits of this release

Other

  • Research: osewa against podssh, the reality check (Q99); its gaps filed as T-660 to T-669 (856940b)
  • The record: the ninth round of drafts, in progress (the triage of #127 to #148, T-660 to T-663) (0b7f303)
  • Triage: GitHub #127 to #148 as T-629 to T-650 (Q100) (6d90d04)
  • WARP's tests: a stand-in edge forgets what an earlier test met at its port (7e6b9bc)
  • The record: the citations of road.rs and stand_in.rs moved with the repair of WARP's tests (c65cfc4)
  • node_cut's test: the stand-in's late close gives the node the 1003 that its frame would get (fb018a7)
  • T-660, partial: what a user feels, measured: ping --under-load and --connect-runs, osewa's four links, and the matrix of roads (a940886)
  • T-663 done: liveness in round trips: a spare link after three round trips, and a check when the host wakes (b7f78d6)
  • T-661 done, T-662 partial: typing-aware SSH windows against any sshd, and windows that grow to the path (1525a6c)
  • v1.1.0-beta.2 published (Q98): STATUS marks its 80 rows; the proofs of its published files passed (release-proofs 41892109498, update-live 41892114409) (6971076)
  • T-632 done: the resumable layer ends one direction: END, and podssh proxy's stdin on it through the relay role (c3a9b89)
  • T-629 and T-635 done: relay serve keeps no capability after its bind, and a list of private ranges that it dials (GitHub #127, #133) (ce411ac)
  • The record: GitHub #127 and #133 closed with T-629 and T-635 (ce411ac) (3775c2f)
  • T-630 and T-648 done: a key's share of the relay role's pairs, and a turn for each session on a node's socket (GitHub #128, #146) (4ae2284)
  • The record: GitHub #128 and #146 closed with T-630 and T-648 (4ae2284) (df92546)
  • T-664 done: a faster cold connect: the key a host took signed in the first request, the pty's request and the command's together, the TLS group kept (b9cfebc)
  • T-671 and T-647 done: the relay role keeps a target's bytes after the client's Close, and a pair halts without ending (GitHub #145) (8caa6f0)
  • The record: GitHub #145 closed with T-647 (8caa6f0) (8f6fa3a)
  • T-670, partial: the slow link's echo beside a download, from 2.4 s to 0.4 s by --direct (a6a1de0)
  • T-634 and T-640 done: a retired PODSSH_* variable refused by name, and a node's lines keep their priority in the journal (GitHub #132, #138) (91669ae)
  • The record: GitHub #132 and #138 closed with T-634 and T-640 (91669ae) (bc22f0f)
  • T-639 and T-645 done: pipe ws-listen serves a cover page, and takes a keyless upgrade...
Read more

podssh v1.1.0-beta.2

podssh v1.1.0-beta.2 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 04 Nov 18:47

podssh v1.1.0-beta.2

The second beta of milestone M10: the relay as a role of podssh itself
(podssh relay serve) and the net of a user's own nodes grow by many
parts, and the default list of relay hosts takes a rank that this host
measured. A beta is a prerelease. Its tag never moves: a defect found in it
goes into the next beta.

What to test again

The relay role, podssh relay serve:

  • A proxy that refuses the WebSocket upgrade: the HTTP road carries the
    session in plain requests, where a probe found the upgrade refused
    (T-319, its first part; Q44).
  • HTTP/2: a host's sessions of one process are streams of one TLS
    connection, the WebSocket over extended CONNECT (RFC 8441), with
    HTTP/1.1's upgrade where the server does not offer it; PODSSH_H2
    chooses, doctor names the ALPN (T-321, its first part).
  • A cleartext road on port 443, tried after the TLS road fails (T-326).
  • A standard sshd's session across a drop of the client's link: podssh proxy and podssh ssh take the role's road in the resumable layer where
    the first host offers it, its offer kept for a day; PODSSH_RELAY_LAYER=yes
    reads the offer at each run and says each case, no turns the road off;
    --resume-budget, --resume-deadline and --resume-host bound and name
    it (T-173). On that road, the end of podssh proxy's stdin stops sending
    and keeps receiving until the target closes, as on the contract's road; a
    relay host that the user named, whose offer is not kept, costs the session
    one read of 1 s at most, once a day.
  • A connect token for each leg of a session, and a stop token that the node
    rotates (T-615); a pair that its owner renews in the role (T-592).
  • A planned stop that no session feels (T-255); a bound on what waits for a
    slow reader (T-336); the role's dials through the host's HTTPS_PROXY
    (T-457); its mint for the members of the net (T-455); its IPv6 targets,
    and doctor's line ipv6 (T-253).
  • Relay hosts outside the default domain from a list of deployments that a
    trusted key signs (T-346).
  • podssh doctor --stream: what the path does to a stream (T-325).
  • A name that the role does not dial (it does not resolve, or resolves to
    an address that is not public, or has none of the family asked for) gets
    one 403 that names no address; the role's line keeps the cause (T-628,
    GitHub #126).

The net and its nodes:

  • podssh net invite and podssh net join: a new device joins the net by
    a short code (T-616); pairing by a short one-time code given out of band
    (T-086); grants that are signed and used once (T-226, GitHub #35).
  • Routes: a node reaches its private networks for the net, --exit auto
    picks the exit whose routes hold the target, and an exit never dials its
    own addresses (T-432).
  • ssh, proxy and pipe take --exit beside --carrier (T-614,
    GitHub #124), the exit over a carrier (T-596), and podssh doctor --exit NAME (T-458).
  • --no-resume, a session to a node that ends with its link (T-612);
    --timeout and PODSSH_TIMEOUT on operator, proxy and pipe
    (T-613).
  • A copy to a node races the roads that podssh ssh races (T-551); the
    quick tunnel's node takes its net's members as its door (T-550);
    OpenTunnel's road at the node and the client (T-530, T-531).
  • A client's lost link during a node's bulk costs the node's other sessions
    no backoff (T-421).

Relay selection:

  • podssh relay rank measures each relay host from this host and keeps the
    rank (T-606); the default list takes it, with the samples of each race
    (T-607); RelayRank auto ranks in a session's background, at most once a
    day for each egress (T-608, Q89); relay info says that the pool's order
    is the relay's (T-610, GitHub #125), names podssh relay rank, and says
    the order that a run from this host takes (T-618).
  • A relay member of the net names its host, and each end of the net takes
    the role's signed list with no --relay-host (T-617); podssh ping NAME
    races a node's roads and says each one's time, podssh status --net lists
    each member, and doctor has the sections net and carriers (T-435).

Repairs:

  • An ECDSA key of P-256 whose scalar OpenSSH writes in 31 bytes is read
    (T-609); a roost on a host with no sshd says so, and doctor has a line
    for a roost (T-590, GitHub #116); doctor's diagnosis of the TLS
    handshakes counts the resolvers of DNS over HTTPS and n0's relays
    (T-604); on WARP's road, the end of a stream waits for the bytes that the
    far side has not acknowledged yet, so a large echo no longer stalls
    (T-599).
  • podssh pipe -v says, for each direction, when its input ended and how
    the other side took the shutdown (T-465).

The files

File For
podssh-x86_64-unknown-linux-musl Linux on x86-64, static: no library and no loader needed
podssh-aarch64-unknown-linux-musl Linux on aarch64, static
podssh-armv7-unknown-linux-musleabihf Linux on 32-bit ARM with hard float, static
podssh-riscv64gc-unknown-linux-musl Linux on 64-bit RISC-V, static
podssh-aarch64-apple-darwin macOS on Apple silicon; it links the system's libraries only
podssh-x86_64-apple-darwin macOS on Intel
podssh-x86_64-pc-windows-msvc.exe Windows on x86-64, with a static C runtime
podssh-aarch64-pc-windows-msvc.exe Windows on ARM64, with a static C runtime
SHA256SUMS The SHA-256 of each binary
SHA256SUMS.sigstore.json The signature of SHA256SUMS: Sigstore's keyless signing, by the release workflow at this tag
provenance.sigstore.json The provenance of each binary (SLSA), signed the same way: the workflow, the tag and its commit
THIRD-PARTY-LICENSES.md The licenses of the crates in the binaries, with their texts

Check a download

T=v1.1.0-beta.2; B=podssh-x86_64-unknown-linux-musl   # or another file of the table
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/$B"
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/SHA256SUMS"
grep " $B\$" SHA256SUMS | sha256sum -c - && chmod +x "$B"
./"$B" --version   # podssh 1.1.0-beta.2 (the commit of the tag)

podssh update --version v1.1.0-beta.2 from v1.1.0-beta.1 or v1.0.1
takes it, checked by its signature; a build of a release follows releases
alone, so without --version it stays on v1.0.1. The provenance and the
signature are checked as for v1.0.0 (its notes),
with T=v1.1.0-beta.2.

How it was checked

By the operator's ruling Q88 (2026-11-03), until podssh is stable: the gate
green at the tag's commit, the release workflow by hand on it, and the short
form of its binary (scripts/release-short.sh BINARY --net); after the tag,
release-proofs.yml and update-live.yml. The whole release check and the
live runs of each road wait until then.

What a beta does not have yet

  • The whole check of a release from end to end with no human
    (scripts/release-check.sh, T-251): it waits (Q88).
  • Signatures of the platforms: the Mac binaries are not signed with an
    Apple Developer ID, and the Windows binaries carry no Authenticode
    signature, so SmartScreen may warn. The proofs above stand in for them.

Report a defect

Open an issue at https://github.com/Azathothas/podssh/issues with the
output of podssh --version and podssh doctor --json. Read that output
before you post it: it names this host's proxy and addresses, and never a
token or a password.

The licenses of the crates in the binaries, with their texts: THIRD-PARTY-LICENSES.md.

The commits of this release

Other

  • T-561: done, WARP's road tries the record's endpoint, then the API's peers (GitHub #108) (c5299c2)
  • GitHub #108 closed: T-561 done (c5299c2); warp-live.yml dispatched for its live step (365dbd1)
  • T-562: done, WARP's API by its routes in turn (GitHub #109); T-561's live run read and its step repaired (cde307f)
  • T-564: done, podssh raises its soft limit of open files at start, within the hard one (GitHub #111) (5b643b1)
  • T-489: done, chat --listen --linger stays for each peer after its stdin ended (GitHub #102) (ea2a70b)
  • WARP live at cde307f (run 41597035711): T-561's turn proved, T-562's second API name registers a device; GitHub #102, #109 and #111 closed (36d1f31)
  • T-483: done, http-listen: takes ssh:HOPS with no target, and pipe --help shows the proxy of an SSH server (GitHub #93) (7417676)
  • GitHub #93 closed: T-483 done (7417676) (5ff6809)
  • T-488: done, podssh mcp offers cp, job, health and session as tools, behind the gate of ssh_exec (GitHub #101) (f8eaeb4)
  • GitHub #101 closed: T-488 done (f8eaeb4) (9694d0c)
  • Drafts: T-561, T-562, T-564, T-489, T-483 and T-488 merged and closed; their worktrees removed (477b47c)
  • T-599: the stack's driver polls at once for packets in that smoltcp left while the queue out was full (partial: the loop under load runs) (02ece60)
  • T-590: done, a roost that the loopback refuses says whether this host has an sshd, and doctor's line sshd (GitHub #116); the manual's notes repaired; release-proofs reach a beta by --version (279a283)
  • GitHub #116 closed: T-590 done (279a283) (0d0c22c)
  • T-474: done, cp copies s...
Read more

podssh v1.1.0-beta.1

podssh v1.1.0-beta.1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 03 Nov 08:31

podssh v1.1.0-beta.1

The first beta of milestone M10: v1.0.1 and the repairs of the defects that
its testers filed after it (GitHub #112, #114 and #118). A beta is a
prerelease. Its tag never moves: a defect found in it goes into the next beta.

What to test again

  • Short logins through a node, with OpenSSH's ProxyCommand=podssh operator:
    operator, pipe with a node: side and ssh node:// take SIGHUP and
    SIGTERM (and SIGINT, but for ssh) as the end of their bytes and close the
    node's session, so a run of logins no longer fills the node's budget. The
    refusal of a full budget says what holds it (T-586, #112).
  • ssh node:// from a Windows client: the question of a new host key no
    longer counts against ConnectTimeout and has its bound on the console, and a
    handshake that does not finish says what came, the bytes through the layer
    and the channel among them; 10 s in, a line says where it is (T-588, #114).
  • A node or a client run as root with HOME of another account: the cache
    passes over a place in another user's tree, takes the home of the uid's
    entry in the user database, and reads what it kept there before without
    moving it; podssh status gives cache.passed (T-593, #118).

The files

File For
podssh-x86_64-unknown-linux-musl Linux on x86-64, static: no library and no loader needed
podssh-aarch64-unknown-linux-musl Linux on aarch64, static
podssh-armv7-unknown-linux-musleabihf Linux on 32-bit ARM with hard float, static
podssh-riscv64gc-unknown-linux-musl Linux on 64-bit RISC-V, static
podssh-aarch64-apple-darwin macOS on Apple silicon; it links the system's libraries only
podssh-x86_64-apple-darwin macOS on Intel
podssh-x86_64-pc-windows-msvc.exe Windows on x86-64, with a static C runtime
podssh-aarch64-pc-windows-msvc.exe Windows on ARM64, with a static C runtime
SHA256SUMS The SHA-256 of each binary
SHA256SUMS.sigstore.json The signature of SHA256SUMS: Sigstore's keyless signing, by the release workflow at this tag
provenance.sigstore.json The provenance of each binary (SLSA), signed the same way: the workflow, the tag and its commit
THIRD-PARTY-LICENSES.md The licenses of the crates in the binaries, with their texts

Check a download

T=v1.1.0-beta.1; B=podssh-x86_64-unknown-linux-musl   # or another file of the table
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/$B"
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/SHA256SUMS"
grep " $B\$" SHA256SUMS | sha256sum -c - && chmod +x "$B"
./"$B" --version   # podssh 1.1.0-beta.1 (the commit of the tag)

podssh update --version v1.1.0-beta.1 from v1.0.1 takes it, checked by
its signature; a build of a release follows releases alone, so without
--version it stays on v1.0.1. The provenance and the signature are checked
as for v1.0.0 (its notes),
with T=v1.1.0-beta.1.

How it was checked

By the operator's ruling Q88 (2026-11-03), until podssh is stable: the gate
green at the tag's commit, the release workflow by hand on it, and the short
form of its binary (scripts/release-short.sh BINARY --net); after the tag,
release-proofs.yml and update-live.yml. The whole release check of
v1.0.1 and the live runs of each road wait until then.

What a beta does not have yet

  • The whole check of a release from end to end with no human
    (scripts/release-check.sh, T-251): it waits (Q88).
  • Signatures of the platforms: the Mac binaries are not signed with an
    Apple Developer ID, and the Windows binaries carry no Authenticode
    signature, so SmartScreen may warn. The proofs above stand in for them.

Report a defect

Open an issue at https://github.com/Azathothas/podssh/issues with the
output of podssh --version and podssh doctor --json. Read that output
before you post it: it names this host's proxy and addresses, and never a
token or a password.

The licenses of the crates in the binaries, with their texts: THIRD-PARTY-LICENSES.md.

The commits of this release

Other

  • T-584: step 2, v1.0.1's release check before the tag passed at 6ece1f9 (43 passed, 6 skipped), each of its 21 runs green (62d26dc)
  • Q88: move fast, the expensive checks wait until podssh is stable; T-584: done, v1.0.1 published at 6ece1f9 (bd3b9e0)
  • Record: the citations of docs/STATUS.md moved with its intro's lines on v1.0.1 (cargo todo remap) (b5a0709)
  • T-586: done, a signal ends operator, pipe node: and ssh node:// with a CLOSE, and a node charges a closing session its unacknowledged bytes (GitHub #112) (84864f2)
  • T-588: done, a handshake that does not finish names what came, and the question of a new host key leaves ConnectTimeout and has its bound on Windows (GitHub #114) (ef50f8b)
  • T-593: done, the cache passes over a place in another user's tree, takes the passwd home's, and only reads what was kept there (GitHub #118) (2f87d7b)
  • Repair CI: the layer's session future on the heap (exit's stack overflow, T-586); roost's SIGHUP test Unix's alone; T-599 filed (bfd8f7d)
  • v1.1.0-beta.1 made ready (T-446): the version 1.1.0-beta.1 and the notes (5d95e5f)

podssh v1.0.1

Choose a tag to compare

@github-actions github-actions released this 03 Nov 05:45

podssh v1.0.1

The repairs of the defects that the testers of v1.0.0 found (GitHub #83 to
#111, and the report of the operator's testing agents of 2026-11-02), with the
work of milestone M10 that main holds since v1.0.0: podssh's own relay
role, the net of an owner's nodes, and more roads. Its tag never moves: a
defect found in it goes into the next release.

The repairs

  • SSH to a server of Go's x/crypto/ssh: a reply to a keepalive or to -R
    that carries data no longer ends the connection (T-460, #83, #85).
  • podssh ssh exits 255, not the far command's status, when the link ends
    after the status and before the output's end (T-461, #84).
  • A -J hop whose channel opens and carries nothing is named, within
    ConnectTimeout (T-462, #86).
  • A connection that ends right after the login is no longer read as a
    refused session; a refusal gives OpenSSH's words of its reason (T-464,
    #104).
  • sftp's ls gives OpenSSH's long form, and its switches act (T-471, #89).
  • cp --delta says why it sends a whole file, and makes the temporary file
    by one command where the server has no copy-data (T-470, #87).
  • cp -r says each failure once, and a device, FIFO or socket is a skip with
    exit 0, not 66 (T-476, #105).
  • health gives a container's CPUs and memory from its cgroup beside the
    host's (T-480, #88).
  • The login name comes from the user database when USER, LOGNAME and
    USERNAME are unset (T-500).
  • --su ends su's read when its password cannot be given (T-501).
  • -o ProxyCommand=none goes past a file's ProxyCommand, and the first
    value of a file holds (T-502).
  • Each host that is dialed, -J's hops among them, is checked before
    anything connects, on each road (T-503).
  • each refuses a blank that would part two hosts of the command line (T-504).
  • The keywords of a restriction (Ciphers, MACs, KexAlgorithms,
    HostKeyAlgorithms, PubkeyAcceptedAlgorithms, CASignatureAlgorithms,
    RequiredRSASize) apply (T-505).
  • session list and detached list say on stderr that none is there, and
    take --json (T-506).
  • update names the move of the kept file as the way back, and --rollback
    only for a release that has it (T-507).
  • The fallback to other products' forwarders follows only a failure where no
    relay host answered about the target (T-509, #106).
  • The relay's record keeps a host that opens, rests one cut short twice, and
    keeps each road apart (T-563, #110).
  • WARP's road proves a packet through its tunnel before it is open (T-560,
    #107).
  • A warning before the relay's idle cut, and --idle-warn SECONDS (T-463,
    #98).

The files

File For
podssh-x86_64-unknown-linux-musl Linux on x86-64, static: no library and no loader needed
podssh-aarch64-unknown-linux-musl Linux on aarch64, static
podssh-armv7-unknown-linux-musleabihf Linux on 32-bit ARM with hard float, static
podssh-riscv64gc-unknown-linux-musl Linux on 64-bit RISC-V, static
podssh-aarch64-apple-darwin macOS on Apple silicon; it links the system's libraries only
podssh-x86_64-apple-darwin macOS on Intel
podssh-x86_64-pc-windows-msvc.exe Windows on x86-64, with a static C runtime
podssh-aarch64-pc-windows-msvc.exe Windows on ARM64, with a static C runtime
SHA256SUMS The SHA-256 of each binary
SHA256SUMS.sigstore.json The signature of SHA256SUMS: Sigstore's keyless signing, by the release workflow at this tag
provenance.sigstore.json The provenance of each binary (SLSA), signed the same way: the workflow, the tag and its commit
THIRD-PARTY-LICENSES.md The licenses of the crates in the binaries, with their texts

Check a download

T=v1.0.1; B=podssh-x86_64-unknown-linux-musl   # or another file of the table
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/$B"
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/SHA256SUMS"
grep " $B\$" SHA256SUMS | sha256sum -c - && chmod +x "$B"
./"$B" --version   # podssh 1.0.1 (the commit of the tag)

podssh update from v1.0.0 takes it, checked by its signature. The
provenance and the signature are checked as for v1.0.0
(its notes),
with T=v1.0.1.

The sizes

The sizes of the release's dry run of 2026-11-03 (at 3bb42ea, the code of this tag: the commits
after it change tests and the record alone, run 41563962586), beside v1.0.0's published files.
They grew with the work of M10 that main holds: podssh's relay role, the net of nodes, and the
new roads.

Binary v1.0.0 v1.0.1
Linux x86-64 15.7 MiB 17.2 MiB
Linux aarch64 12.1 MiB 13.2 MiB
Linux armv7 9.1 MiB 10.0 MiB
Linux riscv64 12.1 MiB 13.3 MiB
macOS, Apple silicon 9.5 MiB 10.4 MiB
macOS, Intel 12.6 MiB 13.9 MiB
Windows x86-64 12.3 MiB 13.6 MiB
Windows ARM64 10.8 MiB 11.9 MiB

How it was checked

As v1.0.0: the release check of T-251 (scripts/release-check.sh) ran before the tag on the
release's dry run and a build of its own, and runs again on the published files, the checksums,
the signature of SHA256SUMS and the provenance of each binary first; then the README's first
steps, doctor, proxy and ssh through the live relay, the reverse road with two sessions at
once, cp of 200 MiB each way through a node, pipe, the iroh road through n0's relays, the
static binary in a fresh container and in a box like the target sandbox, the Tailscale runs
against headscale, the throughput run, IRC against ngircd, and the planted defect of each check.
GitHub's runners ran the rest: Windows and macOS, the box, WARP's road, Cloudflare's edge, the
public forwarders, DNS over HTTPS, a node as a unit of systemd, podssh update, 200 MiB each way
through a node with its moves, and the servers of the repairs: Go's x/crypto/ssh, wstunnel, the
via forwarders, and containers of cgroup limits for health. docs/STATUS.md, "The release
check", holds the table of each run.

What is not in it

As in v1.0.0: the entries that wait for the relay's operator, the work that
the operator holds (Q32), the imports of T-328, the live runs of T-376, the
outside services that turn the relay's address away, the platforms'
signatures, and Tailscale and the Tor road, which need their features.

Report a defect

Open an issue at https://github.com/Azathothas/podssh/issues with the
output of podssh --version and podssh doctor --json. Read that output
before you post it: it names this host's proxy and addresses, and never a
token or a password.

The licenses of the crates in the binaries, with their texts: THIRD-PARTY-LICENSES.md.

The commits of this release

Build and CI

  • CI: the gate red since 0b6fcdb: the net tests remove their scratch directories; the DERP stand-in registers a client before its answer (a2c418e)
  • CI: the gate red at b76548c: the keyed mint's unit tests remove their scratch directories (60b3070)
  • CI: allow the draft of T-460's russh test keys; exit-live meets GitHub's key with no global file (94be1bb)

Other

  • T-251: done, the whole release check before the tag of v1.0.0 passed at 35a0d19 (80a6407)
  • Q63 to Q66: milestone M10, the mesh at parity with Tailscale and the relay as a role of podssh; v1.0.0 tagged (6b6174f)
  • M10: the Corrections of the 15 entries that waited for the relay's operator; relay-operator.md and carriers.md for Q63 to Q65 (d8cc0d6)
  • T-169: podssh relay serve, the relay's forward road served by podssh itself (partial: the live run on a runner closes it); T-447, T-448 filed (00197d5)
  • T-169: the citations of the files that its commit changed, moved against its parent (cargo todo remap --base HEAD~1) (2d847e8)
  • T-443, T-444: the layer's window on the pair's road under the relay's bound; one TLS configuration for each trust, so that TLS resumes; T-449 filed; the relay role's Date header (bd4c576)
  • T-439 (partial): --via, HTTP CONNECT to a second proxy over TLS, HTTP/1.1 and HTTP/2; the run against Caddy and squid follows in Actions (a253c8a)
  • T-169: done, its live run on a runner passed; tls_resume removes its scratch directories (the gate's libs step at bd4c576) (8899450)
  • T-436: the magic-wormhole transit relay as a carrier of a pair's road (Q65); T-450 filed (84eb45e)
  • T-439 (partial): via-interop's first run failed on its script: Caddy is built as xcaddy builds it, each proxy must answer TLS, banners keep stdin open (5b62f4e)
  • T-439: done, via-interop.yml passed against Caddy and squid (12 of 12) (95563f1)
  • T-437: the Piping Server road (Q65) for a proxy that refuses the WebSocket upgrade; T-451 filed (b4817cb)
  • T-438: Wisp: the protocol's client, wisp+wss:// forwarders, and the demo server as a fallback (Q65) (f22efab)
  • T-429: the net: an owner's signed list of its nodes, and their names; T-452 and T-453 filed (0b6fcdb)
  • record: a citation of AGENTS.md's sentence of exit code 70 follows its two new lines (fd4cbbe)
  • T-427: the relay's reverse road in podssh's relay role; the transit relay takes the host's trust; T-454 filed (d5a700b)
  • T-448: the relay role mints tokens, and makes pairs, for the keys of a list; T-455 filed (b76548c)
  • T-440 (partial): VLESS over a WebSocket and over XHTTP on HTTP/2, in place of the relay; Q67 and T-456 filed (33ccb11)
  • T-441 (partial): wstunnel's protocol, --wstunnel URL in place of the relay, its secret in a 0600 file (e077220)
  • T-440 (partial): its interop's first run: Xray-core blackholes a private target unless a final rule allows it (28cba8a)
  • T-449 (partial): suite-repeat.yml, a suite run after run on a runner, each failure counted by its test's name (aca3a35)
  • T-430: the net's policy: who may reach which node, route, exit and range, checked at the node (f85ced1)
  • T-440 and T-441: done, each interop passed against its servers' own projects (f8d15b...
Read more

podssh v1.0.0

Choose a tag to compare

@github-actions github-actions released this 02 Nov 02:07

podssh v1.0.0

The first stable release. podssh carries SSH, or another TCP stream, through
a WebSocket relay on port 443, for a host whose only way out is HTTPS, often
through an HTTP CONNECT proxy: one binary for each platform (static on
Linux), which starts no helper program and uses no capability of the host
that it did not probe for first.
It is v1.0.0-beta.4 with this version and one repair: podssh update of a
build of a release, while the list holds prereleases alone, says that there
is nothing to do (exit 0), where it said that it found no list (T-426).
Its tag never moves: a defect found in it goes into v1.0.1.

The files

File For
podssh-x86_64-unknown-linux-musl Linux on x86-64, static: no library and no loader needed
podssh-aarch64-unknown-linux-musl Linux on aarch64, static
podssh-armv7-unknown-linux-musleabihf Linux on 32-bit ARM with hard float (a Raspberry Pi with a 32-bit system), static
podssh-riscv64gc-unknown-linux-musl Linux on 64-bit RISC-V, static
podssh-aarch64-apple-darwin macOS on Apple silicon; it links the system's libraries only
podssh-x86_64-apple-darwin macOS on Intel
podssh-x86_64-pc-windows-msvc.exe Windows on x86-64, with a static C runtime
podssh-aarch64-pc-windows-msvc.exe Windows on ARM64, with a static C runtime
SHA256SUMS The SHA-256 of each binary
SHA256SUMS.sigstore.json The signature of SHA256SUMS: Sigstore's keyless signing, by the release workflow at this tag
provenance.sigstore.json The provenance of each binary (SLSA), signed the same way: the workflow, the tag and its commit
THIRD-PARTY-LICENSES.md The licenses of the crates in the binaries, with their texts

Each binary ran on its own platform before it was published: --version,
the whole manual, keygen and keygen -y, the iroh road's parse of a
ticket, WARP's road asking for Cloudflare's Terms before it dials, and
GitHub's SSH banner through the live relay.

Check a download

T=v1.0.0; B=podssh-x86_64-unknown-linux-musl   # or another file of the table
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/$B"
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/SHA256SUMS"
grep " $B\$" SHA256SUMS | sha256sum -c - && chmod +x "$B"
./"$B" --version   # podssh 1.0.0 (the commit of the tag)
./"$B" doctor      # what this host allows, and whether the whole path works

On macOS, check with shasum -a 256 -c in place of sha256sum -c -. A
binary that curl fetched has no quarantine; after a browser's download,
run xattr -d com.apple.quarantine "$B" first. On Windows, compare
(Get-FileHash podssh-x86_64-pc-windows-msvc.exe).Hash with its line in
SHA256SUMS (the case of the letters differs).

The provenance of a binary names the release workflow and the tag (with the
GitHub CLI):

gh attestation verify "$B" --repo Azathothas/podssh \
  --signer-workflow Azathothas/podssh/.github/workflows/release.yml --source-ref "refs/tags/$T"

The signature of SHA256SUMS names the workflow at the tag (with cosign; 3.x
and 2.6 both check it):

curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/SHA256SUMS.sigstore.json"
cosign verify-blob --bundle SHA256SUMS.sigstore.json \
  --certificate-identity "https://github.com/Azathothas/podssh/.github/workflows/release.yml@refs/tags/$T" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com SHA256SUMS

The two proofs and podssh --version name the same commit.

The sizes

The sizes of the release's dry run of 2026-11-01 (at e3f90ca, the code of
this tag but for the repair of update, run 41350666813), beside beta.3's:

Binary beta.3 v1.0.0
Linux x86-64 15.2 MiB 15.7 MiB
Linux aarch64 11.7 MiB 12.1 MiB
Linux armv7 8.8 MiB 9.1 MiB
Linux riscv64 11.7 MiB 12.1 MiB
macOS, Apple silicon 9.2 MiB 9.5 MiB
macOS, Intel 12.2 MiB 12.6 MiB
Windows x86-64 11.9 MiB 12.3 MiB
Windows ARM64 10.5 MiB 10.8 MiB

What works

podssh ssh, each, run, job, session, containers, proxy, pipe,
cp, mv, scp, sftp and edit, doctor, keygen, agent, man,
status, ping, health, node, operator, relay, chat, play,
config, mcp, update and detached. podssh man is the reference: each command,
flag, -o keyword, variable, file and exit code. The iroh road is in each
binary: podssh node --iroh, a destination iroh:TICKET, and
--iroh-ticket. So is WARP's road, warp://HOST[:PORT], and the DERP road,
podssh node --derp and a destination derp:TICKET. These binaries have no
Tailscale: podssh ts exits with 70 and says so.

How it was checked

The release check of T-251 (scripts/release-check.sh) ran before the tag on
the release's dry run and a build of its own, and runs again on the
published files: the checksums, the signature of SHA256SUMS and the provenance of each
binary first; then the README's first steps, doctor, proxy and ssh
through the live relay, the reverse road with two sessions at once, cp of
200 MiB each way through a node, pipe, the iroh road through n0's relays,
the static binary in a fresh container and in a box like the target sandbox,
the Tailscale runs against headscale, the throughput run, IRC against
ngircd, and the planted defect of each check. GitHub's runners ran the rest:
Windows and macOS, the box, WARP's road, Cloudflare's edge, the public
forwarders, DNS over HTTPS, a node as a unit of systemd, podssh update,
and 200 MiB each way through a node with its moves. docs/STATUS.md, "The
release check", holds the table of each run.

What is not in it

  • The entries that wait for the relay's operator, each an item of
    docs/relay-operator.md:
    a relay that its users host, a signed list of relays and a second
    deployment, resumption in the relay for a standard sshd, a local HTTP
    service at https://NAME, and the relay's tolerance of a frame on its way
    when a client's link is lost (T-421), among them.
  • The work that the operator holds (Q32): podssh serve with a terminal of
    its own (vi, less and Ctrl-C in a box), two sessions from one box to a
    node in another, and the work parked behind them.
  • The import of FinalShell's and Termius's exports (T-328) and the live run
    of the roads iap:// and eice:// in throwaway cloud accounts (T-376),
    which wait for the operator.
  • Outside services that turn the relay's address away: railway.new's limit
    for anonymous visitors, and the IRC networks libera, undernet and, at
    times, OFTC (docs/irc.md).
  • Signatures of the platforms: the Mac binaries are not signed with an
    Apple Developer ID, and the Windows binaries carry no Authenticode
    signature, so SmartScreen may warn. The proofs above stand in for them.
  • Tailscale (podssh ts), the Tor road (tor://) and their features are
    not in these binaries: a build with --features ts or --features tor
    has them.

Report a defect

Open an issue at https://github.com/Azathothas/podssh/issues with the
output of podssh --version and podssh doctor --json. Read that output
before you post it: it names this host's proxy and addresses, and never a
token or a password.

The licenses of the crates in the binaries, with their texts: THIRD-PARTY-LICENSES.md.

The commits of this release

Other

  • T-425 (partial): irc.live skips when each network turned the relay's address away in its own words; T-251: the runs before beta.4's tag (e3db9db)
  • T-425: done, irc.live skips on the networks' own refusal and fails without it (planted: a closed port, FAIL); the work order names 4e79a1f for beta.4 (9c73e32)
  • v1.0.0 made ready (the steps of T-250): the version 1.0.0, the README's install lines, and the notes (e3f90ca)
  • T-426: podssh update of a build of a release with prereleases alone listed is nothing to do; T-425: a stalled TLS handshake counts as a network's refusal; ts-headscale.sh takes its build from CARGO_TA… (35a0d19)

podssh v1.0.0-beta.4

podssh v1.0.0-beta.4 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 02 Nov 01:59

podssh v1.0.0-beta.4

The fourth beta. It carries the repairs since v1.0.0-beta.3: a run in the
background that podssh starts again and watches, and that leaves a login
session's scope of systemd, a node that goes on past its pair's expiry, a
quick tunnel that races its roads, keeps two connections and rides out the
edge's GOAWAY, and the repairs of a bulk session through a node. A beta is a prerelease. Its tag never moves: a defect found in it
goes into the next beta.

The files

File For
podssh-x86_64-unknown-linux-musl Linux on x86-64, static: no library and no loader needed
podssh-aarch64-unknown-linux-musl Linux on aarch64, static
podssh-armv7-unknown-linux-musleabihf Linux on 32-bit ARM with hard float (a Raspberry Pi with a 32-bit system), static
podssh-riscv64gc-unknown-linux-musl Linux on 64-bit RISC-V, static
podssh-aarch64-apple-darwin macOS on Apple silicon; it links the system's libraries only
podssh-x86_64-apple-darwin macOS on Intel
podssh-x86_64-pc-windows-msvc.exe Windows on x86-64, with a static C runtime
podssh-aarch64-pc-windows-msvc.exe Windows on ARM64, with a static C runtime
SHA256SUMS The SHA-256 of each binary
SHA256SUMS.sigstore.json The signature of SHA256SUMS: Sigstore's keyless signing, by the release workflow at this tag
provenance.sigstore.json The provenance of each binary (SLSA), signed the same way: the workflow, the tag and its commit
THIRD-PARTY-LICENSES.md The licenses of the crates in the binaries, with their texts

Each binary ran on its own platform before it was published: --version,
the whole manual, keygen and keygen -y, the iroh road's parse of a
ticket, WARP's road asking for Cloudflare's Terms before it dials, and
GitHub's SSH banner through the live relay.

Check a download

T=v1.0.0-beta.4; B=podssh-x86_64-unknown-linux-musl   # or another file of the table
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/$B"
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/SHA256SUMS"
grep " $B\$" SHA256SUMS | sha256sum -c - && chmod +x "$B"
./"$B" --version   # podssh 1.0.0-beta.4 (the commit of the tag)
./"$B" doctor      # what this host allows, and whether the whole path works

On macOS, check with shasum -a 256 -c in place of sha256sum -c -. A
binary that curl fetched has no quarantine; after a browser's download,
run xattr -d com.apple.quarantine "$B" first. On Windows, compare
(Get-FileHash podssh-x86_64-pc-windows-msvc.exe).Hash with its line in
SHA256SUMS (the case of the letters differs).

The provenance of a binary names the release workflow and the tag (with the
GitHub CLI):

gh attestation verify "$B" --repo Azathothas/podssh \
  --signer-workflow Azathothas/podssh/.github/workflows/release.yml --source-ref "refs/tags/$T"

The signature of SHA256SUMS names the workflow at the tag (with cosign; 3.x
and 2.6 both check it):

curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/SHA256SUMS.sigstore.json"
cosign verify-blob --bundle SHA256SUMS.sigstore.json \
  --certificate-identity "https://github.com/Azathothas/podssh/.github/workflows/release.yml@refs/tags/$T" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com SHA256SUMS

The two proofs and podssh --version name the same commit.

The sizes

The sizes of the release's dry run of 2026-11-01 (at 1bafa9d, the code of
this tag, run 41337605530), beside beta.3's:

Binary beta.3 beta.4
Linux x86-64 15.2 MiB 15.7 MiB
Linux aarch64 11.7 MiB 12.1 MiB
Linux armv7 8.8 MiB 9.1 MiB
Linux riscv64 11.7 MiB 12.1 MiB
macOS, Apple silicon 9.2 MiB 9.5 MiB
macOS, Intel 12.2 MiB 12.6 MiB
Windows x86-64 11.9 MiB 12.3 MiB
Windows ARM64 10.5 MiB 10.8 MiB

What works

podssh ssh, each, run, job, session, containers, proxy, pipe,
cp, mv, scp, sftp and edit, doctor, keygen, agent, man,
status, ping, health, node, operator, relay, chat, play,
config, mcp, update and detached. podssh man is the reference: each command,
flag, -o keyword, variable, file and exit code. The iroh road is in each
binary: podssh node --iroh, a destination iroh:TICKET, and
--iroh-ticket. So is WARP's road, warp://HOST[:PORT], and the DERP road,
podssh node --derp and a destination derp:TICKET. These binaries have no
Tailscale: podssh ts exits with 70 and says so.

What to test again

New since v1.0.0-beta.3:

  • --detach (-f for ssh): a run that podssh sends into the background
    itself, once it is online, with its log in the cache (T-380); with
    --restart, a small supervisor starts it again whenever it ends, never
    giving up, and starts it again when it hangs: each run beats a file each
    10 s, and one silent for 90 s is ended and started again (T-390, T-394).
    --detach-name NAME and podssh detached list, status NAME and stop NAME: a second start of a name that runs is refused (T-392). A run with no
    /dev/null uses closed pipes, the log is cut with no line lost, old files
    go, and the run leaves the caller's working directory (T-397). A line that
    fails to write (a full disk, a closed journal) no longer ends a run (T-389).
    On Linux, a run detached from a login session asks the user's systemd for
    a scope of its own, podssh-detached-PID.scope, as tmux does, so that a
    logout does not end it where logind ends a session's processes; its log
    says the outcome, and PODSSH_SYSTEMD=no asks nothing (T-381).
  • podssh ssh --persist-forever: connect again after each loss with no limit
    (T-391); podssh ssh --install NAME -N -R ... --persist: a reverse tunnel as
    a service of this user (T-393). --install services restart after each end,
    with a cron watchdog, a LaunchAgent on macOS and a task on Windows (T-393).
  • podssh update runs the new binary once before it takes the old one's
    place, keeps the old one as podssh.prev, and --rollback puts it back
    (T-396).
  • A node says its pair's expiry 24 h, 6 h and 1 h before it, with the command
    that makes the next pair; podssh relay pair NAME makes it in the last day
    of the old one, and the node takes it at the expiry with no new start;
    podssh status names each stored pair's expiry (T-395). A node closed by
    the relay for a fault connects again (T-409), and a bulk session through a
    node moves with no fault (T-410). A node that starts while the relay still
    holds the socket of the pair's last node (a restart, a script that starts
    the next one at once) connects again for 30 s instead of exiting at the
    relay's 409 (T-416).
  • The quick tunnel (podssh node --quick-tunnel): its roads (QUIC, HTTP/2,
    HTTP/2 inside WARP) race with a stagger of 2 s, QUIC after a probe of UDP of
    300 ms (T-400); on the edge's GOAWAY its visitors go on for up to 90 s while
    a new connection takes the new ones (T-402); a window of small frames left
    unread no longer ends the connection (T-408); a push of configuration is
    answered over HTTP/2 and QUIC (T-404, T-411); a refusal of
    api.trycloudflare.com for now is asked again after its Retry-After (T-401).
    The node keeps two connections to the edge, the second to its other region,
    so that a region in trouble leaves one standing (T-414).
  • WARP's tunnel under volume (T-398), and a front door's new key read from the
    device's record (T-399); a front door that shows another certificate once
    is asked once more a second later before the road gives up (T-419).
  • pipe and proxy write what their source has ready together, up to
    32 KiB, so that a source of small reads no longer pays a write for each.
    Through Tor (a build with the feature tor) that took the download from
    2.9 to 7.8 MiB/s through a private network; the Tor road also runs on two
    threads, and it is measured on Tor's public network (T-353).
  • DNS over HTTPS through a proxy asks each resolver by its name first (T-405),
    and over HTTP/2 it ends each connection with GOAWAY (T-418).
  • ssh+tls://, SSH inside TLS as a hop or the destination (#61, T-372); a
    Shadowsocks road from a file of ss:// lines that a subscription can
    refresh (#62, T-373); meek and WebTunnel inside the Tor road's process, in a
    build with the feature tor (T-385).
  • cp of many small files: the far digest's command starts beside each
    file's sync and close, and a tree of 50 files or more that go one at a
    time says once that --parallel 8 copies 8 at once (T-417).

What a beta does not have yet

  • The whole check of a release from end to end with no human
    (scripts/release-check.sh, T-251): its parts ran on this beta's way; the
    whole run, before the tag and after it, is v1.0.0's.
  • Signatures of the platforms: the Mac binaries are not signed with an
    Apple Developer ID, and the Windows binaries carry no Authenticode
    signature, so SmartScreen may warn. The proofs above stand in for them.

Report a defect

Open an issue at https://github.com/Azathothas/podssh/issues with the
output of podssh --version and podssh doctor --json. Read that output
before you post it: it names this host's proxy and addresses, and never a
token or a password.

The licenses of the crates in the binaries, with their texts: THIRD-PARTY-LICENSES.md.

The commits of this release

Build and CI

  • CI: the Windows test of --restart gives --keep-listening; T-410's live move from GitHub's network (e837c63)

Other

Read more

podssh v1.0.0-beta.3

podssh v1.0.0-beta.3 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 01 Nov 01:44

podssh v1.0.0-beta.3

The third beta. It carries the repairs since v1.0.0-beta.2, the iroh road
and WARP's road in each binary, the DERP road, and podssh update, which
replaces the binary with a signed release. A beta is a prerelease. Its tag never moves: a defect found in it
goes into the next beta.

The files

File For
podssh-x86_64-unknown-linux-musl Linux on x86-64, static: no library and no loader needed
podssh-aarch64-unknown-linux-musl Linux on aarch64, static
podssh-armv7-unknown-linux-musleabihf Linux on 32-bit ARM with hard float (a Raspberry Pi with a 32-bit system), static
podssh-riscv64gc-unknown-linux-musl Linux on 64-bit RISC-V, static
podssh-aarch64-apple-darwin macOS on Apple silicon; it links the system's libraries only
podssh-x86_64-apple-darwin macOS on Intel
podssh-x86_64-pc-windows-msvc.exe Windows on x86-64, with a static C runtime
podssh-aarch64-pc-windows-msvc.exe Windows on ARM64, with a static C runtime
SHA256SUMS The SHA-256 of each binary
SHA256SUMS.sigstore.json The signature of SHA256SUMS: Sigstore's keyless signing, by the release workflow at this tag
provenance.sigstore.json The provenance of each binary (SLSA), signed the same way: the workflow, the tag and its commit
THIRD-PARTY-LICENSES.md The licenses of the crates in the binaries, with their texts

Each binary ran on its own platform before it was published: --version,
the whole manual, keygen and keygen -y, the iroh road's parse of a
ticket, WARP's road asking for Cloudflare's Terms before it dials, and
GitHub's SSH banner through the live relay.

Check a download

T=v1.0.0-beta.3; B=podssh-x86_64-unknown-linux-musl   # or another file of the table
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/$B"
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/SHA256SUMS"
grep " $B\$" SHA256SUMS | sha256sum -c - && chmod +x "$B"
./"$B" --version   # podssh 1.0.0-beta.3 (the commit of the tag)
./"$B" doctor      # what this host allows, and whether the whole path works

On macOS, check with shasum -a 256 -c in place of sha256sum -c -. A
binary that curl fetched has no quarantine; after a browser's download,
run xattr -d com.apple.quarantine "$B" first. On Windows, compare
(Get-FileHash podssh-x86_64-pc-windows-msvc.exe).Hash with its line in
SHA256SUMS (the case of the letters differs).

The provenance of a binary names the release workflow and the tag (with the
GitHub CLI):

gh attestation verify "$B" --repo Azathothas/podssh \
  --signer-workflow Azathothas/podssh/.github/workflows/release.yml --source-ref "refs/tags/$T"

The signature of SHA256SUMS names the workflow at the tag (with cosign; 3.x
and 2.6 both check it):

curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/SHA256SUMS.sigstore.json"
cosign verify-blob --bundle SHA256SUMS.sigstore.json \
  --certificate-identity "https://github.com/Azathothas/podssh/.github/workflows/release.yml@refs/tags/$T" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com SHA256SUMS

The two proofs and podssh --version name the same commit.

The sizes

Each binary carries the iroh road (T-348), WARP's road (T-352) and the DERP
road (T-379) now, and podssh update (T-375).
The sizes of the release's dry run of 2026-11-01 (at 5e42bd4), beside
beta.2's:

Binary beta.2 beta.3
Linux x86-64 9.6 MiB 15.2 MiB
Linux aarch64 7.5 MiB 11.7 MiB
Linux armv7 5.6 MiB 8.8 MiB
Linux riscv64 7.2 MiB 11.7 MiB
macOS, Apple silicon 6.2 MiB 9.2 MiB
macOS, Intel 8.1 MiB 12.2 MiB
Windows x86-64 7.9 MiB 11.9 MiB
Windows ARM64 6.9 MiB 10.5 MiB

What works

podssh ssh, each, run, job, session, containers, proxy, pipe,
cp, mv, scp, sftp and edit, doctor, keygen, agent, man,
status, ping, health, node, operator, relay, chat, play,
config, mcp and update. podssh man is the reference: each command,
flag, -o keyword, variable, file and exit code. The iroh road is in each
binary: podssh node --iroh, a destination iroh:TICKET, and
--iroh-ticket. So is WARP's road, warp://HOST[:PORT], and the DERP road,
podssh node --derp and a destination derp:TICKET. These binaries have no
Tailscale: podssh ts exits with 70 and says so.

What to test again

New since v1.0.0-beta.2:

  • podssh update: the newest release for this binary's own target. Its
    SHA256SUMS is checked against Sigstore's signature by this repository's
    release workflow at the tag, then the binary's own sum, before the binary
    is replaced in place. --check only looks; --version TAG takes a given
    release (T-375).
  • The iroh road in each binary, and a notice when a relay refuses this
    binary's iroh, which names podssh update and --iroh-relay (T-348). The
    road keeps UDP only once a datagram came back, so a host that drops UDP
    goes through the relay at once (#70, T-359).
  • warp://HOST[:PORT] with ssh, -J and proxy: a port of any host
    inside Cloudflare WARP's tunnel, MASQUE over HTTP/2 on port 443 through
    the proxy, with no relay. The first run registers one device, only once
    PODSSH_WARP_ACCEPT_TERMS=yes accepts Cloudflare's Terms, and keeps its
    record in the cache. A proxy that allows names alone refuses the
    endpoint's address, and podssh says so (#63, T-352).
  • podssh node --quick-tunnel reaches the quick tunnel's edge inside WARP's
    tunnel when port 7844 is closed to the host, or first with --warp
    (T-374).
  • The DERP road: podssh node --derp serves a node through Tailscale's
    public DERP servers (or those of --derp-server), and podssh ssh derp:TICKET reaches it. A node with an allowlist and no pair serves it
    unasked; PODSSH_DERP=no turns that off. node://NAME --derp-ticket
    adds it to the race of a node's roads, and podssh doctor has a section
    derp (T-379).
  • When no relay host opens a session and no relay was named, podssh ssh
    and the commands that reach a server as it does try the direct road once,
    through the proxy, and say so; PODSSH_DIRECT=no turns that off (T-363).
  • --forwarder TEMPLATES: other products' WebSocket forwarders in place of
    the relay, such as Mudlet's or ssheasy's, for ssh, proxy and the
    commands of ssh's road; PODSSH_FORWARDER and the settings file's
    Forwarder give them too, and podssh doctor --forwarder checks them
    (#59, T-369).
  • -J USER@HOST:443 through a proxy that allows port 443 alone, with the
    hop's password from SSH_ASKPASS, and podssh doctor --hop, which says
    whether a hop answers with SSH there (#61, T-371).
  • The iroh road keeps a signed record of its node's home relay at n0's
    pkarr server, so a client whose ticket names an old relay finds the node;
    PODSSH_IROH_PKARR=off turns it off (T-350).
  • podssh pipe http-listen:PORT relay:%h:%p: an HTTP CONNECT proxy for a
    program that knows only HTTPS_PROXY, with --proxy-auth-file for an
    address off loopback (#75, T-367).
  • podssh pipe with ws://, wss:// and ws-listen:: a WebSocket by its
    URL, and a WebSocket server in front of a port (#76, T-368).
  • podssh ssh iap:// and eice://: the tunnels of Google Cloud's IAP and of
    AWS's EC2 Instance Connect Endpoint. Their tokens and credentials come
    from files, never from the command line (T-351). They were built against
    stand-ins; a live report is welcome.
  • -R takes each form of OpenSSH's: socket paths on either side, and the
    remote SOCKS form (#73, T-365).
  • -J cf://HOST: a Cloudflare tunnel as the first hop of a jump chain
    (T-347).
  • podssh doctor:
    • whether the proxy takes an address as well as names (#74, T-366);
    • the listeners that this host allows, each listened on once (T-357,
      T-358);
    • this host's clock, when a certificate looks expired or not yet valid,
      in each command's TLS failure too (T-345);
    • the system's stores of roots on Windows and macOS, and what to do about
      an issuer that no root signs (T-340).
  • DNS over HTTPS in RFC 8484's wire form, with Quad9 after Cloudflare and
    Google. The addresses that carried a session are tried when the resolvers
    fail (T-344).
  • The quick tunnel over QUIC, where UDP reaches Cloudflare's edge (T-301).
  • russh 0.65.0, with its security fixes (T-356); the keys of the AEAD
    ciphers are wiped when a cipher is dropped (T-377).

What a beta does not have yet

  • The check of a release from end to end with no human (T-251); it runs
    before v1.0.0.
  • Signatures of the platforms: the Mac binaries are not signed with an
    Apple Developer ID, and the Windows binaries carry no Authenticode
    signature, so SmartScreen may warn. The proofs above stand in for them.

Report a defect

Open an issue at https://github.com/Azathothas/podssh/issues with the
output of podssh --version and podssh doctor --json. Read that output
before you post it: it names this host's proxy and addresses, and never a
token or a password.

The licenses of the crates in the binaries, with their texts: THIRD-PARTY-LICENSES.md.

The commits of this release

Documents

  • docs/relay-operator.md, audited on 2026-10-31 for the relay's agent: a brief that stands alone (what podssh is, the contract as the boundary, how an item is handed back), 18 items with their measureme… (804fff4)

Other

  • T-300, partial: a quick tunnel that podssh makes itself, over HTTP/2 with no cloudflared, and its client. The node, podssh node NAME TARGET --quick-tunnel (crates/podssh-relay/src/quick/, feature quic… (2258dd6)
  • T-331, partial: the layer's CLOSE before the exit of job, run, pipe, health, containers and --upgrade on a podssh node's cf:// name. Each runs on a runtime of one thread, where a spawned task runs onl… (24dda6b)
  • T-307:...
Read more

podssh v1.0.0-beta.2

podssh v1.0.0-beta.2 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 31 Oct 00:11

podssh v1.0.0-beta.2

The second beta. It carries the repairs since v1.0.0-beta.1 and more
platforms, and it is the first release that proves where each binary comes
from. A beta is a prerelease. Its tag never moves: a defect found in it goes
into the next beta.

The files

File For
podssh-x86_64-unknown-linux-musl Linux on x86-64, static: no library and no loader needed
podssh-aarch64-unknown-linux-musl Linux on aarch64, static
podssh-armv7-unknown-linux-musleabihf Linux on 32-bit ARM with hard float (a Raspberry Pi with a 32-bit system), static
podssh-riscv64gc-unknown-linux-musl Linux on 64-bit RISC-V, static
podssh-aarch64-apple-darwin macOS on Apple silicon; it links the system's libraries only
podssh-x86_64-apple-darwin macOS on Intel
podssh-x86_64-pc-windows-msvc.exe Windows on x86-64, with a static C runtime
podssh-aarch64-pc-windows-msvc.exe Windows on ARM64, with a static C runtime
SHA256SUMS The SHA-256 of each binary
SHA256SUMS.sigstore.json The signature of SHA256SUMS: Sigstore's keyless signing, by the release workflow at this tag
provenance.sigstore.json The provenance of each binary (SLSA), signed the same way: the workflow, the tag and its commit
THIRD-PARTY-LICENSES.md The licenses of the crates in the binaries, with their texts

Each binary ran on its own platform before it was published: --version,
the whole manual, keygen and keygen -y, and GitHub's SSH banner through
the live relay.

Check a download

T=v1.0.0-beta.2; B=podssh-x86_64-unknown-linux-musl   # or another file of the table
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/$B"
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/SHA256SUMS"
grep " $B\$" SHA256SUMS | sha256sum -c - && chmod +x "$B"
./"$B" --version   # podssh 1.0.0-beta.2 (the commit of the tag)
./"$B" doctor      # what this host allows, and whether the whole path works

On macOS, check with shasum -a 256 -c in place of sha256sum -c -. A
binary that curl fetched has no quarantine; after a browser's download,
run xattr -d com.apple.quarantine "$B" first. On Windows, compare
(Get-FileHash podssh-x86_64-pc-windows-msvc.exe).Hash with its line in
SHA256SUMS (the case of the letters differs).

The provenance of a binary names the release workflow and the tag (with the
GitHub CLI):

gh attestation verify "$B" --repo Azathothas/podssh \
  --signer-workflow Azathothas/podssh/.github/workflows/release.yml --source-ref "refs/tags/$T"

The signature of SHA256SUMS names the workflow at the tag (with cosign; 3.x
and 2.6 both check it):

curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/SHA256SUMS.sigstore.json"
cosign verify-blob --bundle SHA256SUMS.sigstore.json \
  --certificate-identity "https://github.com/Azathothas/podssh/.github/workflows/release.yml@refs/tags/$T" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com SHA256SUMS

The two proofs and podssh --version name the same commit.

What works

podssh ssh, each, run, job, session, containers, proxy, pipe,
cp, mv, scp, sftp and edit, doctor, keygen, agent, man,
status, ping,
health, node, operator, relay, chat, play and config, and
mcp. podssh man is the reference: each command, flag, -o keyword,
variable, file and exit code. These binaries have no Tailscale and no iroh
road: podssh ts, and a destination iroh:TICKET or --iroh-ticket, exit
with 70 and say so.

What to test again

New since v1.0.0-beta.1:

  • podssh doctor tells apart three failures of the WebSocket upgrade, and
    measures each TCP probe nine times, with its loss (#54, T-324). It names a
    proxy that answers 200 to CONNECT and then carries no SSH (T-317).
  • A proxy that answers 407 is named with what it asks for; podssh sends
    Basic from the user and password of the proxy URL (T-320).
  • A relay's name pinned to a loopback address goes with no proxy (T-318).
  • Each frame of a forward is 32 KiB at most, the relay's own limit (T-323).
  • podssh each --interactive --stop-key ^X: the stop of a broadcast on a
    key that you choose (T-322).
  • podssh node --install and --uninstall: the node as a service of its
    user, with no privilege (T-121).
  • podssh config import putty|mobaxterm|remmina FILE: hosts from the
    sessions of those programs (T-292).
  • podssh agent on macOS: its socket goes under /tmp where the temporary
    directory's path is too long for a socket (T-034).
  • podssh session start NAME HOST, then send, wait, capture and
    stop: a session with a pty that a podssh of its own keeps in the
    background, for a program that drives a terminal (T-186).
  • podssh job start|list|log|stop HOST: jobs in the far host's tmux that
    go on after the connection ends (T-193); and its queue, submit with
    --slots, wait and fetch, and a submit to a list of hosts that goes
    to the one with the fewest jobs (T-197).
  • podssh run HOST -- COMMAND: the project goes to the host, only the files
    that changed, and the command runs in it with its exit status (T-192).
  • podssh node --resume-deadline TIME: a node keeps a lost session up to
    72 h, and names the time to its clients (T-306).
  • With the resumable layer of a node: a notice in the window's title while
    the node is silent, which counts up and leaves the screen as it was
    (T-302); and a spare link beside a link that went silent, so that a new
    address of this host costs seconds, not 30 s (T-305;
    PODSSH_SPARE_LINKS=no turns it off).
  • The new platforms of the table: macOS, Windows on ARM64, and Linux on
    32-bit ARM and on RISC-V.

What a beta does not have yet

  • The check of a release from end to end with no human (T-251); it runs
    before v1.0.0.
  • Signatures of the platforms: the Mac binaries are not signed with an
    Apple Developer ID, and the Windows binaries carry no Authenticode
    signature, so SmartScreen may warn. The proofs above stand in for them.

Report a defect

Open an issue at https://github.com/Azathothas/podssh/issues with the
output of podssh --version and podssh doctor --json. Read that output
before you post it: it names this host's proxy and addresses, and never a
token or a password.

The licenses of the crates in the binaries, with their texts: THIRD-PARTY-LICENSES.md.

The commits of this release

Commands

  • podssh session: one SSH session with a pty that outlives each call of an agent (T-186, the draft of 2026-10-13 merged): start runs serve in the background, which binds its socket (mode 0600 in session… (4d17c3e)
  • podssh run: copy a project to a host, only the files that changed, then run a command in it with its exit status (T-192, the draft of 2026-10-13 merged): the project goes to ~/.podssh/run/NAME, or hos… (a792d1a)

Other

  • A proxy that takes the CONNECT and carries no SSH is named (T-317): podssh doctor reads the first bytes of github.com port 22 for 5 s after the 200, and on the direct road too, and says that plain ssh… (465cadc)
  • v1.0.0-beta.1 is published (T-309): a prerelease at 5c8d423, made by the release workflow by hand with publish=v1.0.0-beta.1 (run 41054194363), after the gate, deny, secrets, the dry run (run 41051568… (0becfb9)
  • The requests of 2026-10-30 in the record: GitHub #54 is T-324 (doctor tells the three failures of the upgrade apart, and samples each probe with its loss) and T-325 (what the path does to a stream: bu… (c00c9fd)
  • Each forward frame of podssh is 32 KiB at most (T-323): FORWARD_SEND_PAYLOAD beside the relay's cap in podssh-ws is the one size of the stream of podssh ssh, which sent 64 KiB, of the relay leg of pod… (0d80320)
  • A relay's name pinned to loopback goes with no proxy (T-318): podssh never sends a loopback target to a proxy, as the proxy's loopback is not this host's, and a name that --relay-addr or PODSSH_RELAY_… (472adff)
  • A 407 names what the proxy asks for (T-320): podssh sends Basic only, from the user and password of the proxy URL, as Go, wget, requests and reqwest do, and on a 407 read no Proxy-Authenticate, so a u… (95ef7a3)
  • The stop of the broadcast has a key that the user chooses (T-322): podssh each --interactive --stop-key ^X makes Ctrl-X the terminal's QUIT character for the run on Unix, with a guard that puts the ol… (9133f0a)
  • doctor samples each probe of TCP, and names three failures of the upgrade (T-324): each CONNECT through the proxy and direct TCP is tried nine times, 125 ms apart, and its line gives the best time, th… (c0ed03f)
  • podssh node --install makes the node a service of its user, with no privilege (T-121, partial): a probe finds the way, a user unit of systemd when systemctl --user answers (daemon-reload, enable, rest… (9c6a4a0)
  • podssh node --install, measured on a host with systemd (T-121): the workflow service live (run 41066805844, a GitHub runner) made a pair on the live relay, and --install made a user unit of systemd, e… (0b760dd)
  • The pinned images move out of .github/ to images/ (T-308, partial): Dependabot's docker job finds each update and its create_pull_request gets 400, "The request contains invalid or unauthorized change… (8b53759)
  • podssh config import reads the sessions of PuTTY, MobaXterm and Remmina (T-292): a .reg file of PuTTY's Sessions key in UTF-16LE, UTF-8 or the ANSI of REGEDIT4, or its session files of Unix (a file or… (1891f43)
  • The workflow quick tunnel edge measures the edge of Cloudflare's quick tunnels in GitHub Actions (T-299, partial; Q43). It is dispatched by hand with confirm=Q43. Its steps: cloudflared 2026.10.6, pin… (687ccf1)
  • The workflow quick tunnel edge gets a job relay, step 4 of T-299: podssh built in the job asks the live relay to trace the edge's 7844 (two addresses and the name) and an address'...
Read more

podssh v1.0.0-beta.1

podssh v1.0.0-beta.1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 30 Oct 12:26

podssh v1.0.0-beta.1

The first beta since this repository's history was replaced: it carries
each change since 2026-10-08. A beta is a prerelease. Its tag never moves:
a defect found in it goes into the next beta.

The files

File For
podssh-x86_64-unknown-linux-musl Linux on x86-64, static: no library and no loader needed
podssh-aarch64-unknown-linux-musl Linux on aarch64, static
podssh-x86_64-pc-windows-msvc.exe Windows on x86-64, with a static C runtime
SHA256SUMS The SHA-256 of each binary
THIRD-PARTY-LICENSES.md The licenses of the crates in the binaries, with their texts

Check a download

T=v1.0.0-beta.1; B=podssh-x86_64-unknown-linux-musl   # or podssh-aarch64-unknown-linux-musl
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/$B"
curl -fsSLO "https://github.com/Azathothas/podssh/releases/download/$T/SHA256SUMS"
grep " $B\$" SHA256SUMS | sha256sum -c - && chmod +x "$B"
./"$B" --version   # podssh 1.0.0-beta.1
./"$B" doctor      # what this host allows, and whether the whole path works

On Windows, compare (Get-FileHash podssh-x86_64-pc-windows-msvc.exe).Hash
with its line in SHA256SUMS (the case of the letters differs).

What works

podssh ssh, each, containers, proxy, pipe, cp, mv, scp,
sftp and edit, doctor, keygen, agent, man, status, ping,
health, node, operator, relay, chat, play and config, and
mcp. podssh man is the reference: each command, flag, -o keyword,
variable, file and exit code. These binaries have no Tailscale and no iroh
road: podssh ts, and a destination iroh:TICKET or --iroh-ticket, exit
with 70 and say so.

What to test again

What the earlier betas asked for, and this beta has:

  • ssh_config, -F, -G and Match (#14, #22).
  • A relay session that drops: the hop that broke is named, and a forward is
    tried again when that is safe (#17).
  • Copies (#21): podssh cp continues after a drop, writes a temporary
    name, checks the digest and then renames; pipelined SFTP, parallel chunks,
    delta copies, -r, --delete, --dry-run, progress and a bandwidth
    limit; scp and sftp with OpenSSH's command lines; edit; ZMODEM.
  • Output for machines: doctor --json, man --json, status, ping,
    health, and the exit status of a remote command (#23).
  • Many hosts: each, broadcast with an emergency stop, recordings and
    play (#24).
  • Streams that are not SSH: pipe, -W, AF_UNIX streams, UDP over the
    relay (#26).
  • podssh doctor in your sandbox, with and without HTTPS_PROXY; a
    no_proxy with blocks such as 10.0.0.0/8 keeps each address inside
    them off the proxy now, and doctor names the entry (T-316).

What a beta does not have yet

  • Build provenance and signed checksums (T-210, T-211): SHA256SUMS comes
    from the run that built the binaries, and is not signed.
  • macOS, Linux armv7 and riscv64, and Windows aarch64 binaries (T-218).
  • The check of a release from end to end with no human (T-251); it runs
    before v1.0.0.
  • Known, for the next beta: a proxy that answers 200 to CONNECT and then
    carries no SSH is not named as the cause (T-317).

Report a defect

Open an issue at https://github.com/Azathothas/podssh/issues with the
output of podssh --version and podssh doctor --json. Read that output
before you post it: it names this host's proxy and addresses, and never a
token or a password.

The licenses of the crates in the binaries, with their texts: THIRD-PARTY-LICENSES.md.

The commits of this release

Commands

  • podssh ssh: the native client, on russh (e34597b)
  • podssh doctor: what a host allows and whether the relay path works (7b38e31)
  • podssh keygen: SSH keys in OpenSSH's format, for hosts without ssh-keygen (9b806fe)
  • podssh man: the whole manual from the binary, as text (d0b16a3)
  • podssh ssh: each flag of OpenSSH 10.3p1 answers by name (0c93a7c)
  • podssh ssh: a repeated flag follows OpenSSH; -J and -W only once (3ee70dc)
  • podssh status: one line of JSON about this host (692b3b0)
  • podssh agent: an SSH agent inside podssh, on a socket that only this user can open, with add, list, remove, lock and unlock (T-034) (f7d5640)

Build and CI

  • Workflows: artifact actions on Node 24; dumpbin found with vswhere (3937707)
  • scripts/sandbox-check.sh: the sandbox measurement as one command (4853e6c)
  • scripts/test_in_box.sh: a Podman box built to the target sandbox's profile (4f66d9b)
  • gate: the no-C rule also stops C++ (CXX=/nonexistent) (a378863)
  • CI runs the console checks on Windows, against MSYS2's sshd (dacbf4a)
  • CI runs each step of the gate in a job of its own, at the same time (a04b0c8)
  • scripts/dev.sh in two files, each under 500 lines, and the size check reads the scripts (d88de09)
  • CI pulls each pinned image through a fallback: when Docker Hub refuses a pull with no account, a mirror serves the same digest (5557c62)
  • CI names the systems of its runners, ubuntu-24.04 and windows-2025, before ubuntu-latest moves to Ubuntu 26 on 2026-10-19 (T-278, partial) (0804e38)
  • scripts/gate.sh tries each download of rustup and apk three times, 10 s and then 20 s apart, as CI at 0d3d13a failed in its step msrv_ts when one DNS lookup of rustup's channel file failed on the runn… (73f910b)
  • scripts/fuzz.sh builds and runs each fuzz target for this host's own target, as the first run of the workflow fuzz found that a release binary of cargo-fuzz, built for musl, built the targets for musl… (6529789)

Documents

  • docs: design.md, the answers that decide podssh's future (bcbccf1)
  • Docs, pass 1: the routing documents in ASD-STE100, and docs/defects.md (3c7734a)
  • Docs, pass 2: STATUS and ROADMAP in ASD-STE100 (5b9805f)
  • Docs, pass 3: the topic pages in ASD-STE100, brought up to date (6649623)
  • Docs, pass 4: design, milestone pages and release notes in ASD-STE100 (3a88e1d)

Repairs

  • Fix -4/-6, the 1001 exit, -W on a lost connection, two messages (72dc8a6)

Other

  • podssh: initial public release (9a03102)
  • STATUS: the gate re-run is green, interop 62 of 62 (32a2837)
  • podssh-ws: never proxy loopback; drop three unused dependencies (f9dda61)
  • Roadmap: the operator's decisions on the way to a finished podssh (fd259f8)
  • podssh-relay: relay hosts with failover, in a C-free library crate (b45fcb4)
  • Liveness: ping the relay, declare a silent link dead in 30 s (a00c7a2)
  • No proxy and no DNS: pinned addresses, DNS over HTTPS, RSA in TLS (a89deaf)
  • Fault injection in the gate; the dead DNS stack in podssh-transport removed (c078085)
  • Interactive use on Windows, measured in a real pseudo console (ca50a68)
  • Release notes for v0.1.0-beta.1: doctor, keygen, failover, the fault harness (aa9cfaa)
  • Prompts: no wait for ever on a terminal that nobody watches (eacd94e)
  • TODO/: the work record, with its checker in Rust and in the gate (22c3b88)
  • TODO/: T-249, a cited line that moved still exists (e275d36)
  • AGENTS.md: a session runs unattended toward v1.0.0 (b1b111b)
  • One release only: v1.0.0, tagged once at the end (4bf0c26)
  • The box has the sandbox's dead /dev/tty; T-005 measured there (d272ebb)
  • podssh-todo: remap moves the citations of an edited file; a quote must hold (cd12fa3)
  • sandbox-check.sh: each step has a verdict, and a failed step fails the run (eaf9822)
  • IPv6 addresses as targets: podssh sends the bare literal to the relay (2da855f)
  • Relay tokens: one cache entry for each deployment, with the host that minted it (37ace00)
  • A command that is not implemented says so before the --timeout gate (3cd368b)
  • A flag with no value names the flag and its value (56b466b)
  • podssh --help and --version drop no word (4bceef6)
  • A host that starts with -: refused also as HostName, and -- is documented (475aea9)
  • A refusal names keys only when keys were tried (80f20bf)
  • A dropped session names the hop that broke (25ab0e7)
  • The -R refusal gives its own cause, not the listener (cd3fea5)
  • A bad relay variable is a configuration error (78) (fdbba30)
  • The help of a command that does not work says so (02e4e1f)
  • podssh man relay-facts selects THE RELAY (9fefff2)
  • Each answer of the server while logging in has a time limit (8d668b7)
  • A channel that podssh did not ask for is refused (5c7a1ad)
  • The % tokens are OpenSSH's (5521cbf)
  • -W takes HOST:PORT, as OpenSSH reads it (d87ca8a)
  • podssh doctor gives the version and the age of the compiled-in roots (2c39778)
  • An interactive session over -tt from the box: vi, less, top and Ctrl-C (bc13eee)
  • podssh doctor --json (332ee58)
  • podssh man --json (a2eeb7f)
  • PODSSH_TIMEOUT gives the default of --timeout (bd626c7)
  • podssh doctor --full logs in to GitHub with a key made for the check (d98d77e)
  • T-052 measured in the box: login ok (c6f09a8)
  • The node leg's control leaves as a text frame (3d4785a)
  • A Close from the relay keeps its code and reason (6d7737f)
  • The node leg sends data only for a readied session (1a00ba2)
  • An HTTP answer to an upgrade keeps its body and follows the contract (4b6e917)
  • A host or a pair name cannot change the relay path (3b60753)
  • A control frame that RFC 6455 forbids fails the connection (076e3ce)
  • cargo todo check finds a citation that a forgotten remap left (4e817d7)
  • No crate carries a verifier that accepts each certificate (510d86f)
  • No draw of random bytes can panic (c56792f)
  • A library can bring its own rustls configuration (723d90b)
  • A session's failure has a class (23b5d82)
  • A plain ws:// session to the loopback, for tests (3632dcb)
  • Pairs of the reverse road, made, asked about and stopped (9811e0d)
  • The node of the reverse road (c3a3ca9)
  • The operator of the reverse road (0d92eef)
  • A blocking facade for podbox (af0a163)
  • The node and the pairs on the command line (3cbf215)
  • The operator, and ssh to a node (e8bbd4d)
  • The codecs of the reverse road in podssh-relay (cd75137)
  • The reverse road has no idle cut, and drops at random (0052ac9)
  • ...
Read more