Skip to content

Releases: wslkit/skrog

Skrog 0.4.1

Skrog 0.4.1 Pre-release
Pre-release

Choose a tag to compare

@zcsizmadia zcsizmadia released this 12 Sep 23:09
845fa3b

v0.4.0 shipped a bug that hangs docker run -i. If you are on v0.4.0,
this is the release to take. (#237)

A patch release: no rename, no new engine, no migration. The rootfs is unchanged
(29.8.0-2), so skrog install pulls the same engine v0.4.0 did.

Install

irm https://wslkit.github.io/skrog/install.ps1 | iex

Already on v0.4.0? skrog upgrade reports it; the installer above replaces the
binaries in place and your distro, images and volumes are untouched.

The hang

echo hi | docker run -i --rm alpine cat never returned on v0.4.0, and neither
did docker exec -i.

The bridge wraps its connections to count bytes for skrog status --stats. That
wrapper embedded io.ReadWriteCloser — an interface, whose method set is
exactly {Read, Write, Close}. Embedding an interface in Go gives you that
interface's methods, not the concrete type's, so CloseWrite was never promoted
and the type assertion for it failed. The docker CLI half-closes to signal stdin
EOF; the signal was swallowed, the container's stdin stayed open, and cat
waited forever.

The wrapper now asserts through to the underlying connection. A test that had
passed throughout asserted the wrapper was still a net.Conn, which it always
was — it never asked whether the half-close survived.

Also fixed

Verifying a download actually works now. SHA256SUMS was written with CRLF,
so sha256sum -c printed no file was verified on every release to date — the
trailing \r became part of the filename it looked for. The hashes were right;
the format was not. Past releases are signed as published and cannot be
corrected, so the workaround for them is documented.
(#248)

Three fixes where a guard was not guarding:

  • A policy file that has never parsed now refuses requests instead of
    allowing everything. A rule file present but unreadable meant every container
    was judged by no rules at all, silently — the opposite of what configuring one
    asks for. (#254)
  • allow-bind-sources judges npipe mounts and resolves traversal first.
    A named-pipe mount is a bind mount by the time the bridge is done with it, and
    a path with .. in it was compared before being resolved.
    (#256)
  • Every listener that serves the engine enforces policy and audits. One did
    not. (#257)

And a run of state-handling bugs, each of which left something in a worse place
than it claimed:

  • the agent is told where its secret is rather than trusting a default that
    moved with the rename (#239)
  • a volume migrate created but could not fill is no longer reported as already
    migrated (#251)
  • a failed snapshot restore says where your data is, and can be retried
    (#252)
  • relocate starts the engine before deleting the archive, not after
    (#253)
  • a self-heal that fails records the engine actually installed
    (#264)
  • compact no longer leaves the engine stopped and pinned down in silence
    (#265)
  • a snapshot whose record cannot be written no longer orphans its archive
    (#267)
  • the offline bundle no longer names the file it is extracted to
    (#260)

New

  • skrog runner check reports whether the machine sleeps on mains power
    the setting that quietly kills a self-hosted runner overnight.
    (#268)
  • skrog status names the endpoint it is serving, in the text output and
    under endpoint in --json, with both the pipe and its DOCKER_HOST
    spelling. It reports what the running supervisor bound, read back from the
    supervisor's own record rather than recomputed — Docker Desktop can start or
    stop after Skrog chose, and a recomputed answer could name a pipe nothing is
    serving. (#273)

Docs

The site now has canonical URLs, a sitemap crawlers can find, and link previews.
Every page distinguishes running with Docker Desktop from running without
it — the old text handed you --context skrog as the happy path even on a
machine where Skrog holds the default pipe and no flag is needed. The README
says where Rancher Desktop, Podman Desktop and Docker Desktop each win, and when
to pick one of them instead.

Verifying this release

gh attestation verify skrog_0.4.1_windows_amd64.zip --owner wslkit
sha256sum -c SHA256SUMS --ignore-missing

The second one works on this release. It did not on any earlier one.

Still not code-signed — SmartScreen warns on first run. A SignPath Foundation
application is in. (#77)

Full changelog: v0.4.0...v0.4.1

Skrog 0.4.0

Skrog 0.4.0 Pre-release
Pre-release

Choose a tag to compare

@zcsizmadia zcsizmadia released this 12 Sep 00:04
a6154ca

Hawser is now Skrog. Everything is renamed: the binaries, the WSL distro,
the docker context, the state directory, the config and lock files, the pipes
and the environment variables. There is no in-place upgrade from v0.3.1
what you download here is a different program, not a newer copy of the one you
have. If you have images or volumes worth keeping, read
coming from Hawser
before you uninstall anything. (#1)

The old name was chosen on the belief that its namespace was nearly empty. That
was true of trademark registries and false of common-law use:
Finsys/hawser, a 606-star Go agent for
Docker host management, predated this project by nine months. A search for
"hawser" returned dictionaries and that project, never this one — so the
discoverability the name was chosen for could never have worked.

Skrog is Norwegian for hull: the body of the ship that carries the cargo
and keeps the sea out. It is closer to what this is than a mooring line ever
was — the thing containers live inside, not the rope to the dock.

Install

irm https://wslkit.github.io/skrog/install.ps1 | iex

What changed

was now
binaries hawser.exe, hawserw.exe, hawsertray.exe skrog.exe, skrogw.exe, skrogtray.exe
WSL distro hawser-engine skrog-engine
docker context hawser skrog
state directory %LOCALAPPDATA%\Hawser %LOCALAPPDATA%\Skrog
config / lock hawser.yaml, hawser.lock skrog.yaml, skrog.lock
environment HAWSER_* SKROG_*
org hawserhq wslkit
docs hawserhq.github.io/hawser wslkit.github.io/skrog

The GitHub repository URLs redirect. The Pages URLs do not — so any
bookmark to the old documentation site is already broken, and the install
one-liner above is the current one.

Coming from Hawser

Your images and volumes live inside the hawser-engine distro, and uninstalling
removes them. Because every name above differs, the two installs can coexist —
which gives you a way to keep them:

skrog install
skrog start
skrog migrate --from-context hawser --dry-run   # what would move, and how big
skrog migrate --from-context hawser

skrog migrate is documented for Docker Desktop, but the mechanism is
engine-to-engine and --from-context takes any docker context. It never writes
to the source, so an interrupted run leaves the Hawser side untouched. This
path has not been exercised against a Hawser install
— run the --dry-run
first and keep Hawser until you have checked what arrived.

A new mark

The coiled rope was a picture of the old name. The mark is now a hull's body
plan
— the section a naval architect draws at each frame, with the centreline
through it. It is drawn as an outline, so the stroke weight is corrected per
size: 15 design units on a 512 px tile, 28 at 16 px, which is what keeps the
tray icon and favicon from greying out. (#231)

Fixed

  • The installer was broken by the rename and only the published one-liner
    showed it — the asset it fetched no longer existed under that name.
    (#229)
  • The installer was not republished when it changed, only when the docs did,
    so the fix above merged green without reaching the URL people run.
    (#230)
  • The engine manifest pointed at rootfs tarballs that do not exist. The
    rename rewrote the filenames of assets that were already published, so every
    skrog install and skrog engine rollback would have 404'd. It passed CI
    because the rename also rewrote the test that guards it. A network-tagged
    check now asks GitHub whether each published URL resolves.
    (#232)

Verifying this release

# 1. Did GitHub Actions build this, from this repository, at a known commit?
gh attestation verify skrog_0.4.0_windows_amd64.zip --owner wslkit

# 2. Is the checksum list itself authentic?
cosign verify-blob --bundle SHA256SUMS.cosign.bundle `
  --certificate-identity-regexp '^https://github.com/wslkit/skrog/' `
  --certificate-oidc-issuer https://token.actions.githubusercontent.com SHA256SUMS

# 3. Does your download match the signed list?
sha256sum -c SHA256SUMS --ignore-missing

Binaries are still not Authenticode-signed, so SmartScreen will warn. That
is tracked in #77.

Hawser 0.3.1

Hawser 0.3.1 Pre-release
Pre-release

Choose a tag to compare

@zcsizmadia zcsizmadia released this 11 Sep 16:43
42d3d8d

This release predates the rename. The project was called Hawser until
after v0.3.1; it is now Skrog, under the wslkit org. The assets below
keep the names they were published with and still verify. The install
command has been corrected to the current URL — GitHub redirects repository
URLs after an org rename but not GitHub Pages URLs, so the original link no
longer resolves. See #1.

Releases are verifiable from this one onward. Every artifact now carries SLSA build provenance, and SHA256SUMS is signed with cosign keyless — two independent checks that v0.3.0 could not offer, because both landed two days after it was tagged.

# 1. Did GitHub Actions build this, from this repository, at a known commit?
gh attestation verify hawser_0.3.1_windows_amd64.zip --owner hawserhq

# 2. Is the checksum list itself authentic?
cosign verify-blob --bundle SHA256SUMS.cosign.bundle `
  --certificate-identity-regexp '^https://github.com/hawserhq/hawser/' `
  --certificate-oidc-issuer https://token.actions.githubusercontent.com SHA256SUMS

# 3. Does your download match the signed list?
sha256sum -c SHA256SUMS --ignore-missing

Binaries are still not Authenticode-signed, so SmartScreen will warn. That is tracked in #77.

Install

irm https://wslkit.github.io/skrog/install.ps1 | iex

New in this release: it downloads the newest release, verifies it against SHA256SUMS, unpacks it and adds it to your PATH. It deliberately stops there — hawser install provisions the engine, and that is not something a piped command should do unasked.

New

  • hawser policy — local admission control for the docker API. Refuse --privileged, capabilities, host namespaces, bind sources or registries this machine has ruled out, before the engine sees them. A guardrail against mistakes, not a boundary against a hostile local user, and it says so. (#120)
  • hawser upgrade — one answer to "am I current?" across the app, the engine and the bundled docker CLI, and it applies the two it owns. It also surfaces an ordering dependency nothing else showed: the engines hawser engine upgrade can reach are pinned in the binary you are running, so a newer engine can need a newer hawser first. (#191)
  • hawser restart --supervisor — the supervisor process could not be restarted at all before; the only way was to kill a PID by hand. (#202)
  • A documentation site at https://hawserhq.github.io/hawser/, generated from docs/, with a command reference generated from the binary's own --help so it cannot drift. (#197, #209)
  • Experimental AMD GPU support through the same hookless CDI spec as NVIDIA. Untested on real hardware — if you have a Radeon, #185 wants to hear from you.

Fixed

  • hawser config set audit on did nothing. The supervisor read the setting once at startup, and the help text told you to run hawser restart — which bounces the engine, not the supervisor holding the setting. The command exited 0, printed no error, and produced no audit log. Settings are now re-read live wherever they are consumed. (#202)
  • Corporate-network settings were captured at supervisor launch, so hawser config set network.proxy … followed by hawser restart re-applied whatever was set at logon. (#202)
  • hawser uninstall deleted the shared hawser docker context, breaking any other install on the machine — including the developer's own, after running the acceptance suite. It now hands the context back. (#217)
  • The recorded rootfs URL depended on a GitHub redirect that can lapse or be taken over. It is normalised to the project's current home. (#212)
  • hawser audit tail -n 5 was rejected, though that is the form the command's own usage line advertises.
  • The tray flashed a console window on every status poll, and spawned a process every four seconds to recompute state the supervisor already publishes. (#195, #192)
  • The engine rootfs shipped no licence text for the software inside it. It now ships all five components' licences. (#205)

Upgrading from 0.3.0

hawser upgrade does not exist in 0.3.0, so this one is a manual step — run the installer above, or download the zip and unpack it over your existing install. Stop the engine first (hawser stop, and quit the tray) so the binaries are not locked. From 0.3.1 onward, hawser upgrade reports and applies.

Your engine, images, containers and volumes are untouched by an app upgrade.

rootfs 29.8.0-2

rootfs 29.8.0-2 Pre-release
Pre-release

Choose a tag to compare

@zcsizmadia zcsizmadia released this 11 Sep 23:25
0e7a927

A revision bump with no engine change: containerd (2.1.4), runc (1.3.0), BuildKit (0.27.0), Alpine (3.24.1) and nvidia-cdi-hook (1.20.0) are identical to 29.8.0-1, and the engine is still moby docker-v29.8.0 pinned to commit 3ce5872b7950c63ba2ffbc5123101019ff3e6682.

What changed is inside the tarball: the in-distro agent is skrog-agent, not hawser-agent. Renaming the project renamed the binary the rootfs build produces, but every rootfs published before this one still carries the old name — a name crossing a boundary that cannot be renamed with it. Skrog looks for either, so nothing broke; this release is what lets that compatibility lookup go away.

The asset names change with it, for the same reason: this is the first rootfs published as skrog-rootfs-*. Earlier releases keep the hawser-rootfs-* names they were published under, and internal/release/manifest.json records them that way (#232) — a published asset's filename is a fact, not text to be renamed.

Verify before use:

# the checksum the manifest pins
sha256sum -c skrog-rootfs-29.8.0-2.tar.gz.sha256

# and that GitHub Actions signed that checksum list
cosign verify-blob --bundle skrog-rootfs-29.8.0-2.tar.gz.sha256.cosign.bundle `
  --certificate-identity-regexp '^https://github.com/wslkit/skrog/' `
  --certificate-oidc-issuer https://token.actions.githubusercontent.com `
  skrog-rootfs-29.8.0-2.tar.gz.sha256

rootfs 29.8.0-1

rootfs 29.8.0-1 Pre-release
Pre-release

Choose a tag to compare

@zcsizmadia zcsizmadia released this 10 Sep 23:55
f72dfc1

Rootfs 29.8.0-1 moves the engine to moby docker-v29.8.0 (upstream released 2026-09-03), from 29.7.2. It also closes a drift: the bundled docker CLI was already 29.8.0, so hawser cli install had been putting a 29.8.0 client in front of a 29.7.2 daemon.

containerd (2.1.4), runc (1.3.0), BuildKit (0.27.0), Alpine (3.24.1) and nvidia-cdi-hook (1.20.0) are unchanged. Those pins are a tested combination rather than a race to the newest tag, and moving one is a separate, justified decision — see docs/bumping-upstream.md.

The moby tag is pinned to commit 3ce5872b7950c63ba2ffbc5123101019ff3e6682, which the build verifies before compiling.

Built from PR #186 (issue #183).

rootfs 29.7.2-4

rootfs 29.7.2-4 Pre-release
Pre-release

Choose a tag to compare

@zcsizmadia zcsizmadia released this 10 Sep 04:59

Rootfs 29.7.2-4 adds a statically linked nvidia-cdi-hook (v1.20.0, Apache-2.0) so moby registers its NVIDIA GPU driver at daemon start and docker run --gpus all routes to the hookless CDI spec that hawser enable-gpu installs. The hook is never executed — its presence is what enables the driver — and VS Code Dev Containers' "hostRequirements": {"gpu": true} goes through the same path.

Engine, containerd, runc and BuildKit pins are unchanged from 29.7.2-3.

Built from PR #165 (issue #139).

Hawser 0.3.0

Hawser 0.3.0 Pre-release
Pre-release

Choose a tag to compare

@zcsizmadia zcsizmadia released this 08 Sep 13:31
9fc626e

Third milestone: the diagnosis-and-configuration layer, plus the security hardening from an independent multi-agent review of v0.2.

Highlights

  • hawser doctor — turns the WSL2 quirk zoo into a diagnosable surface. Eight checks seeded from failures this project actually hit (WSL platform, which docker.exe wins on PATH, credential-helper resolution, engine install, docker context, supervisor/engine agreement, disk space, unattended-startup readiness). Human text, --json for CI, --report (Markdown to paste into an issue), and --fix for the safe subset.
  • Validated engine settingshawser config set engine.<key> edits the engine's daemon.json (registry mirrors, insecure registries, DNS, logging, concurrency) through a curated allowlist. Every change is run through dockerd --validate before it replaces the live file, applied atomically, and rolled back if the engine does not come back — where Docker Desktop offers a raw JSON textbox that can brick the daemon.
  • Lifecycle hooks — run your own script on post-start / pre-stop / on-idle-stop / on-wake, time-bounded and best-effort (a failing hook is logged, never blocks the engine). hawser config set hook.post-start <path>.
  • Declarative installshawser install --config hawser.yaml provisions and converges a whole install (distro, engine version, idle timeout, engine keys, hooks, integrations, autostart) idempotently; hawser config export round-trips an existing machine into a file. Infrastructure-as-code for a fleet — the free answer to Docker Desktop's paywalled Settings Management.
  • Security hardening (independent 4-agent review of v0.2, all findings fixed) — per-install mutual authentication on the vsock channel; the docker pipe DACL scoped to the installing user instead of all interactive users; the supervisor's single-instance lock rewritten from a thread-affine named mutex to a file lock; a health probe that no longer boots a stopped distro; rootfs built from SHA-verified upstream sources; and a documented trust-boundary model.
  • Idle-stop bug fixed — the shared-socket "busy" veto was counting Hawser's own health probe and keeping the engine up forever; it is now scoped to installs that actually share the socket via wsl-integrate.

Install

Download hawser_0.3.0_windows_amd64.zip (or arm64), unzip, and run hawser install. The rootfs is checksum-verified against the embedded manifest. Requires any docker CLI on PATH (Docker Desktop's works; a bundled CLI is planned for a later release).

New in v0.3: run hawser doctor if anything misbehaves, and see docs/hooks.md and docs/declarative-install.md.

Notes

  • Unsigned (signing lands in v0.4) — SmartScreen will warn; verify against SHA256SUMS.
  • Unattended/CI use needs a logged-on session — see docs/auto-logon-runner.md.
  • Pre-release: validated end-to-end on Windows 11 + WSL2 via the 22-stage acceptance suite, on a single machine. Field-test before relying on it broadly.

Engine: dockerd 29.7.2, containerd 2.1.4, runc 1.3.0, buildkit 0.27.0 (rootfs 29.7.2-3, built from source).

Rootfs 29.7.2-3

Rootfs 29.7.2-3 Pre-release
Pre-release

Choose a tag to compare

@zcsizmadia zcsizmadia released this 06 Sep 03:18

Engine rootfs, packaging revision 3 of engine 29.7.2. Engine components are unchanged from 29.7.2-2 (dockerd 29.7.2, containerd 2.1.4, runc 1.3.0, buildkit 0.27.0, Alpine 3.24); this revision rebuilds the in-distro hawser-agent with the v0.2.0 security-review hardening:

  • Mutual authentication (#81) — the agent (now hawser-agent/2) proves a per-install secret in the vsock handshake, so a sibling distro cannot impersonate it while the engine is idle-stopped. Backward compatible: a host without the secret still connects.
  • fd-race fix (#84)CloseWrite pins the fd via SyscallConn, so a concurrent close can't half-close a stranger's connection under load.
  • Hardening (#92) — a handshake read deadline and EMFILE-tolerant accept loop.

Also, the build now verifies each engine component's commit SHA and pins the Alpine base by digest (#88).

Assets (attached by the rootfs workflow): hawser-rootfs-29.7.2-3.tar.gz, its .sha256, and an SPDX SBOM. Becomes the default once the manifest PR lands.

Hawser 0.2.0

Hawser 0.2.0 Pre-release
Pre-release

Choose a tag to compare

@zcsizmadia zcsizmadia released this 02 Sep 02:37
072b3d2

Second milestone: the always-on layer, native-speed transport, and Docker Desktop parity for trying it out.

Highlights

  • Always-on supervisor — starts at logon, keeps the engine alive across crashes, wsl --shutdown, and sleep/resume. hawser start|stop|restart|status, autostart via a windowless launcher, and a Warn+ mirror to the Windows Event Log.
  • vsock guest agent — replaces per-connection socat with an in-distro hawser-agent over AF_HYPERV. docker version is ~80 ms — at parity with Docker Desktop (~83 ms) — and interrupted-client connection leaks are gone. Falls back to socat automatically on an older rootfs.
  • Idle timeout + on-demand starthawser config set idle-timeout 30m: the engine stops when the bridge is quiet and no containers run, then cold-starts (~0.8 s) on the next docker command. hawser status reports idle distinctly from stopped.
  • hawser wsl-integrate <distro> — share the engine into your own WSL distros (DOCKER_HOST to a /mnt/wsl socket), usable as the ordinary user.
  • hawser migrate --from-desktop — copy images and named volumes out of Docker Desktop, non-destructively; --dry-run, --only, resumable.
  • Status-light tray (hawsertray.exe, optional) — a six-item menu that shells out to the CLI; no control panel, ever.
  • Interactive docker run -i/exec -i fixed — the byte-mode named pipe could not carry a half-close, so piping into containers hung; the bridge now serves the pipe in message mode. Interactive TTY (-it), resize, and Ctrl-C forwarding validated against Docker Desktop parity.

Install

Download hawser_0.2.0_windows_amd64.zip (or arm64), unzip, and run hawser install. The rootfs is checksum-verified against the embedded manifest.

Notes

  • Unsigned (signing lands in v0.4) — SmartScreen will warn; verify against SHA256SUMS.
  • Unattended/CI use needs a logged-on session — see docs/auto-logon-runner.md.
  • Pre-release: validated end-to-end on Windows 11 + WSL2 via the 18-stage acceptance suite, on a single machine. Field-test before relying on it broadly.

Engine: dockerd 29.7.2, containerd 2.1.4, runc 1.3.0, buildkit 0.27.0 (rootfs 29.7.2-2, built from source).

Hawser 0.1.0

Hawser 0.1.0 Pre-release
Pre-release

Choose a tag to compare

@zcsizmadia zcsizmadia released this 01 Sep 20:12
2fe3b46

The first installable Hawser: the upstream Docker Engine on Windows via WSL2, reached by stock docker.exe over a named pipe. No license fees, no Electron, no Kubernetes.

What works

hawser install     # verified rootfs download -> WSL2 distro -> engine start -> docker context
hawser proxy       # serves the pipe, translates Windows bind paths, coexists with Docker Desktop
docker --context hawser run --rm hello-world
hawser uninstall   # removes everything it created, restores your previous context
  • The real Docker API — compose, bind mounts with Windows paths (-v C:\src:/app), exec, logs -f, and anything that speaks to docker.sock work unmodified
  • Coexists with Docker Desktop: never takes the default pipe if Desktop holds it; both engines usable side by side
  • Deterministic by contract: the engine (dockerd 29.7.2, containerd 2.1.4, runc 1.3.0, buildkit 0.27.0) is pinned in an embedded manifest, checksum-verified before import, and built from upstream source — the SBOM points at commits
  • Verified by a 13-stage acceptance suite on real WSL2, including a compose stack, an interrupted client, and a Docker-Desktop-still-works check

Honest limits

  • Pre-release, unsigned binaries — SmartScreen will warn; verify against SHA256SUMS (signing lands in v0.4)
  • A logged-on session is required (a WSL2 constraint that binds every WSL-based engine; auto-logon covers headless runners)
  • hawser proxy runs in the foreground; the always-on supervisor is v0.2
  • Interrupted clients can leave relay processes alive for up to 5 minutes (bounded; fully fixed by the v0.2 agent)
  • Linux containers only, x64 and arm64 Windows

Install

  1. Download the zip for your architecture below and extract hawser.exe
  2. hawser.exe install
  3. hawser.exe proxy (keep it running)
  4. docker --context hawser run --rm hello-world

Binaries are attached automatically by the release workflow, with SHA256SUMS.