Inspect a study over SSH
Inspect DICOM files on a remote machine without copying them to a third-party viewer or exposing the server on the network.
Prerequisites
Section titled “Prerequisites”dcmviewis installed on the remote machine that can read the DICOM files.- You can connect to that machine with SSH.
- A chosen port is available on both machines, or you can adapt the forwarding command.
Start the remote viewer
Section titled “Start the remote viewer”On the remote machine, choose a fixed loopback port so the forwarding command is predictable:
dcmview --no-browser --host 127.0.0.1 --port 8888 /path/to/studyWait for the startup message:
dcmview: (on a remote server? run on your local machine: ssh -L 8888:localhost:8888 user@host)dcmview: then open http://localhost:8888/#token=<session-token>dcmview: server running at http://127.0.0.1:8888/#token=<session-token>dcmview: press Ctrl+C to stopThe #token=… fragment is this session’s access token. Every API request needs it, so the bare address without the fragment does not load the study. Treat the printed links as credentials.
The server remains bound to the remote loopback interface. Do not replace the host with 0.0.0.0 for this workflow: the token does not encrypt anything, so over plain HTTP on a network interface the token and the DICOM data are readable in transit.
Forward the port
Section titled “Forward the port”On your local machine, open a second terminal and run the printed command, replacing user@host with your SSH destination:
ssh -L 8888:localhost:8888 user@remote-serverKeep the SSH session open, then copy the then open link from the remote terminal into your local browser, with its #token=… fragment:
http://localhost:8888/#token=<session-token>The browser connects to the local end of the tunnel, SSH carries requests to the remote loopback server, and DICOM files remain on the remote machine. The viewer removes the token from the address bar once the page has loaded and keeps it for that tab, so reloading the tab still works.
Run the forwarding command on your own machine, not on the remote server. dcmview no longer offers the --tunnel options that tried to start forwarding from the serving machine.
Use an automatically assigned viewer port
Section titled “Use an automatically assigned viewer port”Omit --port when a fixed remote port is inconvenient:
dcmview --no-browser /path/to/studyThe printed ssh -L hint and then open link already contain the assigned port. For example, if dcmview binds port 43127:
ssh -L 43127:localhost:43127 user@remote-serverThen open the printed http://localhost:43127/#token=… link.
Use a private Unix socket on a shared server
Section titled “Use a private Unix socket on a shared server”A loopback port can be reached by every account on the remote machine. The access token keeps those accounts out of the API, but on Linux and macOS you can also stop them from connecting at all by serving the viewer through a Unix domain socket:
dcmview --unix-socket ~/dcmview/scan.sock /path/to/studydcmview: listening on /home/alice/dcmview/scan.sockdcmview: on your local machine run: ssh -L 8080:/home/alice/dcmview/scan.sock user@hostdcmview: then open http://localhost:8080/#token=<session-token>dcmview: press Ctrl+C to stopOn your local machine, run the printed command with your SSH destination, then open the printed link with its #token=… fragment:
ssh -L 8080:/home/alice/dcmview/scan.sock user@remote-serverYou can choose another local port; change it in both the command and the link.
Rules for the socket path:
- Give an explicit path. There is no default socket location.
- Directory. The socket’s directory must be owned by your account and must not be writable by group or others. If it is missing,
dcmviewcreates that one directory with mode0700; its own parent must already exist. An unsafe directory is refused before anything in it is touched. - Permissions. The socket is created with mode
0600, and a connection from another user ID is dropped. - Lock file. A
scan.sock.lockfile beside the socket is held while the viewer runs, so a second launch on the same path reports that the socket is already in use instead of replacing it. The directory needs a filesystem that supports file locks. Some network filesystems do not; use a local directory such as one under$XDG_RUNTIME_DIR. - Existing entries. A regular file, symlink, or other non-socket entry at the path is refused and left untouched. A stale socket left by a forced kill is replaced by the next launch on that path.
- Cleanup. The socket and its lock file are removed when the viewer shuts down.
Socket mode has these limits:
- It needs OpenSSH 6.7 or newer on both ends to forward a Unix socket.
- It is available on Linux and macOS only. Windows builds reject the option.
- It is not available from Python
view()or in the VS Code extension, and adcmview --unix-socketcommand in a VS Code terminal always runs the local viewer instead of opening a webview. - It conflicts with
--hostand--port, and it never opens a browser, with or without--no-browser. - The access token is still required. The socket limits who can connect; it does not replace the token.
Limit unattended sessions
Section titled “Limit unattended sessions”Add --timeout to stop a forgotten viewer. The idle clock starts only after the scan finishes, so a long scan of a large directory does not count against it:
dcmview --no-browser --port 8888 --timeout 1800 /path/to/studyUse a reverse proxy
Section titled “Use a reverse proxy”The viewer loads its assets and API with page-relative URLs, so it also works behind a reverse proxy that serves it under a path prefix, such as a Jupyter server proxy route. The proxy must strip the prefix before forwarding and serve the page with a trailing slash, such as .../8888/. Append the #token=… fragment of the printed link to the proxied address so the viewer can authenticate. The proxy must pass the Authorization header through unchanged; if it uses that header for its own login, such as HTTP Basic authentication, start dcmview with --no-token instead.
If the proxy already authenticates every request, you can start dcmview with --no-token to turn the token check off. dcmview prints a warning, because in that mode anything that can reach the listener directly can use the API.
Shut down cleanly
Section titled “Shut down cleanly”Press Ctrl+C in the remote dcmview terminal, then close the SSH forwarding session. The temporary server, its token, and in-memory state are removed.
Troubleshoot the tunnel
Section titled “Troubleshoot the tunnel”- If the page says This viewer needs its access link, you opened the address without the
#token=…fragment. Paste the full printed link into the same tab. - If the page says The viewer restarted, the tab belongs to an earlier
dcmviewprocess. Paste the new link from the terminal into the same tab. - If the local port is busy, use a different first port:
ssh -L 8899:localhost:8888 …, then openhttp://localhost:8899/followed by the same#token=…fragment. - If the browser cannot connect, confirm that both processes are still running and that the forwarded remote port matches the
dcmviewstartup URL. - If the viewer shows Disconnected, restore the
dcmviewprocess or SSH session, then choose Retry. - If server startup fails, select another remote port or use the default automatic port.
- If
--unix-socketfails to start, see socket troubleshooting.
What the token does not protect
Section titled “What the token does not protect”- It does not encrypt traffic. SSH forwarding does; a non-loopback bind over plain HTTP does not.
- When
dcmviewopens the browser itself, the operating system’s opener receives the launch link, token included, as a process argument that other local users can read on some systems. On a shared machine, keep--no-browserand open the printed link, or use--unix-socket. - A token fixed with
DCMVIEW_TOKENis not rate-limited; use a long random value.
Anyone who has the token and can reach the listener can access pixels, tags, file paths, identifiers, and annotations. See ephemeral state and network security for the complete boundary.