lukaszraczylo 6d8677026f Bugfixes nov2025 pt5 (#9)
* Update dependencies.

* Add autoupdate action.
2025-11-25 16:50:06 +00:00
2025-11-25 16:50:06 +00:00
2025-11-25 11:14:33 +00:00
2025-11-25 11:14:33 +00:00
2025-11-23 17:51:35 +00:00
2025-11-23 18:35:37 +00:00
2025-11-25 01:28:23 +00:00
2025-11-24 13:00:19 +00:00
2025-11-23 17:51:35 +00:00
2025-11-23 17:51:35 +00:00
2025-11-25 16:50:06 +00:00
2025-11-25 16:50:06 +00:00
2025-11-23 17:51:35 +00:00
2025-11-23 17:51:35 +00:00
2025-11-25 01:28:23 +00:00
2025-11-25 11:14:33 +00:00
2025-11-23 18:35:49 +00:00
2025-11-25 11:14:33 +00:00

kportal logo

Release License Go Report Card

Kubernetes port-forward manager with interactive terminal UI

kportal manages multiple Kubernetes port-forwards with an interactive terminal interface. It provides real-time status updates, automatic reconnection, hot-reload configuration, and mDNS hostname publishing.

kportal Screenshot

Features

  • Interactive TUI - Terminal interface with keyboard navigation
  • Live management - Add, edit, and delete port-forwards without restarting
  • Auto-reconnect - Exponential backoff retry on connection failures
  • Hot-reload - Configuration changes applied automatically
  • Health monitoring - Multiple check methods with stale connection detection
  • Multi-context - Support for multiple Kubernetes contexts and namespaces
  • Pod restart handling - Automatic reconnection when pods restart
  • Label selectors - Dynamic pod targeting using label selectors
  • Port conflict detection - Validates port availability with PID information
  • mDNS hostnames - Access forwards via .local hostnames

📦 Installation

Homebrew (macOS/Linux)

brew install lukaszraczylo/brew-taps/kportal

Quick Install

curl -fsSL https://raw.githubusercontent.com/lukaszraczylo/kportal/main/install.sh | bash

Manual Download

Download binaries from the releases page.

Build from Source

git clone https://github.com/lukaszraczylo/kportal.git
cd kportal
make build && make install

🚀 Quick Start

Create .kportal.yaml:

contexts:
  - name: production
    namespaces:
      - name: backend
        forwards:
          - resource: service/postgres
            protocol: tcp
            port: 5432
            localPort: 5432
            alias: prod-db

          - resource: service/redis
            protocol: tcp
            port: 6379
            localPort: 6379

Run:

kportal

Keyboard Controls

Key Action
↑↓ / j/k Navigate
Space / Enter Toggle forward
a Add forward
e Edit forward
d Delete forward
q Quit

📖 Configuration

Basic Structure

contexts:
  - name: <context-name>
    namespaces:
      - name: <namespace-name>
        forwards:
          - resource: <type>/<name>
            protocol: tcp
            port: <remote-port>
            localPort: <local-port>
            alias: <display-name>      # optional
            selector: <label-selector> # optional

Forward Options

Field Required Description
resource Yes Resource type and name (e.g., service/postgres, pod/my-app)
protocol Yes Protocol (tcp)
port Yes Remote port
localPort Yes Local port
alias No Display name and mDNS hostname
selector No Label selector for pod resolution

Resource Formats

Format Description
service/name Service forwarding
pod/name Direct pod by name
pod/prefix Pod by prefix (matches prefix-*)
pod + selector Pod by label selector
deployment/name Deployment

Health Check Configuration

healthCheck:
  interval: "3s"           # Check frequency
  timeout: "2s"            # Check timeout
  method: "data-transfer"  # tcp-dial or data-transfer
  maxConnectionAge: "25m"  # Reconnect before k8s timeout
  maxIdleTime: "10m"       # Detect idle connections

reliability:
  tcpKeepalive: "30s"
  dialTimeout: "30s"
  retryOnStale: true

Health check methods:

  • tcp-dial - Fast TCP connection test
  • data-transfer - Verifies tunnel functionality by attempting data read

Connection age reconnection only triggers when the connection is also idle, preventing interruption of active transfers like database dumps.

mDNS Hostnames

Enable mDNS to access forwards via .local hostnames:

mdns:
  enabled: true

contexts:
  - name: production
    namespaces:
      - name: default
        forwards:
          - resource: service/postgres
            port: 5432
            localPort: 5432
            alias: prod-db  # Accessible via prod-db.local:5432
  • Explicit alias becomes <alias>.local
  • Without alias, hostname is generated from resource name (service/redisredis.local)
  • Works on macOS (Bonjour) and Linux (avahi-daemon)

Verify registration:

dns-sd -B _kportal._tcp local       # macOS
avahi-browse -t _kportal._tcp       # Linux

Usage

Interactive Mode

kportal

Verbose Mode

kportal -v

Validate Configuration

kportal --check

Custom Config File

kportal -c /path/to/config.yaml

Status Indicators

Indicator Description
● Active Connection healthy
○ Starting Initial connection (10s grace period)
◐ Reconnecting Reconnecting after failure
✗ Error Connection failed
○ Disabled Manually disabled

Advanced Features

Hot-Reload

Configuration changes are applied automatically. Manual reload:

kill -HUP $(pgrep kportal)

Port Conflict Detection

kportal validates port availability at startup and during hot-reload, showing which process is using conflicting ports.

Retry Strategy

Exponential backoff: 1s → 2s → 4s → 8s → 10s (max). Retries continue indefinitely until connection succeeds.

Migration from kftray

kportal --convert configs.json --convert-output .kportal.yaml

Signal Handling

  • Ctrl+C / SIGTERM - Graceful shutdown
  • SIGHUP - Reload configuration

🐛 Troubleshooting

Port Already in Use

lsof -i :<port>
kill <pid>

Connection Refused

  1. Verify pod is running: kubectl get pods -n <namespace>
  2. Verify port is correct: kubectl describe pod <pod>
  3. Check service endpoints: kubectl get endpoints <service>

Context Not Found

kubectl config get-contexts

🔧 Development

Prerequisites

  • Go 1.23+
  • Kubernetes cluster access
  • kubectl configured

Build

make build    # Build binary
make test     # Run tests
make all      # fmt, vet, staticcheck, test
make install  # Install locally

Contributing

See CONTRIBUTING.md for guidelines.

License

MIT License - see LICENSE.

Acknowledgments

S
Description
Languages
Go 98.3%
Shell 0.8%
Makefile 0.7%
Ruby 0.2%