How Starship Handles Port Forwarding for Local Access to Blockchain Nodes
Starship automates Kubernetes port forwarding through a single CLI command that validates cluster readiness, maps logical service ports to localhost endpoints, and manages concurrent kubectl processes until manual termination.
Starship, developed by hyperweb-io, eliminates the manual complexity of exposing blockchain nodes running in Kubernetes to your local development environment. The connect command streamlines port forwarding for local access to blockchain nodes by orchestrating multiple kubectl port-forward processes based on declarative configuration, enabling seamless interaction with chain RPC endpoints, REST APIs, and explorer interfaces.
The Connect Command Architecture
The connect sub-command in starship/cmd/starship/connect.go implements a six-stage workflow that transforms high-level service definitions into active localhost tunnels.
Environment Validation and Prerequisites
Before establishing any tunnels, Starship validates the operational environment. The client.CheckKubectl() function verifies that the kubectl binary exists in $PATH and is executable. Subsequently, client.CheckPortForward() inspects the Kubernetes cluster to confirm that all required pods—including chain nodes, relayers, and explorers—are in the Running phase. This prevents connection attempts against containers that are still initializing or in a crash loop.
Configuration-Driven Port Discovery
Starship reads the deployment configuration from a Config struct (defined in starship/tests/e2e/config.go) that contains a Port map for each infrastructure component. When you execute the connect command, the system iterates over every defined chain, relayer, and optional service to identify which endpoints require exposure. The configuration specifies logical service names that map to container ports without requiring developers to memorize pod names or internal cluster DNS entries.
Default Port Mappings for Blockchain Components
The defaultPorts map in connect.go establishes well-known port assignments for common blockchain interfaces. Standard mappings include chain.rest at 1317, chain.rpc at 26657, and exposer at 8081. When a chain configuration specifies cometmock as the RPC provider, Starship automatically overrides the remote port to defaultCometmockPort = 22331, ensuring compatibility with the mock consensus engine.
Building and Executing Kubectl Port Forwards
Once Starship validates the environment and parses the configuration, it constructs and executes the underlying kubectl commands that bridge the cluster-network boundary.
Command Construction Logic
The PortForwardCmds() function generates port-forward specifications for every enabled service. For each endpoint, it calls execPortForwardCmd(resource, localPort, remotePort), which returns an *exec.Cmd configured to run:
kubectl port-forward <resource> <localPort>:<remotePort> -n <namespace>
The <resource> parameter accepts either pod identifiers (e.g., pods/cosmoshub-genesis-0) or service names (e.g., svc/explorer). If the configuration specifies a custom namespace, the command builder appends the -n flag automatically. This abstraction allows developers to target specific chain validators or load-balanced services without manual kubectl syntax.
Concurrent Execution and Error Handling
The RunPortForward() method launches each kubectl command in its own goroutine, enabling parallel initialization of multiple endpoints. A result channel aggregates success and failure states from each forwarder. If any individual port forward fails—due to port conflicts, permission errors, or pod termination—the context cancellation propagates to all running processes, ensuring clean shutdown rather than leaving orphaned kubectl instances.
The CLI blocks the main thread until the user sends an interrupt signal (Ctrl-C). Upon receiving the termination request, Starship cancels the parent context, which triggers graceful shutdown of all background kubectl processes and releases the bound localhost ports.
Configuration Example: Defining Exposed Services
The ports stanza in your config.yaml declaratively specifies which services Starship should expose. Each component supports distinct port mappings that correspond to standard blockchain tooling interfaces:
chains:
- id: cosmoshub
name: cosmoshub
ports:
rest: 1317 # Cosmos SDK REST server
rpc: 26657 # Tendermint RPC endpoint
grpc: 9090 # gRPC query interface
exposer: 8081 # Starship exposer service
relayers:
- name: hermes
type: hermes
ports:
rest: 3000 # Hermes REST API
exposer: 8081 # Relayer exposer endpoint
explorer:
enabled: true
ports:
rest: 8080 # Block explorer web interface
Running the Port Forward CLI
Execute the connect command to initiate all configured port forwards simultaneously:
starship connect -c config.yaml
Upon successful startup, the CLI outputs structured logs mapping each service to its localhost endpoint:
INFO Port forwarding
INFO port-forwarding: cosmoshub: rest: to: http://localhost:1317
INFO port-forwarding: cosmoshub: rpc: to: http://localhost:26657
INFO port-forwarding: hermes: rest: to: http://localhost:3000
INFO port-forwarding: explorer: rest: to: http://localhost:8080
These endpoints remain accessible until you terminate the process, at which point Starship automatically cleans up all kubectl port-forward subprocesses.
Implementation Deep Dive
The core port-forward logic resides in starship/cmd/starship/connect.go, while command registration occurs in starship/cmd/starship/root.go. The implementation leverages the Config struct from starship/tests/e2e/config.go for test-validated configuration parsing.
Key implementation details include:
- Resource targeting: The system distinguishes between direct pod access (for specific validators) and service abstraction (for load-balanced explorers)
- Namespace injection: Commands automatically include the
-nflag whenc.config.Namespaceis non-empty - Cometmock adaptation: Automatic port substitution occurs when the configuration specifies cometmock as the RPC backend
Test suites in starship/tests/e2e/exposer_test.go and starship/tests/e2e/solana_test.go demonstrate real-world usage patterns, verifying that forwarded exposer ports correctly proxy chain-specific queries and that Solana nodes remain accessible through the established tunnels.
Summary
Starship transforms Kubernetes port forwarding from a manual, error-prone process into a declarative, automated workflow:
- Validates
kubectlavailability and pod readiness before attempting connections - Maps logical service names to well-known ports via the
defaultPortsconfiguration - Constructs precise
kubectl port-forwardcommands targeting pods or services - Executes forwards concurrently with centralized error handling and graceful shutdown
- Maintains connections until user interruption, ensuring stable local access to blockchain infrastructure
Frequently Asked Questions
How does Starship handle port conflicts on the local machine?
Starship binds to the exact localhost ports specified in your configuration YAML. If a port is already occupied by another process, the underlying kubectl port-forward command fails, and Starship's RunPortForward() error propagation mechanism cancels all active forwards. You must free the conflicting port or modify your configuration to use alternative local port numbers before retrying.
Can I port forward to specific validator pods rather than services?
Yes. The execPortForwardCmd() function accepts any valid Kubernetes resource identifier. When targeting specific validators, Starship constructs resource strings like pods/<chain>-genesis-0 (or the appropriate pod index) rather than service names. This enables direct debugging of individual chain nodes while bypassing any load balancing or service abstraction layers.
What happens if a blockchain node restarts during an active port forward?
If the target pod terminates or restarts, the underlying kubectl port-forward process exits with an error. Starship detects this failure through the result channel monitoring each goroutine. Upon detecting any forward failure, the system cancels the parent context, which terminates all remaining port-forward processes and returns control to the shell. You must rerun starship connect after the pod returns to Running status to re-establish connectivity.
Does Starship support port forwarding for non-blockchain services like explorers?
Absolutely. The PortForwardCmds() iterator processes all configuration sections uniformly, including explorers, registries, and relayers. The defaultPorts map includes entries for explorer interfaces, and the resource builder correctly formats service targets as svc/explorer when generating kubectl commands. This unified approach treats blockchain nodes and auxiliary infrastructure identically from a port-forwarding perspective.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →