Skip to content

Repository files navigation

PortRelay

PortRelay is a native macOS menu bar app for managing SSH local port forwarding tunnels to services running inside Docker containers on remote hosts.

The SSH transport, remote command execution, and TCP forwarding run in-process with SwiftNIO and SwiftNIO SSH. PortRelay does not launch the system ssh client or a shell helper.

Disclaimer and Trademark Notice

PortRelay is fundamentally an SSH tunnel manager with a Docker-focused workflow. It is intended for people who administer remote containers and already understand their SSH access, Docker networks, exposed services, firewall rules, and the security implications of forwarding remote traffic to local ports.

PortRelay is an independent project and is not affiliated with, sponsored by, or endorsed by Docker, Inc. Docker and the Docker logo are trademarks or registered trademarks of Docker, Inc. in the United States and/or other countries.

Overview

PortRelay network overview

Screenshots

All connections, hosts, users, and endpoints shown below are fictitious.

Connection Manager

PortRelay connection manager

New Connection

PortRelay new connection form

Menu Bar

PortRelay menu bar menu

Settings

PortRelay settings

Help

PortRelay help window

How It Works

  1. PortRelay connects to the configured SSH host and verifies its host key.
  2. It authenticates with a Keychain password or an unencrypted ED25519 private key from ~/.ssh/id_ed25519.
  3. It runs docker container inspect remotely and reads the container address from the selected Docker network.
  4. It binds the configured local IP and port.
  5. Each local client is forwarded through an SSH direct-tcpip channel to the container IP and service port.

The first connection to an SSH host displays its SHA-256 fingerprint for confirmation. A changed host key always requires explicit approval.

After an established tunnel is interrupted, PortRelay resolves the container address again and reconnects automatically with delays of 2, 4, 8, 16, and then 30 seconds between attempts. Retries continue until the tunnel is restored or stopped manually. Initial authentication and configuration errors remain visible instead of entering the retry loop.

Requirements

  • macOS 13 or later.
  • SSH access to the remote host.
  • Permission to run docker container inspect on the remote host.
  • Password authentication or an unencrypted OpenSSH ED25519 key at ~/.ssh/id_ed25519.
  • Swift 6.1 or later to build from source.

Encrypted private keys and other private-key formats are not supported yet.

Run From Source

cd port-relay
./Scripts/run.sh

The app appears in the macOS menu bar. From the menu you can start or stop saved connections, open the connection manager, add connections, open settings, and view the help diagram.

Swift Package Manager downloads the pinned dependencies on the first build.

Saved Data

Connection profiles are stored in:

~/Library/Application Support/PortRelay/connections.json

Settings are stored in:

~/Library/Application Support/PortRelay/settings.json

By default, connection logs are written to:

~/Library/Application Support/PortRelay/Logs/

Logs are appended across application launches and include connection losses, failed attempts, scheduled retries, and successful recovery.

Each profile stores the SSH user, host and port, Docker container and network, remote service port, local IP and port, and automatic-start preference. Passwords are stored in the macOS Keychain and are never written to the profile or log files.

The log location, SSH connection timeout, KeepAlive interval, allowed KeepAlive failures, and UI language can be changed from Settings....

On its first launch, PortRelay copies existing DockerBridge profiles, settings, logs, host fingerprints, and Keychain credentials into its new application identity. The original data is retained for rollback.

Localization

PortRelay supports English, Spanish, and Portuguese. English is the base and fallback language, while the default setting follows the macOS language. It can be changed from Settings....

Application strings live in Resources/en.lproj/Localizable.strings and the corresponding es.lproj and pt.lproj files. The help diagram is localized as overview.svg inside each .lproj directory.

Build

cd port-relay
./Scripts/build.sh

The generated app bundle is:

build/PortRelay.app

Package DMG

cd port-relay
./Scripts/package-dmg.sh

The installer image is:

build/PortRelay.dmg

Website

The static product website lives in Website/ and is published at tecnologica.ar/port-relay. It includes the localized product page, screenshots, DMG download, and privacy policy used for App Store Connect.

Run it locally with:

python3 -m http.server 8765 --directory Website

The distributable DMG is copied to Website/downloads/PortRelay.dmg for deployment but remains excluded from Git because GitHub Releases is the source of versioned binaries.

Launch at Login

PortRelay can enable or disable its login item from the Settings window. The helper is embedded in the signed application bundle and registered with Apple's ServiceManagement framework. PortRelay does not invoke launchctl or install property lists in the user's Library/LaunchAgents directory.

Dependencies

Runtime networking and cryptography are provided by Apple open-source Swift packages pinned in Package.resolved: SwiftNIO, SwiftNIO SSH, and Swift Crypto, plus their transitive Swift packages.

See THIRD_PARTY_NOTICES.md for dependency versions, licenses, and notices.

License

PortRelay is released under the MIT License.

About

Native macOS menu bar app for managing SSH local port forwarding tunnels to services running inside Docker containers on remote hosts.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages