Use external editor like VSCode with an Workspace #2765
Vitor Carvalho opened 3 months ago

Hi,

I would like to know if it is possible to connect VSCode to an existing and active Workspace, which means, using the remote controller to access files in the workspace and run the LLM model agent/session - essentially, using VSCode as a UI interface for the Workspace. GitHub already allows this with their Codespaces feature (they even have a "Open with VS Code" button.

If not, do you foresee this being implemented soon?

Thank you.

  • Robin Shen commented 3 months ago

    This is an interesting idea. Will explore this in future versions, but no schedule for that yet.

  • Robin Shen changed fields 3 months ago
    Name Previous Value Current Value
    Type
    Question
    New Feature
  • Zak Siddiqui commented 2 weeks ago

    Oh boy, I'd love to tackle this with the help of AI of course.

    Many years ago I tried to integrate GitPod into self-hosted GitLab without any success.

    But I certainly learned a lot of lessons about what is possible.

  • Zak Siddiqui commented 2 weeks ago

    @servicedesk Please raise the following with @robin, or initiate, according to your rules. It may be more appropriate to create this as a clean issue once the questions are answered.

    Architecture Question: How to implement a browser-based VS Code (Web IDE) hosted via Docker Job Executors?

    Context & Motivation

    Modern Git platforms (like GitHub Codespaces and GitLab Web IDE) offer seamless, browser-based VS Code environments. I would like to propose and design a similar feature for OneDev, expanding on the concepts discussed in OD-2765 (External editor/Workspace support).

    Core Architectural Constraint

    To maintain the security, stability, and lightweight nature of the core OneDev server, the Web IDE environment must NOT be hosted on the OneDev server itself. Instead, it should be spun up and managed as a specialized, long-running interactive job on a Docker Job Executor.

    This approach leverages OneDev's existing executor infrastructure, ensures strict environment isolation per user/repository, and prevents heavy IDE workloads from impacting the core application.

    Question for the AI Agent:

    Based on OneDev's current codebase and architecture, how should we design and implement this feature? Please provide a comprehensive architectural plan and identify the specific OneDev classes, interfaces, and modules that would need to be modified or created.

    Specifically, please address the following technical challenges:

    1. Job Modeling & Lifecycle Management

      • How can we extend OneDev's job execution framework to support a new WEB_IDE job type (distinct from standard CI/CD jobs)?
      • Standard CI jobs have strict timeouts and run to completion. How should we handle long-running, interactive sessions (e.g., idle timeouts, manual termination by the user, and graceful shutdown of the container)?
      • Which existing executor classes/interfaces need modification to support persistent, interactive Docker containers rather than ephemeral build containers?
    2. Networking & Reverse Proxying

      • VS Code in the browser (via openvscode-server or code-server) requires heavy WebSocket usage and dynamic port exposure.
      • How can the OneDev server act as a reverse proxy to route the user's browser traffic to the specific Docker container running on the remote executor node?
      • Please outline how to handle WebSocket upgrades and dynamic port mapping within OneDev's current web server/proxy configuration.
    3. Security & Authentication

      • How do we securely pass OneDev user credentials/Git tokens into the container so the user can pull/push without re-authenticating?
      • How do we ensure the proxied Web IDE URL is strictly protected by OneDev's existing authentication and authorization (e.g., ensuring only users with READ or WRITE access to the repository can access the IDE)?
    4. UI & State Integration

      • Where in the OneDev UI (e.g., repository file browser, branch dropdown) should the "Open in Web IDE" entry point be placed?
      • How should OneDev track the state of active Web IDE sessions so a user can reconnect to an existing workspace rather than spinning up a new one?
    5. Technology Selection

      • Between Gitpod's openvscode-server and Coder's code-server, which is better suited for this specific Docker-executor-managed architecture, and why? (Consider factors like upstream VS Code parity, extension compatibility, and ease of headless configuration).

    Expected Output from AI

    1. A high-level architectural diagram/flow of how the request travels from the OneDev UI to the Executor and back.
    2. A list of specific OneDev Java classes/packages that will need to be modified.
    3. A proposed database schema change (if any) to track active Web IDE sessions.
    4. A step-by-step implementation roadmap for a developer to start building this feature.
  • Service Desk commented 2 weeks ago

    @zaakiy Thanks for the detailed architecture questions. I investigated the current codebase/docs; summary below. Flagging @robin for product direction on whether/when to pursue this (and whether to spin a dedicated feature issue).

    Recommendation: build on Workspaces, not CI Job Executors

    A new WEB_IDE job type on Docker Job Executors is the wrong substrate. CI jobs (Job / JobExecutor / DefaultJobService) are batch-oriented: they have timeouts (default 14400s), run steps to completion, then tear down. Job services are sidecar containers reachable only by Docker-network DNS — they are not browser-routed.

    OneDev already has a first-class Workspace subsystem for long-running, interactive, Docker-isolated environments:

    ConcernAlready covered by Workspaces
    Long-lived containerWorkspace lifecycle PENDING → ACTIVE → INACTIVE via WorkspaceService / WorkspaceProvisioner
    Docker isolation off the “job” pathServerDockerProvisioner (CE); EE also has remote/agent and K8s provisioners
    Git auth inside containerWorkspace token (Workspace.setToken) + DefaultCloneInfo / @workspace_token@
    Exposed HTTP portsWorkspaceSpec.containerPorts + Docker -PWorkspaceRuntime.getPortMappings()
    UI entry pointsBlob page, branches/tags, PRs, Workspaces tab, WorkspaceDetailPage
    Auth for API/Git as userBearerAuthenticationFilter already resolves workspace tokens to the owner’s subject

    Docs already steer heavy interactive work toward workspaces (and EE remote/K8s provisioners to offload the server): Working with Workspaces.

    So the feature should be: “Web IDE workspace template + authenticated reverse proxy”, not a new job type.


    High-level flow

    User (blob/branch/PR UI)
      → "Open in Web IDE"
      → WorkspaceService.create(spec=web-ide, branch/commit)
      → WorkspaceProvisioner (Docker/agent/K8s)
      → Container: openvscode-server (or code-server)
           ├─ git clone via workspace token
           └─ listens on container port (e.g. 3000)
      → Browser
           ├─ MVP: http://<executor-host>:<mapped-port>  (existing port menu)
           └─ Target: https://onedev/.../~workspaces/<n>/ide/**
                → new authenticated reverse proxy (HTTP + WebSocket)
    

    Answers to the technical challenges

    1. Job modeling & lifecycle → use Workspace lifecycle

    • Do not extend Job / JobExecutor for this.
    • Model as a WorkspaceSpec (image, runInContainer, containerPorts, startup via entrypoint or ShortcutConfig, env vars).
    • Lifecycle already exists on io.onedev.server.model.Workspace + DefaultWorkspaceService (create, activate, cancel/stop → INACTIVE, reconnect while ACTIVE).
    • Gaps vs Codespaces-style UX:
      • No built-in idle timeout today (container runs until process exits / user stops it) — add idle detection later (proxy activity or workspace heartbeat).
      • Manual terminate already fits “stop workspace”.
    • Executor classes to reuse (not redesign as jobs): WorkspaceProvisioner, ServerDockerProvisioner, and EE remote/K8s provisioners — not ServerDockerExecutor / RemoteDockerExecutor.

    2. Networking & reverse proxying

    Today: workspaces publish ports with Docker -P; UI builds direct links http://{portHost}:{hostPort} in WorkspaceDetailPage (no OneDev-origin proxy, no session auth on that URL).

    Needed for a proper Web IDE:

    1. New reverse-proxy route (e.g. {project}/~workspaces/{number}/ide/**) mounted via BaseUrlMapper / a dedicated servlet or Jetty ProxyServlet.
    2. Proxy must support HTTP + WebSocket upgrade (VS Code Web uses many WS channels) — far beyond the existing tmux-oriented TerminalPanel.
    3. Resolve target from WorkspaceService.getPortMappings(workspace) + getPortHost(workspace) (or pin a known IDE port in the spec).
    4. Prefer path-based proxy under the OneDev origin (cookies/SSO, fewer CORS issues) over exposing raw host ports publicly.

    Job-executor networking does not help here: CI services never get browser ingress.

    3. Security & authentication

    NeedExisting mechanism
    Git pull/push in containerWorkspace token as clone credential (same pattern as today)
    API calls as workspace userBearerAuthenticationFilter already binds workspace token → owner
    Who may open IDEReuse CreateWorkspaces / SecurityUtils.canModifyOrDelete(workspace) (and project code read/write as appropriate)

    New work: the reverse proxy must gate every request/upgrade with the Shiro web session (or a short-lived IDE-scoped token). Do not rely on obscure host ports as security. Optional: inject/workspace-bind auth into the IDE if the chosen server supports a connection token.

    4. UI & state integration

    Natural entry points (already used for workspace creation):

    • ProjectBlobPage, ProjectBranchesPage / tags, PullRequestDetailPage, Workspaces nav
    • GetCodePanel already has a local vscode:// clone deeplink — different feature (local VS Code), keep it; add a separate “Open in Web IDE” action

    Session tracking: Workspace entity already is the session record (user, project, branch, commit, status, provisioner, agent/server). List/reconnect = existing workspace list filtered to active Web IDE specs. No separate “IDE session” table is required for an MVP.

    5. Technology selection: openvscode-server vs code-server

    For a Docker-provisioner-managed workspace, prefer Gitpod openvscode-server:

    • Closer upstream VS Code parity / extension model
    • Designed for headless / server deployments
    • Clean fit as a workspace image entrypoint listening on a single HTTP port

    Coder code-server remains a valid alternative (mature, widely used) if you need its specific auth/config story; functionally either works as WorkspaceSpec.image + exposed port. Product choice can be a preset template; architecture should not hard-depend on one binary.


    Classes / packages to touch (implementation map)

    AreaTouch points
    Spec / templateWorkspaceSpec, new WorkspaceSpecTemplate (e.g. Web IDE), project workspace settings UI
    ProvisioningServerDockerProvisioner (and EE remote/K8s provisioners for scale-out)
    ServiceDefaultWorkspaceService, WorkspaceRuntime (port host/mappings; optional idle timeout)
    Proxy (new)New servlet/filter + BaseUrlMapper mount; WS-capable reverse proxy
    SecurityShiro check in proxy; optionally extend token handling
    UI“Open in Web IDE” on blob/branch/PR; optional IDE page/iframe wrapper; enhance WorkspaceDetailPage
    PersistenceMostly reuse Workspace; optional fields: idle timeout, preferred IDE container port

    Database schema

    MVP: no schema change — reuse Workspace.

    Later (optional):

    • idle timeout / last-activity timestamp
    • flagged “webIde” / preferred container port (or keep that only in WorkspaceSpec)

    Suggested implementation roadmap

    1. MVP (config only): WorkspaceSpec template image = openvscode-server (or code-server), containerPorts: [3000], document using existing port-mapping menu. Validates UX with almost no core changes.
    2. Authenticated reverse proxy under OneDev origin (HTTP + WebSocket).
    3. UI: “Open in Web IDE” entry points + reconnect to existing ACTIVE workspace.
    4. Hardening: idle timeout, concurrency limits (provisioner settings), TLS/public URL behavior for mapped ports.
    5. Scale-out: ensure proxy works with EE remote agent / K8s provisioners (routing to the node that hosts the container).

    Relation to the original request

    The original ask (local VS Code attached to a live workspace, Codespaces-style) is related but not identical to an in-browser IDE. Local VS Code would additionally need a remote-SSH / tunnel / vscode-remote style bridge into the workspace container. The workspace + port/proxy foundation above is still the right base; a browser IDE is the shorter path to “edit in a full VS Code UI without installing anything.”


    @zaakiy — does this architectural direction answer your questions, or do you want a dedicated feature issue opened from this plan? Any strong preference for browser IDE vs local VS Code attach first?

  • Zak Siddiqui commented 2 weeks ago

    @servicedesk I think that looks good. It should be browser IDE only and not local VS Code, attach via remote SSH.

    I like the idea of proxying through the OneDev server. Consider if there is any CORS implementation required if we are proxying through the OneDev server.

    Between the available options, code-server, openvscode-server, etc, which project is most dedicated to free-and-open source and is the least likely to be gating its product behind a pay wall in the future based on what they have published about their principles?

  • Service Desk commented 2 weeks ago

    @zaakiy Thanks — noted: browser Web IDE only (no local VS Code / remote-SSH attach).

    CORS when proxying through OneDev

    For a path-based reverse proxy under the OneDev origin (e.g. {project}/~workspaces/{n}/ide/**), a dedicated CORS layer is generally not required for the IDE itself:

    • The browser treats the IDE HTML/JS/CSS and its WebSockets as same-origin with OneDev, so the same-origin policy applies and CORS preflights are not triggered for those requests.
    • What does matter for the proxy: HTTP + WebSocket upgrade, correct Host / X-Forwarded-* headers, and a stable base path so asset URLs and WS endpoints stay under the OneDev path.

    CORS (or related cross-origin concerns) would mainly show up if we broke that model, e.g.:

    • linking users to raw http://executor-host:mapped-port while the OneDev UI is on another origin
    • embedding the IDE in an iframe across different origins
    • relying on browser calls from the OneDev page to a different IDE origin

    Third-party extension marketplace / CDN calls from the IDE are separate (those origins are outside OneDev); they are governed by the IDE/marketplace, not by OneDev adding CORS on the proxy. Prefer keeping the IDE fully same-origin via the proxy so OneDev session auth stays the gate.

    FOSS / paywall risk: code-server vs openvscode-server

    Both are MIT. On published principles and “won’t gate the IDE binary behind a paywall,” coder/code-server is the safer default:

    code-server (Coder)openvscode-server (Gitpod / Ona)
    LicenseMITMIT
    Stated modelFree self-hosted IDE; Coder’s commercial product is a separate platform (coder/coder)Minimal fork to run VS Code in the browser; tied to Gitpod’s product history
    Marketplace stanceDefaults to Open VSX (explicitly avoiding Microsoft Marketplace ToS issues)Oriented toward Microsoft Marketplace (ToS risk for non-Microsoft products)
    Maintainer trajectoryLong-lived free project with commercial upsell around workspaces, not the IDE binaryGitpod → Ona rebrand; Ona/Gitpod acquisition activity under OpenAI increases maintenance/priority uncertainty for the open side project

    Recommendation for OneDev: treat code-server as the default Web IDE image for FOSS durability and subpath-friendly self-hosting (--base-path, built-in proxy helpers). Keep the architecture image-agnostic so openvscode-server (or others) can still be a template option.

    If this direction works for you, next step is a dedicated feature issue (workspace Web IDE template + authenticated OneDev reverse proxy) rather than expanding this thread further. Want me to open that?

  • Zak Siddiqui commented 2 weeks ago

    If this direction works for you, next step is a dedicated feature issue (workspace Web IDE template + authenticated OneDev reverse proxy) rather than expanding this thread further. Want me to open that?

    @servicedesk yes please

  • Service Desk commented 2 weeks ago

    @zaakiy Opened dedicated feature issue OD-2883 for the agreed plan: workspace Web IDE template (code-server default) + authenticated OneDev reverse proxy (browser IDE only).

    I don't have permission to add the Related link from here — @robin please link OD-2883 as Related to this issue if that fits.

  • Robin Shen commented 2 weeks ago

    This is duplicated by OD-2883

  • Robin Shen changed state to 'Closed' 2 weeks ago
    Previous Value Current Value
    Open
    Closed
1/1
Type
New Feature
Priority
Normal
Assignee
Labels
No labels
Issue Votes (0)
Watchers (5)
Reference
OD-2765
Please wait...
Connection lost or session expired, reload to recover
Page is in error, reload to recover