Skip to content
Section: Overview

Documentation

Overview

linkport publishes SSH, TCP, UDP and HTTP from a machine behind NAT. The connector only dials out on port 443 — no inbound ports, no public IP.

  • Connector. linkport-agent proxies only the local addresses you publish.
  • Console links. A 256-bit link opens a browser terminal, a raw tunnel or an HTTP origin.
  • linkport Terminal. A desktop SSH client over the same tunnel. Pro and Team.
  • MCP server. linkport-mcp: 15 typed tools, hosted or local --stdio.

Quick start

In the dashboard, click Connect a machine and run the one-time command (valid for 30 minutes) on a Linux host, x86_64 or aarch64:

sh
curl -fsSL https://linkport.cloud/i/<token> | sudo sh

Read it first

Fetching the script doesn’t use up the token, so you can inspect it before running. It checks the agent’s SHA-256 and leaves sshd, sudoers and the firewall alone.

inspect
curl -fsSL https://linkport.cloud/i/<token> -o install.sh && cat install.sh

Custom publications

Repeat --expose proto:host:port[:name] for ssh, tcp, udp or http. The default is ssh:127.0.0.1:22.

expose
linkport run --edge tls://edge.linkport.cloud:443 --expose ssh:127.0.0.1:22:ssh --expose tcp:127.0.0.1:5432:postgres --expose http:127.0.0.1:3000:grafana

Removing the agent

sh
sudo systemctl disable --now linkport-agent && sudo rm -rf /etc/systemd/system/linkport-agent.service /etc/linkport /usr/local/bin/linkport /etc/sudoers.d/linkport

Connector

linkport-agent runs on Linux x86_64 and aarch64; there is no Mac or Windows agent. It opens no inbound listener. CONNECT-only proxies are not supported.

Transport

  • WebSocket GET /agent/ws over TLS 443. The token travels in a Hello frame, not the URL.
  • Or direct TLS with ALPN linkport/1 (tls://host:443) — lighter, but fails behind a CDN or WAF that drops that ALPN.
  • The edge terminates 443 itself, with no extra reverse proxy.

Service user

Shown before the installer changes anything: LP_RUN_AS if set, otherwise SUDO_USER or the current user — possibly root. No system user is created; console commands and MCP run_command run with that account’s permissions.

Files

  • /etc/linkport/agent.env (0600): LP_EDGE_ADDR, LP_AGENT_TOKEN, LP_EXPOSE, LP_API_URL.
  • /etc/systemd/system/linkport-agent.service with Restart=always, RestartSec=3.
  • A .sig check runs only when /etc/linkport/release.pub or LP_AGENT_VERIFY_KEY is set.

linkport Terminal

Desktop SSH client for Windows, macOS and Linux, included with Pro and Team: SSH over the link, split panes, two-pane SFTP, a local vault (Argon2id + OS keychain), import from ~/.ssh/config, PuTTY, Termius and MobaXterm.

Device-code sign-in

On first launch the app shows an 8-character code. Approve it at linkport.cloud/device while signed in. The app never sees your password.

Edge command policy does not apply here: native SSH over the tunnel is a raw byte pipe. Recordings stay on the device as .cast.

MCP integration

linkport-mcp speaks MCP 2024-11-05. Hosted: POST /mcp with Authorization: Bearer lp_…. Local: linkport-mcp --stdio with LP_TOKEN, launched by your client — no listening socket.

Cursor (hosted)

In .cursor/mcp.json, with a key from API & MCP keys:

.cursor/mcp.json
{
  "mcpServers": {
    "linkport": {
      "url": "https://linkport.cloud/mcp",
      "headers": {
        "Authorization": "Bearer lp_…"
      }
    }
  }
}

Claude Desktop and local stdio

For claude_desktop_config.json or any client that spawns a stdio server. Only local mode can upload your own files with local_path; set LP_MCP_LOCAL_FILES=1 only on a machine you trust.

stdio
{
  "mcpServers": {
    "linkport": {
      "command": "linkport-mcp",
      "args": [
        "--stdio"
      ],
      "env": {
        "LP_TOKEN": "lp_…",
        "LP_API_URL": "https://linkport.cloud",
        "LP_EDGE_URL": "https://linkport.cloud",
        "LP_LINK_BASE": "https://linkport.cloud",
        "LP_MCP_LOCAL_FILES": "1"
      }
    }
  }
}

All 15 tools

The last column shows what a read-only machine allows. Control-plane tools such as list_machines and rotate_link ignore the flag.

ToolGroupArgumentsRead-only
list_machinesMachines—n/a
list_tunnelsLinksagent_idn/a
create_tunnelLinksagent_id, name, proto, local_addr, …n/a
revoke_linkLinkstunnel_idn/a
rotate_linkLinkstunnel_idn/a
get_connection_infoLinkslink_idn/a
run_commandCommandsagent_id or link_id, command, timeout_secs?403
list_filesFilesagent_id or link_id, path?allowed
stat_fileFilesagent_id or link_id, pathallowed
read_fileFilespath, offset?, max_bytes? (≤ 8 MiB)allowed
write_fileFilespath, content? / local_path?403
make_dirFilespath, parents?403
delete_fileFilespath, recursive?403
move_fileFilespath, to403
install_commandMachinesaccess[]?, e2e?n/a

Access control & guardrails

Read-only mode, command allow/deny lists and session recording. The filter runs at the edge for the browser terminal and MCP run_command.

Read-only

  • Browser terminal: only reading commands run (ls, cat, grep…). Shells, editors, sudo, curl and output redirects are refused.
  • Raw and WebSocket tunnels to non-HTTP publications are blocked.
  • MCP: run_command, write_file, make_dir, delete_file and move_file return 403; list, stat and read still work.
  • HTTP apps keep their own auth; the flag does not make their filesystem read-only.

What the filter can’t catch

It reads a byte stream, not a parsed shell — a hard stop on accidents, a speed bump on intent.

  • Input inside a full-screen program (an editor, top, less) is not parsed.
  • A line recalled from history or completed with Tab is refused — type the whole command.
  • A deny list doesn’t see through interpreters (python -c, base64 | sh, an uploaded script). Read-only refuses interpreters.
  • A native ssh client over the link is a raw byte pipe with no filter.
  • An open console keeps its policy until it reconnects. With the control plane unreachable, new sessions, commands and file changes are refused.

Session recording

Off, commands only, or full session (asciinema v2, Team plan). Input is never recorded. Files live on a local volume, not object storage.

End-to-end encryption

Enable at install with LP_E2E=1. The key is generated on the machine and never leaves it; the server keeps only a SHA-256 fingerprint. X25519 + ML-KEM-768, HKDF-SHA256, ChaCha20-Poly1305. Keys look like lpe2e1_….

ssh
ssh -o ProxyCommand='linkport connect https://linkport.cloud/s/<link_id> --e2e' deploy@host

The edge can’t filter what it can’t read, so E2E turns off the browser terminal and HTTP links. MCP commands and file transfers still cross the edge in the clear — they use the agent control channel, not the tunnel.

Troubleshooting

Machine never appears

journalctl
sudo systemctl status linkport-agent && journalctl -u linkport-agent -n 50 --no-pager

Install tokens expire after 30 minutes — generate a new command in the dashboard.

Machine shows offline

The agent reconnects with backoff. If it stays offline, check that outbound TCP 443 is allowed; CONNECT-only proxies are not supported.

Publication refused

New publications apply on the next agent connect. Restart to apply now:

systemctl
sudo systemctl restart linkport-agent

A command is refused in the console

Check read-only mode and the allow/deny lists. Lines from history or Tab completion are refused too — type the full command.

Still stuck? Write to [email protected] with the machine name and the output of the first command above. Security issues: [email protected].