This release merges the API and SSH services into one server, authorizes SSH by account and access policy, replaces device auto-accept with provisioning keys, and puts the console under a tab strip of namespaces, terminals and recordings.
One server, one gateway
The API and the SSH server now run as one server binary, so they no longer call each other over HTTP (#6764, #6769). The shellhubio/server image replaces shellhubio/api and shellhubio/ssh. The gateway serves the edge from Caddy, built into its binary, in place of nginx and certbot (#6780). It can also serve a certificate you supply through SHELLHUB_TLS_CERT_FILE and SHELLHUB_TLS_KEY_FILE (#6859). static-web-server now serves the console (#6836).
Behind a load balancer?
SHELLHUB_PROXY_TRUSTED_IPSlists the peers allowed to send a PROXY protocol header. The default trusts every peer, as before. Set it to your load balancer's addresses so no other peer can claim a client address. This release also removesSHELLHUB_INTERNAL_HTTP_CLIENT_*andSHELLHUB_RECORD_URL. SSH logs now followSHELLHUB_LOG_FORMAT, which defaults to text.
SSH access by account and policy
A namespace can authorize an SSH login against the account that owns the key, instead of a list of public keys. SSH keys bind to accounts as identities. Access policies decide which members, roles and API keys reach which devices, and under which logins (#6759, #7493). A policy can hold a login until a member approves it in the console or answers a keyboard-interactive prompt in the SSH client (#7153). API keys can hold SSH identities for automation (#7149).
Existing namespaces stay in legacy mode. A namespace created before this release keeps its SSH behaviour and its
TENANT_IDenrollment. An owner can upgrade it to the new mode once, and the upgrade is permanent (#7578). Every namespace created from now on starts in the new mode.
Enroll devices with pairing and provisioning keys
A device no longer needs a tenant ID to enroll. The agent prints a code, and a logged-in member accepts it in the browser (#6482). Provisioning keys are reusable registration credentials with a usage limit, an expiry, tags and an optional webhook that decides the accept (#6677, #7185). In a namespace in the new mode, TENANT_ID enrollment is deprecated and the device lands pending.
The install script checks the server's certificate, the agent version and the binary's release checksum (#7422, #7427). It exits non-zero when the device fails to enroll (#7661).
Upgrading? Provisioning keys replace the namespace-wide device auto-accept setting, which this release removes (#6677). It also removes the pre-authorized pairing code, with the agent's
SHELLHUB_PAIRING_CODEand the installer'sCODE=(#7256).SHELLHUB_REQUIRE_VERIFIED_DEVICE_KEYbecomesSHELLHUB_NAMESPACE_REQUIRE_VERIFIED_DEVICE_KEY. It defaults totrueand applies only to new namespaces. Existing namespaces start with the requirement off (#7615).
A console framed by tabs
The console sits under a tab strip of namespaces, terminals and session recordings, and you can drag tabs into a new order (#7191, #7194, #7195). The web terminal records its sessions, and each recording plays in its own tab. You can download and delete recordings (#6602, #7255). The theme follows the system unless you pick one (#7211), and each terminal theme uses the palette it is named after (#7270). New accounts go through one first-run flow in place of the welcome screens (#7268).
Community Edition runs one namespace
A Community instance now binds to a single namespace, and the console shows an upgrade prompt where it offered to create another (#6624). An existing install with several namespaces keeps all of them. The oldest becomes the bound namespace, and the others keep working until you delete them.
Also in this release
Features
SHELLHUB_SESSION_RETENTION_DAYSprunes session records older than the window. It is off by default (#6888)SHELLHUB_ACCOUNT_LOCKOUT_BASEandSHELLHUB_MAXIMUM_ACCOUNT_LOCKOUTset the login lockout (#7545)SHELLHUB_TUNNEL_PING_INTERVALsets the agent's tunnel ping interval (#7520)SHELLHUB_POSTGRES_EXTERNALandSHELLHUB_NETWORK_EXTERNALrun the stack against an external PostgreSQL or Docker network (#7259)- A session records what it did and who opened it (#7173)
- The observer role has read-only device access (#7118)
- A password change revokes the user's tokens (#7434)
- Every API error answers with a JSON body (#6916, #7156)
- Ctrl +, Ctrl - and Ctrl 0 change the terminal font size (#6937)
- This release removes announcements. The server ignores
SHELLHUB_ANNOUNCEMENTS(#7226)
Fixes
- A device counts as online only while its tunnel beats, and a late heartbeat no longer brings it back (#7613, #7407)
- The server closes a removed device's tunnel, even when another process removed it (#7303)
- The SSH gateway and agent no longer drop bytes or leave sessions open (#6834, #6867)
- SSH signals reach the running command, and SFTP sessions send their exit status (#7423, #7287)
- The agent enforces shadow account expiry on ShellHub logins (#7133)
- Only the owner can read the device private key (#7290)
- The server caps API request bodies and stalled headers (#7634)
- Request logs and Sentry reports redact credentials (#7402)
- Migrations hold a PostgreSQL advisory lock, and each records itself in its own transaction (#7262, #7264)
- The agent builds on FreeBSD again (#7003)
Performance
- The device heartbeat no longer blocks HOT updates, and three unused session indexes are gone (#6883, #6884)
- The server no longer looks up the namespace again on every authenticated request (#6890)
- The console serves the IBM Plex fonts itself (#7480)
Enterprise and Cloud
- Instance-admin API keys reach the admin API (#7021)
- The admin dashboard shows the instance (#7302)
- SSO users can use the console, and admins can edit users created through SAML (#6735, #7354)
- Cloud enforces license checks for devices and SSH (#7579)
Under the hood
- The CLI module moved into the server (#6808)
- Echo v5 (#6878), and more Go linters enabled (#6981, #6985, #6986)
- The testcontainers and end-to-end suites run in containers (#7306)
- Dependency updates across all services, including Go 1.26, Alpine and Node, via Dependabot and Renovate
New Contributors
- @prashantdivate made their first contribution in #6732
Full Changelog: v0.26.0...v0.27.0