Stop juggling localhost ports. Get real .roxy domains with trusted
HTTPS for every local project.
One binary. CLI-first. Zero dependencies.
- ✓ Test OAuth/webhooks locally with real HTTPS
- ✓ See all traffic in real-time
- ✓ Share work across devices
- ✓ No nginx. No dnsmasq. No YAML.
| Without Roxy | With Roxy |
|---|---|
http://localhost:3000 + certificate warnings |
https://myapp.roxy - trusted ✓ |
| Remember 5 different ports for 5 services | One domain, path-based routing |
| Can't test webhooks/OAuth locally | Works with Stripe, OAuth, callbacks |
| Edit nginx configs, restart services | roxy register myapp.roxy |
| Manual setup for each subdomain | --wildcard and every subdomain just works |
| No visibility into traffic | Full request/WebSocket logging |
Homebrew:
# 1. Install via Homebrew
brew tap rbas/roxy
brew install roxy
# 2. One-time setup (CA, DNS, and unprivileged system service)
sudo roxy install
# 3. Register your first project
roxy register myapp.roxy --route "/=3000" --route "/api=3001"
# 4. Open in browser (the proxy is already running)
open https://myapp.roxy # on macOS
xdg-open https://myapp.roxy # on linuxNote: After first install, restart your browser for the certificates to be recognized. On Linux with snap browsers (Firefox, Chromium), see the Linux guide for an extra one-time step.
That's it. Trusted HTTPS, no warnings, no config files. Just works.
Find Roxy useful? ⭐ Star the repo to help others discover it!
- 🚀 Full-stack developers — Run frontend + backend + database with memorable domains
- 📱 Mobile app developers — Test APIs that require HTTPS without tunnels
- 🔗 OAuth/webhook development — Real HTTPS callbacks work locally (Stripe, GitHub, etc.)
- 👥 Teams — Share work across devices on the same network
- 🔧 Microservices developers — Stop memorizing which service is on which port
- 🏢 Multi-tenant SaaS developers — Wildcard subdomains
(
*.myapp.roxy) for testing tenant routing locally - 🎨 Anyone tired of
localhost:3000— Get real domains likemyapp.roxyinstead
roxy register frontend.roxy --route "/=3000"
roxy register backend.roxy --route "/=8080" --route "/api=8081"
roxy register docs.roxy --route "/=/var/www/docs"
# Wildcard: one registration covers all subdomains
roxy register myapp.roxy --wildcard --route "/=3000"
# → myapp.roxy, api.myapp.roxy, admin.myapp.roxy...All domains work simultaneously. No port conflicts. No config files to manage.
Core Features:
- ✓ Custom
.roxydomains —myapp.roxyinstead oflocalhost:3000 - ✓ Trusted HTTPS — Auto-generated certificates your browser actually trusts (no warnings!)
- ✓ Path-based routing — Route
/to port 3000,/apito port 3001,/staticto a directory - ✓ Built-in DNS server — No dnsmasq, no external DNS tools needed
- ✓ Wildcard subdomains — Register
*.myapp.roxyand every subdomain just works, with trusted HTTPS - ✓ Single binary — No nginx, no containers, no runtime dependencies
Developer Experience:
- ✓ Real-time traffic logs — See every HTTP request and WebSocket
connection with
roxy logs -f - ✓ WebSocket support — Full proxying and connection lifecycle tracking
- ✓ Static file serving — Serve directories with automatic
index.htmlsupport and file browser - ✓ LAN access — Access your projects from phone/tablet on the same network
- ✓ Any tech stack — Works with Next.js, Rails, Django, Express, Go, Rust, PHP... anything on any port
- ✓ Shell completions — Tab completion for bash, zsh, and fish
Docker Integration:
- ✓ Auto-discovery — Docker Compose services are automatically
registered as
.roxydomains. Start a stack, get HTTPS instantly - ✓ Zero config — Enable once, then
docker compose upis all you need. Noroxy registerrequired - ✓ Label-driven — Fine-tune with
roxy.domain,roxy.port, androxy.wildcardlabels
Stripe webhooks require HTTPS. With Roxy, it's trivial:
# Register your e-commerce app
roxy register shopify-clone.roxy \
--route "/=3000" \
--route "/api=3001"
# Point Stripe webhooks to: https://shopify-clone.roxy/api/webhooks
# No ngrok. No tunnels. No port forwarding. Just works.# Frontend on port 3000, API on port 3001, admin dashboard on port 8080
roxy register myapp.roxy \
--route "/=3000" \
--route "/api=3001" \
--route "/admin=8080"
# Access:
# https://myapp.roxy → Next.js frontend
# https://myapp.roxy/api → Express API
# https://myapp.roxy/admin → Admin dashboardYour app uses subdomains for tenants? One command:
# Register a wildcard — covers myapp.roxy AND *.myapp.roxy
roxy register myapp.roxy --wildcard \
--route "/=3000" \
--route "/api=3001"
# All of these work instantly, trusted HTTPS included:
# https://myapp.roxy → main app
# https://acme.myapp.roxy → tenant "acme"
# https://globex.myapp.roxy → tenant "globex"
# No extra registration needed. Just add a subdomain and go.With Docker integration enabled, docker compose up is all
you need:
# docker-compose.yml
services:
web:
build: .
ports:
- "3000:3000"
api:
build: ./api
ports:
- "8080:8080"docker compose up -d
# Roxy auto-discovers both services:
# https://web.myproject.roxy → port 3000
# https://api.myproject.roxy → port 8080
# No roxy register needed. Just works.See the Docker guide for labels, custom domains, and container-to-Roxy communication.
# Start your API server on port 3000
roxy register api.roxy --route "/=3000"
# Now your phone on the same WiFi can access:
# https://api.roxy
# (Add your Mac's IP to your phone's /etc/hosts or use LAN IP mode)Works with any stack: Next.js, Rails, Django, Express, Flask, Go, Rust, PHP... anything that speaks HTTP.
Unlike nginx or Valet, Roxy shows you everything flowing through it in real-time:
# Follow traffic live (like tail -f)
roxy logs -fExample output:
INFO Request completed method=GET host=myapp.roxy path=/ status=200 duration_ms=45
INFO Request completed method=POST host=myapp.roxy path=/api/users status=201 duration_ms=123
INFO WebSocket connection established target=127.0.0.1:3000
INFO WebSocket message sent bytes=156 target=127.0.0.1:3000
INFO WebSocket message received bytes=89 target=127.0.0.1:3000
INFO WebSocket connection closed target=127.0.0.1:3000 duration_ms=45230
INFO DNS query domain=myapp.roxy qtype=A response=127.0.0.1
Need debugging details? Set daemon.log_level = "debug" in
your user configuration, restart Roxy, then follow the log:
roxy restart
roxy logs -fDEBUG Routing request method=GET host=myapp.roxy path=/api/users matched_route=/api
DEBUG Proxying HTTP request target=127.0.0.1:3001 headers=5
DEBUG Proxy response target=127.0.0.1:3001 status=200 body_size=1024
DEBUG WebSocket upgrade successful target=127.0.0.1:3000
Perfect for:
- Debugging API calls between frontend and backend
- Tracking WebSocket connection issues
- Understanding which service handled which request
- Monitoring DNS resolution for
.roxydomains
# Register a domain with routes
roxy register <domain> --route "PATH=TARGET" [--route "PATH=TARGET" ...]
# Register with wildcard subdomains (*.myapp.roxy)
roxy register <domain> --wildcard --route "PATH=TARGET"
# Targets can be:
# Port: --route "/=3000" → proxies to 127.0.0.1:3000
# Host:Port: --route "/=192.168.1.50:3000" → proxies to a specific host
# Directory: --route "/static=/var/www" → serves static files
# Manage routes on existing domains
roxy route add myapp.roxy /webhooks 9000
roxy route remove myapp.roxy /webhooks
roxy route list myapp.roxy
# Unregister a domain
roxy unregister myapp.roxy
# List all registered domains
roxy list
# Daemon control (no sudo after installation)
roxy start
roxy stop
roxy restart
roxy reload
roxy status
# View logs
roxy logs
roxy logs -f # Follow (like tail -f)
roxy logs -n 100 # Last 100 linessudo roxy install installs a launchd service on macOS or systemd socket and
service units on Linux. The operating system owns ports 80 and 443 and passes
the listeners to Roxy, while the Roxy process itself runs as the developer who
performed the installation. No separate brew services setup is needed.
Three steps, then forget about it:
-
roxy install- Creates a trusted Root Certificate Authority (CA)
- Adds it to your system trust store (macOS Keychain / Linux ca-certificates)
- Configures DNS to resolve
.roxydomains (macOS/etc/resolver// Linux systemd-resolved) - Installs socket activation for ports 80/443 and starts Roxy as your user
⚠️ Restart your browser after first install for certificates to be recognized
-
roxy register <domain>- Saves your routing configuration (which paths go to which ports/directories)
- Reloads the running daemon immediately, without
sudoor a restart
-
First HTTPS request
- Generates an exact, in-memory certificate from TLS SNI
- Reuses it from an in-memory cache; no per-domain key files are written
Your browser trusts the certificates (no warnings) because they're
signed by your Root CA. WebSockets work transparently. DNS queries for
.roxy domains resolve instantly.
Clean and contained:
- macOS data/config:
~/Library/Application Support/Roxy/ - macOS logs/runtime:
~/Library/Logs/Roxy/and~/Library/Caches/Roxy/ - Linux config/data:
~/.config/roxy/and~/.local/share/roxy/ - Linux logs/runtime:
~/.local/state/roxy/ - DNS:
/etc/resolver/roxy(macOS) or/etc/systemd/resolved.conf.d/roxy.conf(Linux) - Run
sudo roxy uninstallto remove the active installation cleanly
For configuration details, logging options, and file locations see the full documentation.
| Feature | Roxy | Caddy | nginx/Traefik | Laravel Valet | ngrok | /etc/hosts |
|---|---|---|---|---|---|---|
| CLI-first setup | ✓ | ✓ | ✗ | ✗ | ✓ | ~ |
| Trusted HTTPS | ✓ | ✓ | Manual setup | ✓ | ✓ | ✗ |
| Built-in DNS | ✓ | ✗ | ✗ | Uses dnsmasq | N/A | ✗ |
| Path-based routing | ✓ | ✓ | Manual setup | ✗ | Limited | ✗ |
| Built-in traffic logs | ✓ | ✓ | Manual setup | ✗ | ✓ | ✗ |
| Stays local | ✓ | ✓ | ✓ | ✓ | ✗ | ✓ |
| Single binary | ✓ | ✓ | ✗ | ✗ | ✓ | N/A |
| Any tech stack | ✓ | ✓ | ✓ | PHP-focused | ✓ | ✓ |
| WebSocket support | ✓ | ✓ | ✓ | ~ | ✓ | ~ |
| Wildcard subdomains | ✓ | Config-based | Manual setup | ✗ | ✗ | ✗ |
| Docker auto-discovery | ✓ | ✗ | Labels only | ✗ | ✗ | ✗ |
Caddy is the closest alternative — it has excellent HTTPS ergonomics with a built-in CA,
caddy trust, and a powerful CLI (caddy reverse-proxy --from domain --to target). The main
differences are that Roxy includes a built-in DNS server (no /etc/hosts editing needed) and
handles wildcard subdomain DNS resolution out of the box.
TL;DR: Roxy is purpose-built for local development. It bundles DNS, HTTPS, and reverse
proxying into one workflow — register a domain, start the proxy, and everything just works.
No /etc/hosts, no config files, no manual cert setup.
- macOS (Monterey or later) or Linux (Ubuntu 22.04+ / Debian 12+)
- Rust toolchain (for building from source)
- sudo access for the one-time install/uninstall only
- Linux only:
systemd-resolved(default on Ubuntu)
brew tap rbas/roxy
brew install roxyDownload the latest binary for your platform from the Releases page:
macOS (Apple Silicon):
curl -LO https://github.com/rbas/roxy/releases/latest/download/roxy-macos-arm64.tar.gz
tar -xzf roxy-macos-arm64.tar.gz
sudo mv roxy /usr/local/bin/
roxy --versiongit clone https://github.com/rbas/roxy.git
cd roxy
cargo install --path .
roxy --versionRoxy is ready for daily development use on macOS and Linux. Recent additions and future plans:
- Pre-built binaries — download and run without building from source (macOS ARM64)
- Homebrew support —
brew tap rbas/roxy && brew install roxy - Auto-start on boot — unprivileged launchd/systemd service with socket activation
- File browser — automatic directory listing for static file routes
- Wildcard subdomains —
*.myapp.roxypatterns with automatic certificate generation - Linux support — Ubuntu/Debian with systemd-resolved DNS integration and system CA trust
- Docker auto-discovery — Compose services get
.roxydomains automatically with label-driven customization - Docker network DNS — resolve
.roxydomains inside containers withoutextra_hosts
Have a feature idea? Open an issue and let's discuss!
- 📖 Full documentation: docs/README.md
- 🐳 Docker guide: docs/docker.md
- 🐧 Linux guide: docs/linux.md
- 🐛 Having issues?: Check the troubleshooting guide
- 💬 Questions or feedback?: Open an issue
MIT — Martin Voldrich