Skip to content

feat(permissions): add server.terminal to decouple server access from root SSH - #5142

Open
narcisonunez wants to merge 1 commit into
canaryfrom
feat/add-terminal-permission
Open

feat(permissions): add server.terminal to decouple server access from root SSH#5142
narcisonunez wants to merge 1 commit into
canaryfrom
feat/add-terminal-permission

Conversation

@narcisonunez

@narcisonunez narcisonunez commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Reaching a server implied being able to open an SSH root shell on it: the /terminal websocket only checked that the server was in the caller's accessible set, so granting a server to a developer necessarily granted root on it.

Add a server.terminal action, assignable on custom roles, and require it on the remote-server terminal websocket on top of server access. Owner/admin keep it through the enterprise bypass; the local host terminal stays owner/admin only.

A migration grants server.terminal to existing custom roles that already have server.read, which is the permission that surfaces the terminal today, so current setups keep working. Roles without a server entry are left alone.

What is this PR about?

Please describe in a short paragraph what this PR is about.

Checklist

Before submitting this PR, please make sure that:

  • You created a dedicated branch based on the canary branch.
  • You have read the suggestions in the CONTRIBUTING.md file https://github.com/Dokploy/dokploy/blob/canary/CONTRIBUTING.md#pull-request
  • You have tested this PR in your local instance. If you have not tested it yet, please do so before submitting. This helps avoid wasting maintainers' time reviewing code that has not been verified by you.

Issues related (if applicable)

Screenshots (if applicable)

Greptile Summary

This PR introduces a separate server.terminal permission and enforces it for remote host-terminal WebSockets while preserving the owner/admin-only local terminal.

  • Adds the new action to access-control declarations, custom-role management, and frontend visibility checks.
  • Migrates existing custom roles with server.read and adds permission and WebSocket authorization tests.
  • Leaves built-in free-tier members without a compatibility grant, breaking their existing remote-terminal access.

Confidence Score: 4/5

The existing remote-terminal access regression for built-in free-tier members should be fixed before merging.

The new WebSocket check requires server.terminal, but non-licensed built-in members previously received access to all organization servers and have no role grant, legacy override, or custom-role path that can satisfy the new permission.

Files Needing Attention: apps/dokploy/server/wss/authorize.ts, packages/server/src/lib/access-control.ts, and apps/dokploy/drizzle/0186_grant-server-terminal-permission.sql

Reviews (1): Last reviewed commit: "feat(permissions): add server.terminal t..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Context used:

@narcisonunez
narcisonunez force-pushed the feat/add-terminal-permission branch from 5aa9c25 to b8cb7fa Compare August 21, 2026 14:43
… root SSH

Reaching a server implied being able to open an SSH root shell on it: the
/terminal websocket only checked that the server was in the caller's accessible
set, so granting a server to a developer necessarily granted root on it.

Add a server.terminal action, assignable on custom roles, and require it on the
remote-server terminal websocket on top of server access. Owner/admin keep it
through the enterprise bypass; the local host terminal stays owner/admin only.

A migration grants server.terminal to existing custom roles that already have
server.read, which is the permission that surfaces the terminal today, so
current setups keep working. Roles without a server entry are left alone.

Note: server.create still implies root execution (server.update persists
server.command and server.setup runs it over SSH), reflected in the Create
description in the role editor.
@narcisonunez
narcisonunez force-pushed the feat/add-terminal-permission branch from b8cb7fa to bbde5eb Compare August 21, 2026 15:08
@narcisonunez
narcisonunez marked this pull request as ready for review August 21, 2026 19:52
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Aug 21, 2026
Comment on lines +81 to +83
return await hasPermission(buildCtx(user, session.activeOrganizationId), {
server: ["terminal"],
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Built-in members lose terminal access

When a built-in member in an organization without an enterprise license opens a remote terminal, this new check denies access because the member role has no server.terminal grant or legacy override. These members previously received access to all organization servers, and the migration updates only custom roles, so upgrading removes their remote-terminal access with no way to restore it.

Knowledge Base Used:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant