Summary
CRI-O depends on github.com/soheilhy/cmux (v0.1.5, released 2021-02-05) in cmd/crio/main.go to multiplex gRPC and HTTP traffic on a single Unix socket. The library has not received a commit in 5 years, has 26 open issues and 10 open PRs (oldest from 2019) with no maintainer response, and pins a stale golang.org/x/net snapshot from Nov 2020.
This proposes removing it.
Current usage
// cmd/crio/main.go
m := cmux.New(lis)
grpcL := m.MatchWithWriters(cmux.HTTP2MatchHeaderFieldSendSettings("content-type", "application/grpc"))
httpL := m.Match(cmux.HTTP1Fast())
go grpcServer.Serve(grpcL) // CRI v1 Runtime + Image
go httpServer.Serve(httpL) // /info, /config, /containers/:id, /pause/:id, /unpause/:id, /debug/*
go m.Serve()
The metrics server and pprof endpoints already use independent listeners.
Proposal
Option A (recommended): remove cmux, split into two listeners.
- gRPC keeps
/var/run/crio/crio.sock (existing listen key).
- HTTP inspect API gets its own socket via a new
inspect_listen key. Default it to crio.sock initially with a deprecation notice so existing tooling keeps working, then flip the default to a separate socket in a later release.
This matches the design containerd already uses (separate sockets for gRPC, debug, metrics) and the pattern CRI-O's own metrics server uses. Upstream grpc-go explicitly recommends this approach for HTTP-on-the-side endpoints.
Option B (fallback): swap to [elastic/gmux](https://github.com/elastic/gmux). Actively maintained (last release Apr 2026), modern Go and golang.org/x/net, designed specifically for the gRPC+HTTP case. Small refactor in cmd/crio/main.go. Keeps the single-socket behaviour.
Full evaluation of these and other options (cockroachdb/cmux, grpc.ServeHTTP, connect-go) in the design doc linked below.
Acceptance criteria
github.com/soheilhy/cmux removed from go.mod / vendor
- gRPC (CRI v1) and HTTP inspect endpoints continue to function
- Backwards-compatible default for any new config key
- Existing socat-based integration test (
/info through the socket) updated
docs/ / man pages updated if socket configuration changes
References
Summary
CRI-O depends on
github.com/soheilhy/cmux(v0.1.5, released 2021-02-05) incmd/crio/main.goto multiplex gRPC and HTTP traffic on a single Unix socket. The library has not received a commit in 5 years, has 26 open issues and 10 open PRs (oldest from 2019) with no maintainer response, and pins a stalegolang.org/x/netsnapshot from Nov 2020.This proposes removing it.
Current usage
The metrics server and pprof endpoints already use independent listeners.
Proposal
Option A (recommended): remove cmux, split into two listeners.
/var/run/crio/crio.sock(existinglistenkey).inspect_listenkey. Default it tocrio.sockinitially with a deprecation notice so existing tooling keeps working, then flip the default to a separate socket in a later release.This matches the design containerd already uses (separate sockets for gRPC, debug, metrics) and the pattern CRI-O's own metrics server uses. Upstream grpc-go explicitly recommends this approach for HTTP-on-the-side endpoints.
Option B (fallback): swap to
[elastic/gmux](https://github.com/elastic/gmux). Actively maintained (last release Apr 2026), modern Go andgolang.org/x/net, designed specifically for the gRPC+HTTP case. Small refactor incmd/crio/main.go. Keeps the single-socket behaviour.Full evaluation of these and other options (cockroachdb/cmux, grpc.ServeHTTP, connect-go) in the design doc linked below.
Acceptance criteria
github.com/soheilhy/cmuxremoved fromgo.mod/vendor/infothrough the socket) updateddocs// man pages updated if socket configuration changesReferences
https://github.com/soheilhy/cmuxetcd-io/etcd#18032) — etcd evaluating the same migration since May 2024