Skip to content

steig/tube

Repository files navigation

tube

tube logo

Local development proxy with .test domains

Stop memorizing port numbers. Start using pretty URLs.

Go Version License Tests macOS

FeaturesQuick StartScreenshotsDocumentation


The Problem

During development, you juggle multiple services:

Frontend:  http://localhost:3000
API:       http://localhost:8080
Admin:     http://localhost:4200
Docs:      http://localhost:3001

tube fixes this:

Frontend:  https://app.test
API:       https://api.test
Admin:     https://admin.test
Docs:      https://docs.test

Both HTTP and HTTPS work out of the box with trusted local certificates.

✨ Features

Feature Description
🌐 Pretty URLs Access myapp.test instead of localhost:3000
🔒 HTTPS Support Auto-generated trusted certificates with mkcert
🖥️ Menu Bar App Control everything from your macOS menu bar
📊 Web Dashboard Beautiful UI at localhost:3249
Zero Config DNS One command sets up macOS resolver
🔄 Live Reload Add projects without restarting
🛠️ CLI + GUI Use whichever you prefer

🚀 Quick Start

1. Install

The fastest path: a POSIX sh install script that detects your OS/arch, verifies SHA256 against the published checksums.txt, and installs tube to /usr/local/bin.

curl -fsSL https://raw.githubusercontent.com/steig/tube/main/scripts/install.sh | sh

Pin a specific version or install without sudo:

curl -fsSL https://raw.githubusercontent.com/steig/tube/main/scripts/install.sh \
  | TUBE_VERSION=v0.1.0 sh
curl -fsSL https://raw.githubusercontent.com/steig/tube/main/scripts/install.sh \
  | TUBE_PREFIX="$HOME/.local" sh

Runtime deps (nginx, dnsmasq, mkcert) aren't installed by the script — grab them separately: brew install nginx dnsmasq mkcert.

On macOS the install script also drops tube-gui (menu bar app) alongside tube. Run tube-gui & after installing.

Build from source instead
# Clone and build
git clone https://github.com/steig/tube.git
cd tube
make build-all

# Add to PATH
sudo cp bin/tube bin/tube-gui /usr/local/bin/

2. Initialize (one-time)

tube init

This configures tube and sets up HTTPS with trusted local certificates (requires mkcert).

3. Setup DNS (one-time)

tube setup

This creates /etc/resolver/test so *.test domains work automatically.

4. Add Your Projects

tube add myapp 3000
tube add api 8080

5. Start Services

tube start

6. Open Your App

open https://myapp.test

That's it! 🎉 Both http:// and https:// work.


📸 Screenshots

Menu Bar App

Run tube-gui to get a persistent menu bar icon:

┌───────────────────────────────┐
│ tube ●                        │  ← Green = running
├───────────────────────────────┤
│ ● Services Running            │
├───────────────────────────────┤
│ Projects                     ▸│
│   ├─ myapp.test       :3000   │
│   ├─ api.test         :8080   │
│   └─ dashboard.test   :4200   │
├───────────────────────────────┤
│ Start Services                │
│ Stop Services                 │
├───────────────────────────────┤
│ Open Dashboard...             │
│ Quit tube                     │
└───────────────────────────────┘

Web Dashboard

Access at http://localhost:3249:

╭──────────────────────────────────────────────────────────────────╮
│                                                                  │
│   tube Dashboard                              ● Running          │
│                                                                  │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│   Services                                                       │
│   ┌─────────────────────┐  ┌─────────────────────┐              │
│   │ ● nginx             │  │ ● dnsmasq           │              │
│   │   running (pid 123) │  │   running (pid 456) │              │
│   └─────────────────────┘  └─────────────────────┘              │
│                                                                  │
│   [Start Services]  [Stop Services]                              │
│                                                                  │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│   Projects                                                       │
│   ┌────────────────────────────────────────────────────────────┐│
│   │ ● myapp        http://myapp.test              :3000   [x]  ││
│   │ ○ api          http://api.test                :8080   [x]  ││
│   │ ● dashboard    http://dashboard.test          :4200   [x]  ││
│   └────────────────────────────────────────────────────────────┘│
│                                                                  │
│   [________name________] [__port__] [Add Project]                │
│                                                                  │
╰──────────────────────────────────────────────────────────────────╯

📖 CLI Reference

Project Management

tube add <name> <port>    # Add a project (e.g., tube add api 8080)
tube remove <name>        # Remove a project
tube list                 # List all projects with status

Service Control

tube start                # Start nginx + dnsmasq
tube stop                 # Stop all services
tube restart              # Restart all services
tube status               # Show service status

System Setup

tube init                 # Initialize tube config + SSL certificates
tube setup                # Configure macOS DNS (run once)
tube uninstall            # Remove DNS configuration
tube dns-status           # Check DNS resolver status
tube doctor               # Diagnose issues

SSL Management

tube ssl status           # Show SSL configuration
tube ssl install          # Install mkcert CA to trust store
tube ssl generate         # Generate/regenerate certificates
tube ssl enable           # Enable HTTPS
tube ssl disable          # Disable HTTPS (HTTP only)

Example Session

$ tube add frontend 3000
✓ Added project 'frontend' on port 3000

$ tube add backend 8080
✓ Added project 'backend' on port 8080

$ tube list
NAME                 PORT     URL                                           STATUS
─────────────────────────────────────────────────────────────────────────────────
backend              8080     https://backend.test                          ○
frontend             3000     https://frontend.test                         ○

● = running  ○ = stopped

$ tube start
✓ Started nginx
✓ Started dnsmasq
Services are running!

$ tube status
nginx:   running (pid 12345)
dnsmasq: running (pid 12346)

$ open https://frontend.test  # 🎉 It works!

⚙️ Configuration

Configuration lives in ~/.tube/config.yaml:

# Domain settings
domain: example.com
tunnel_prefix: dev-

# Local proxy settings
proxy:
  local_domain: .test        # TLD for local domains
  dashboard_port: 3249       # Dashboard port

# Service binaries
nginx:
  binary: nginx
  http_port: 80
  https_port: 443

dnsmasq:
  binary: dnsmasq
  port: 53

# SSL/HTTPS settings
ssl:
  enabled: true
  cert_file: ~/.tube/ssl/wildcard.test.pem
  key_file: ~/.tube/ssl/wildcard.test-key.pem

# Your projects
projects:
  frontend: 3000
  backend: 8080
  admin: 4200

Environment Variables

Variable Description Default
TUBE_CONFIG Config file path ~/.tube/config.yaml
TUBE_* Any config key, prefixed with TUBE_ and uppercased (per-key default)

🏗️ Architecture

                        ┌─────────────────┐
                        │    Browser      │
                        │ myapp.test:443  │
                        └────────┬────────┘
                                 │
                                 ▼
┌─────────────────────────────────────────────────────────────┐
│                    macOS DNS Resolver                        │
│                                                              │
│  /etc/resolver/test  ──►  nameserver 127.0.0.1              │
│                                                              │
└────────────────────────────────┬────────────────────────────┘
                                 │
                                 ▼
┌─────────────────────────────────────────────────────────────┐
│                        dnsmasq                               │
│                                                              │
│  *.test  ──►  127.0.0.1                                     │
│                                                              │
└────────────────────────────────┬────────────────────────────┘
                                 │
                                 ▼
┌─────────────────────────────────────────────────────────────┐
│                         nginx                                │
│                                                              │
│  :80  (HTTP)   ──►  proxy_pass http://127.0.0.1:PORT        │
│  :443 (HTTPS)  ──►  proxy_pass http://127.0.0.1:PORT        │
│                     (SSL termination with mkcert certs)      │
│                                                              │
└────────────────────────────────┬────────────────────────────┘
                                 │
                                 ▼
┌─────────────────────────────────────────────────────────────┐
│                    Your Application                          │
│                                                              │
│                    localhost:3000                            │
│                                                              │
└─────────────────────────────────────────────────────────────┘

🛠️ Development

Prerequisites

  • Go 1.23+
  • nginx
  • make

Build

# Clone
git clone https://github.com/steig/tube.git
cd tube

# Enter nix shell (optional, but recommended)
nix develop

# Build CLI only
make build

# Build GUI only
make build-gui

# Build both
make build-all

Test

# Run unit tests
make test

# Run tests in Docker (includes nginx/dnsmasq)
make test-docker

# Integration tests
make test-integration

# Coverage report
make coverage

Project Structure

tube/
├── cmd/
│   ├── tube/              # CLI entry point
│   └── tube-gui/          # GUI entry point
├── internal/
│   ├── cli/               # CLI commands (cobra)
│   ├── config/            # Configuration (viper)
│   ├── dns/               # macOS resolver management
│   ├── gui/               # Menu bar + dashboard
│   ├── proxy/             # nginx/dnsmasq managers
│   ├── service/           # Process lifecycle
│   └── ssl/               # Certificate management (mkcert)
├── templates/
│   ├── nginx/             # nginx config templates
│   └── dnsmasq/           # dnsmasq config templates
├── docs/                  # Documentation
├── scripts/               # Build/test scripts
└── Makefile

📚 Documentation

Document Description
Installation Detailed install guide
CLI Reference All commands
Configuration Config options
GUI Guide Menu bar & dashboard
Architecture How it works
Troubleshooting Common issues
Contributing How to contribute

🗺️ Roadmap

  • Core CLI
  • nginx reverse proxy
  • macOS DNS resolver
  • Menu bar app
  • Web dashboard
  • HTTPS with mkcert
  • Cloudflare Tunnel integration
  • Linux support
  • Homebrew formula

🤝 Contributing

Contributions welcome! Please read CONTRIBUTING.md first.

# Fork, clone, branch
git checkout -b feature/my-feature

# Make changes, test
make test

# Commit and push
git commit -m "Add my feature"
git push origin feature/my-feature

# Open PR

📄 License

MIT License - see LICENSE for details.


Made for developers who are tired of remembering port numbers 🚀

Report BugRequest Feature

About

Local development proxy for .test domains on macOS — HTTPS out of the box, menu bar app, and web dashboard.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors