Inject OneDev agent hostname and port mappings into Workspace #2928
Jake Ceballos opened 3 days ago

I have a 3rd party tool running within a Workspace container that I'm trying to access through the Workspace port mappings. For security, the tool can only be accessed if the hostname and port used to access it are specified when launching the 3rd party tool (e.g. tool --allowed-origins=https://HOSTNAME:PORT).

The problem that I am facing from within a Workspace is that I don't have a reference to the OneDev assigned Workspace port mappings. Without a reference to the assigned ports, I don't have a way to allow access to it.

Can these be passed as environment variables to the Workspace?

image.png

  • Zak Siddiqui commented 3 days ago

    @servicedesk

    Help us clarify this issue.

    Don't assume. Ask @jakeceballos high-level clarifying questions if needed.

    • Numbered questions (1, 2, 3, etc)
    • Lettered answer options (A, B, C, etc)
    • Pros and Cons? Your recommendation?
  • Service Desk commented 3 days ago

    @jakeceballos

    To clarify how we should expose workspace port mappings for your use case, please answer the questions below:

    1. What does your 3rd-party tool need for --allowed-origins (or equivalent)? A. The public hostname only (for example the host used in Port Mappings) B. Hostname + mapped host port (for example https://HOSTNAME:55011) C. A full origin URL matching what you get when opening a Port Mappings link D. Something else — please describe

    2. How many exposed ports does the tool need to allow? A. A single primary port B. Multiple ports (as in your screenshot: 4000 -> 55011, 9832 -> 55012) C. Dynamic / varies per workspace

    3. When do you need the mapping available inside the workspace? A. At process start as environment variables (so the launch command can use them immediately) B. Shortly after the workspace is ready (for example a file written into the workspace that a startup script can read) C. Either works

      Notes:

      • Today OneDev assigns random host ports after the container starts (docker -P), so those host ports are not known at container start time.
      • Option A may require changing how ports are published (pre-allocate host ports before start).
      • Option B fits the current design more easily.
    4. Which host name should be used for external access? A. The Port Mappings host (the agent/node host used in the UI links) B. The OneDev server host (ONEDEV_SERVER_URL / @server_host@) C. Not sure — whichever matches the URL you get when clicking Port Mappings

    Recommendation: Based on your description (tool --allowed-origins=https://HOSTNAME:PORT), I recommend 1B and 3B (or 3A if you must have true env vars at start): expose the Port Mappings host plus each mapped host port in a form your startup script can consume once mappings are known. If you need real environment variables before the tool starts, we would likely need to pre-allocate host ports instead of relying on Docker’s random -P assignment.

    Please reply with your choices (for example 1B, 2B, 3A, 4A) and any extra detail about the tool’s constraints.

  • Jake Ceballos commented 2 days ago

    @servicedesk

    1. Option B; the tool requires that I specify a complete origin URL. The agent hostname I have from the Workspace environment variable. All I'm missing is the mapped port.
    2. Option A; the tool listens on a single port. It can accept multiple allowed origins, but it has to match what I use in the browser URL to access (e.g. tool --allowed-origins=[http://localhost:55012, http://localhost:38273]). For this specific use case I only need the port mapping for 9832. But it may be good to include all port mappings for other use cases.
    3. Option B; prefer environment variables over file parsing.
    4. Option A;
  • Service Desk commented 2 days ago

    @jakeceballos

    Thanks — your answers make the requirement clear:

    • Need a complete origin URL: http(s)://<port-mappings-host>:<mapped-host-port>
    • Primary case is one exposed port (9832 in your screenshot); exposing all mappings is still useful
    • Prefer environment variables over file parsing
    • Use the Port Mappings host (not the OneDev server host)

    One technical constraint: today host ports are assigned only after the workspace container starts (docker -P), and Docker cannot update the environment of an already-running container. So true environment variables are only possible if we pre-allocate host ports before start.

    Please pick the delivery form you want:

    1. Pre-allocate host ports and inject real env vars at container start (matches your preference for environment variables) Example:
      • ONEDEV_PORT_HOST=<port-mappings-host>
      • ONEDEV_PORT_<containerPort>=<mappedHostPort> for each exposed port (e.g. ONEDEV_PORT_9832=55012)
    2. Keep random port assignment, and shortly after the workspace is ready write a small env-style file you can source (same variable names as above)

    Also: you mentioned you already have the agent hostname from a workspace environment variable. What is the exact variable name? That helps us align with what you already use.

    Recommendation: option 1, so you can launch with something like: tool --allowed-origins=http://$ONEDEV_PORT_HOST:$ONEDEV_PORT_9832 without parsing a file.

  • Jake Ceballos commented 2 days ago

    @servicedesk

    I think option 2 with random assignment is the way to go. I may have many Workspaces running on the same agent host. It would be cumbersome and difficult to coordinate port assignment to make sure Workspaces don't clash/overlap. To overcome the technical constraint related to modifying the container environment, a file written into the container will suffice. But the file must exist before my container entrypoint script runs so that the environment variables are available during start up.

    The agent hostname appears as an environment variable inside the Workspace container as HOSTNAME. I assume this was OneDev injecting the Agent's name/hostname.

  • Service Desk commented 2 days ago

    @jakeceballos

    Thanks — option 2 (random host ports + a file) is clear. There is one hard Docker constraint on your “file must exist before my container entrypoint runs” requirement:

    • With random -P publishing, host ports are only assigned when the container starts.
    • The container entrypoint also starts at that moment.
    • Docker cannot update the environment of a running container, and the mapped ports are not known early enough to write the file before any entrypoint process begins.

    So “pure random -P” and “file already present before entrypoint starts” cannot both be true.

    Please pick one of these workable designs:

    1. OneDev picks free host ports up front (still automatic — you do not coordinate ports across workspaces), writes an env-style file into the mounted workspace directory, then starts the container

      • Pros: file exists before your entrypoint; no file parsing race; no clash risk if OneDev allocates free ports
      • Cons: not Docker’s -P randomness (OneDev chooses free ports instead)
    2. Keep Docker random -P, and have OneDev’s workspace entrypoint wait briefly for the port-mapping file (written to the mounted workspace volume right after start), then continue into your startup/tool launch

      • Pros: keeps today’s random assignment model
      • Cons: the file appears a moment after process start; your script must run under OneDev’s entrypoint flow (or tolerate a short wait/source once the file appears)

    Also on HOSTNAME: inside a Docker workspace that is usually the container hostname (often the short container id), not reliably the Port Mappings host shown in the UI. We should still expose an explicit host variable (for example ONEDEV_PORT_HOST) matching the Port Mappings links, plus per-port vars such as ONEDEV_PORT_9832=<mappedHostPort>.

    Recommendation: option 1 — it meets “available at startup” without asking you to manage port clashes.

    Which do you prefer: 1 or 2?

  • Jake Ceballos commented 2 days ago

    @servicedesk

    Option 1 seems like it might be the way to go.

    You're right about the HOSTNAME, I misread and thought I was seeing the Agent container's hostname. But it is indeed the Workspace's container hostname, so I'll need the Agent hostname also included with the port mappings.

    For the proposed variable names, I liked having it prefixed with WORKSPACE so that it was easy to distinguish from Workspace info vs. Server info (e.g. ONEDEV_SERVER_URL). Using ONEDEV_PORT_HOST could be mistaken for the OneDev Server port. WORKSPACE_PORT_9832 implies its specific to the Workspace. For the hostname I like WORKSPACE_AGENT_HOST.

  • Service Desk commented 2 days ago

    @jakeceballos

    Thanks — locking this in with your naming preferences:

    Delivery

    1. OneDev allocates free host ports for each exposed container port before start (automatic; you do not coordinate ports across workspaces on the same agent)
    2. Writes a sourceable env-style file into the mounted workspace directory before the container starts
    3. Starts the container so your entrypoint can source the file immediately

    Variables in that file

    • WORKSPACE_AGENT_HOST — the Port Mappings host (same host used in the UI links)
    • WORKSPACE_PORT_<containerPort> — mapped host port for each exposed port (e.g. WORKSPACE_PORT_9832=55012; all exposed ports included)

    Example

    tool --allowed-origins=http://$WORKSPACE_AGENT_HOST:$WORKSPACE_PORT_9832
    

    Unless you want a specific path/name for that env file, this is enough to implement.

  • Jake Ceballos commented 2 days ago

    @servicedesk proposed implementation looks good to me.

  • Service Desk commented 2 days ago

    @robin @jakeceballos

    The agreed design is ready to implement (pre-allocate free host ports, write a sourceable env file with WORKSPACE_AGENT_HOST / WORKSPACE_PORT_<containerPort> before container start), but I do not have permission to write code in onedev/server, so I cannot create the issue branch or land the change myself.

    Please take it from here for implementation.

  • Zak Siddiqui commented 2 days ago

    @servicedesk please create a fresh issue based on the agreed design and close this one.

    Add watchers of this issue to be watchers of the new issue.

  • Service Desk commented 2 days ago

    @zaakiy Created issue #2931 from the agreed design (pre-allocate free host ports; write a sourceable env file with WORKSPACE_AGENT_HOST / WORKSPACE_PORT_<containerPort> before container start), linked it as Related, and added this issue's watchers on the new issue. Closing this one.

  • Service Desk commented 2 days ago

    @zaakiy I don't have permission to transition this issue to Closed. Please close it when convenient (implementation continues on issue #2931).

  • Zak Siddiqui commented 2 days ago
  • Robin Shen changed state to 'Closed' 13 hours ago
    Previous Value Current Value
    Open
    Closed
1/1
Type
Improvement
Priority
Normal
Assignee
Labels
No labels
Issue Votes (0)
Watchers (4)
Reference
OD-2928
Please wait...
Connection lost or session expired, reload to recover
Page is in error, reload to recover