Inside ShellHub: March 2026

Developers managing Linux devices remotely via terminal and dashboard interface.
A visual overview of ShellHub updates for March 2026.

Two months ago we laid out a three-phase rollout plan: ship the new React UI on MongoDB, introduce migration tooling, then switch to PostgreSQL. All three phases shipped. v0.22.0, v0.23.0, and v0.24.0 are out — the React frontend is the default interface, PostgreSQL is the default database, and the enterprise architecture was unified along the way. Here's a closer look at what happened.

Highlights

  • The rollout plan is complete. Three releases in two months: v0.22.0 (React UI), v0.23.0 (migration tooling), v0.24.0 (PostgreSQL default). Each earned its way to the next.
  • Enterprise architecture was unified. Cloud and Enterprise features now build as extensions of the core API binary, not separate services. Deployment is simpler, routing is simpler, and transactions work end-to-end.
  • The new UI grew far beyond CE parity. Session recording playback, an encrypted SSH key vault, a migration status dashboard, and a welcome wizard all shipped.

UI: From parity to product

Status: The React UI is now the default at /. The legacy Vue frontend is still available at /v1 but is no longer maintained.

The first edition of this post described a UI that had reached Community Edition feature parity. Since then, the frontend evolved from "everything Vue had" to "things Vue never had."

Secure Vault is a client-side encrypted SSH key store. Keys are encrypted in the browser before they reach the server, and decrypted only at connection time. This means the server never sees your private keys in plaintext — a capability the old UI never offered.

Session recording playback lets you review past terminal sessions as recorded video, with full scrollback and timing preserved. This was an Enterprise feature that existed only as raw data before; now it has a proper player.

Other additions include a welcome onboarding wizard for first-time setups, a migration status page with live progress feedback during the MongoDB-to-PostgreSQL transition, and a namespace creation dialog for Community Edition users.

Under the hood, the entire data-fetching layer was rebuilt. Hand-written API wrappers were replaced with a generated OpenAPI SDK (via hey-api/openapi-ts), and all data fetching now goes through TanStack Query with proper caching, invalidation, and loading states. This alone eliminated entire categories of bugs around stale data and race conditions.

Up next: Now that the major migration is behind us, the focus shifts to polish: fixing rough edges found in production, improving test coverage, and starting work on features that were deferred during the rewrite.

Database: PostgreSQL is the default

Status: PostgreSQL ships as the default database in v0.24.0. The MongoDB-to-PostgreSQL migration pipeline is production-ready with deep validation. Cloud-specific migration is also complete.

The migration story matured significantly. Beyond the store-layer completeness we reported last time, the pipeline now includes:

  • Deep field-by-field validation. After migrating data, the system reads from both MongoDB and PostgreSQL, converts to the same entity structs, and compares every field. Eleven comparators cover all tables including junction tables, processing records in batches of a thousand.
  • Cloud extension points. The migration framework now supports extension hooks so Cloud and Enterprise editions can register their own migration logic. Cloud-specific data (firewall rules, announcements, licenses, tunnels, billing, invitations, web endpoints) migrates through the same pipeline.
  • Live migration status UI. A dedicated page in the new frontend shows real-time progress as data moves from MongoDB to PostgreSQL.
  • Edge case handling. Orphaned MongoDB records, BSON type inconsistencies, and schema mismatches are detected and handled rather than silently dropped.

On the store testing side, a new storetest package with YAML fixtures enables the same tests to run against both MongoDB and PostgreSQL. Coverage now includes sessions, tunnels, public keys, namespace cascading deletes, device cascading deletes, and more.

All PostgreSQL migrations (nine for core, nine for cloud) were squashed into single SQL files per edition, making fresh installs clean and fast.

Up next: Performance benchmarking under production workloads, monitoring the migration path for early adopters, and continuing to expand storetest coverage.

Enterprise architecture: one binary

The most significant architectural change this cycle happened on the enterprise side. Previously, Cloud and Enterprise features ran as a separate service alongside the core API. This meant separate containers, separate routing, and the transaction coordination problem we described in the first edition.

Now, enterprise features build as extensions of the core API binary. The API server was extracted into an importable app package. Enterprise code registers additional routes, billing logic, and background workers through an extension system. At runtime, it's a single container serving everything.

This change simplifies deployment (one fewer container to manage), eliminates the routing complexity of having two services behind a gateway, and — most importantly — makes the transaction wrapping we built for PostgreSQL actually work end-to-end. When enterprise code extends a community operation inside a transaction, it's the same connection, the same transaction, the same atomic guarantee.

Releases

Three releases shipped, each with multiple release candidates:

  • v0.22.0 — New React UI on MongoDB. The Vue frontend moves to /v1.
  • v0.23.0 — Migration tooling: the MongoDB-to-PostgreSQL pipeline with deep validation and live status UI. Four release candidates.
  • v0.24.0 — PostgreSQL as the default database. Fresh installs skip MongoDB entirely.

Other updates

  • Go 1.25. The entire backend was bumped from Go 1.24 to 1.25.8, and golangci-lint from v2.1.6 to v2.11.3.
  • Agent improvements. Keepalive handling was fixed (agent now sets WantReply=true), PTY window change deadlocks were resolved with a drain pattern, and the standalone runc dependency was replaced with a native static binary.
  • WebSocket stability. Race conditions in the WebSocket adapter were fixed with sync.Once and concurrency-safe ping handling.
  • OpenAPI spec. Missing fields, required annotations, and the X-Total-Count header were added to all paginated endpoints. The spec is now served dynamically based on edition (community vs. enterprise).
  • License enforcement at SSH connection time. Device limits are now checked when an SSH connection is established, not just at registration.
  • CI improvements. A multi-agent PR review workflow, cross-repo enterprise validation, and a verify-fix workflow for TDD-style PRs were added.

AI as a force multiplier

Last edition we described AI-assisted development in general terms. Two months in, some patterns have sharpened.

The storetest package is a good example. Writing YAML fixture files, comparator functions, and test cases across eleven entity types is precisely the kind of work where AI shines: repetitive enough to benefit from generation, specific enough to need human review. The pattern was designed by hand, the first comparator was written by hand, and then AI helped replicate it across the remaining ten — each one reviewed and adjusted.

The OpenAPI SDK migration followed a similar pattern. Replacing dozens of hand-written API wrappers with generated code required touching nearly every data-fetching call in the frontend. AI handled the mechanical translation while we focused on the TanStack Query integration patterns and cache invalidation strategy.

The enterprise unification was the opposite: almost entirely human-driven. Architectural decisions about how extensions register, how billing is injected, and how routing is simplified required understanding the full system. AI contributed to code review and catching inconsistencies, but the design was human.

The takeaway: AI is most valuable when the pattern is clear and the volume is high. It's least valuable when the work is fundamentally about design decisions. Knowing where each tool fits is what makes a small team productive.

Get involved

ShellHub is open source and we welcome contributions at any level: code, bug reports, documentation, or just feedback.