Daemon Mode
The localup daemon manages multiple tunnels simultaneously from a single configuration file. It provides automatic reconnection, IPC for control, and seamless integration with your development workflow.
Quick Start
# Create a configuration file
cat > .localup.yml << 'EOF'
defaults:
relay: "relay.example.com:4443"
local_host: "localhost"
timeout_seconds: 30
tunnels:
- name: api
port: 3000
protocol: https
subdomain: myapp-api
- name: frontend
port: 3001
protocol: https
subdomain: myapp-frontend
EOF
# Start the daemon
localup daemon start
Platform Support
The daemon works on all major platforms:
| Platform | Status | Notes |
|---|---|---|
| macOS | Full support | IPC via Unix socket |
| Linux | Full support | IPC via Unix socket |
| Windows | Full support | IPC via named pipe |
Configuration File
File Location
The daemon discovers .localup.yml or .localup.yaml by searching:
- Current directory
- Parent directories (walking up to root)
Specifying a Custom Config Path
# Use a specific config file
localup daemon start --config /path/to/my-config.yml
# Or use a relative path
localup daemon start --config ./configs/production.yml
Configuration Structure
# Global defaults (applied to all tunnels)
defaults:
relay: "relay.example.com:4443" # Relay server address
token: "${LOCALUP_TOKEN}" # Auth token (env var supported)
local_host: "localhost" # Default local host
transport: "quic" # Transport protocol (quic, h2, websocket)
timeout_seconds: 30 # Connection timeout
# Tunnel definitions
tunnels:
# HTTP tunnel with subdomain
- name: api
port: 3000
protocol: http
subdomain: my-api
enabled: true # Optional, defaults to true
# HTTPS tunnel with subdomain
- name: frontend
port: 3001
protocol: https
subdomain: my-frontend
# HTTPS tunnel with custom domain
- name: production
port: 8080
protocol: https
custom_domain: api.mycompany.com # Requires DNS setup
# TCP tunnel
- name: database
port: 5432
protocol: tcp
remote_port: 15432 # Optional specific port
# TLS passthrough tunnel
- name: secure-backend
port: 8443
protocol: tls
sni_hostname: backend.example.com
# Tunnel with overrides
- name: staging
port: 4000
protocol: https
subdomain: staging-api
relay: "staging-relay.example.com:4443" # Override relay
token: "${STAGING_TOKEN}" # Override token
local_host: "127.0.0.1" # Override local host
enabled: false # Disabled by default
Token Resolution
Tokens are resolved in order:
- Tunnel-specific
tokenfield defaults.tokenfield- Environment variable expansion (
${LOCALUP_TOKEN}) - Saved token from
localup config set-token
# Save a default token
localup config set-token YOUR_AUTH_TOKEN
# Or use environment variable in config
# token: "${LOCALUP_TOKEN}"
export LOCALUP_TOKEN="your-token-here"
Daemon Commands
Starting the Daemon
# Start with auto-discovered config
localup daemon start
# Start with specific config file
localup daemon start --config /path/to/config.yml
# View logs during startup
localup daemon start 2>&1 | tee daemon.log
Stopping the Daemon
# Stop via IPC (graceful shutdown)
localup daemon stop
# Or use Ctrl+C in the daemon terminal
Graceful Shutdown: When stopped (via daemon stop or Ctrl+C), the daemon:
- Stops accepting new connections
- Sends disconnect messages to all active tunnels
- Waits for tunnels to close gracefully (up to 5 seconds each)
- Cleans up IPC socket and resources
All tunnels are properly closed - no orphaned connections.
Checking Status
# View running tunnels and their status
localup daemon status
Output example:
NAME PROTOCOL LOCAL PUBLIC URL STATUS UPTIME
api https :3000 https://my-api.tunnel.dev UP 15m 32s
frontend https :3001 https://my-frontend.tunnel.dev UP 15m 30s
database tcp :5432 tcp://tunnel.dev:15432 UP 15m 28s
Listing Configured Tunnels
# Show all tunnels from .localup.yml
localup daemon list
Output example:
Config: /path/to/.localup.yml
NAME PROTOCOL PORT SUBDOMAIN/DOMAIN ENABLED
----------------------------------------------------------------------
api https 3000 my-api yes
frontend https 3001 my-frontend yes
database tcp 5432 (port 15432) yes
staging https 4000 staging-api no
Tunnel Operations
Starting a Specific Tunnel
# Start a tunnel by name
localup daemon tunnel-start api
Stopping a Specific Tunnel
# Stop a tunnel by name
localup daemon tunnel-stop api
Reloading a Specific Tunnel
When you change a tunnel's configuration, reload it to apply changes:
# Reload a specific tunnel (stops and restarts with new config)
localup daemon tunnel-reload api
Reloading All Configuration
# Reload entire configuration
localup daemon reload
This will:
- Stop tunnels removed from config
- Start new tunnels added to config
- Keep unchanged tunnels running
Adding and Removing Tunnels
Adding a New Tunnel
# Add a tunnel to .localup.yml
localup daemon add backend --port 8080 --subdomain backend-api
# Add with custom domain
localup daemon add production --port 8080 --custom-domain api.mycompany.com
# Add with specific protocol
localup daemon add db --port 5432 --protocol tcp
After adding, reload to apply:
localup daemon reload
Removing a Tunnel
# Remove a tunnel from .localup.yml
localup daemon remove backend
After removing, reload to apply:
localup daemon reload
Environment Variables
| Variable | Description |
|---|---|
LOCALUP_TOKEN | Default authentication token |
TUNNEL_AUTH_TOKEN | Alternative token variable |
Use in config with ${VAR_NAME} syntax:
defaults:
token: "${LOCALUP_TOKEN}"
IPC Socket Location
The daemon creates an IPC socket for CLI communication:
| Platform | Location |
|---|---|
| macOS/Linux | ~/.localup/daemon.sock |
| Windows | \\.\pipe\localup-daemon |
Limitations
Single Daemon Instance
Only one daemon can run at a time per user. The daemon uses a fixed IPC socket path (~/.localup/daemon.sock), so starting a second daemon will fail with a socket binding error.
Workarounds:
- Combine all tunnels from multiple projects into a single
.localup.yml - Use absolute paths in tunnel configs if projects are in different directories
- Stop the current daemon before starting another with a different config
Custom Domains Require Pre-Registration
Custom domains must be registered in the relay's database before use. See Custom Domain Not Working for setup instructions.
Troubleshooting
Daemon Won't Start
-
Check if another daemon is running:
localup daemon statusIf a daemon is already running, stop it first:
localup daemon stop -
Remove stale socket file (Unix) - if daemon crashed without cleanup:
rm ~/.localup/daemon.sock -
Check configuration syntax:
localup daemon list # Will show parse errors -
Verify config file exists:
ls -la .localup.yml .localup.yaml 2>/dev/null
Tunnel Not Connecting
-
Check relay server is accessible:
nc -zv relay.example.com 4443 -
Verify authentication token:
localup config get-token -
Check tunnel status:
localup daemon status
Custom Domain Not Working
Custom domains require pre-registration before use. The relay validates that the domain exists in the custom_domains database table with an active status.
Setup steps:
-
Register the domain via relay API or admin dashboard:
curl -X POST https://relay.example.com/api/domains \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -d '{"domain": "api.mycompany.com"}' -
Set up DNS pointing to the relay server:
api.mycompany.com. IN CNAME relay.example.com. # or api.mycompany.com. IN A <relay-ip-address> -
Wait for certificate provisioning (if using ACME/Let's Encrypt)
- Domain status changes from
pendingtoactive - Check status via API or admin dashboard
- Domain status changes from
-
Connect your tunnel
Error messages:
| Error | Cause |
|---|---|
Custom domain 'X' is not registered | Domain not in database |
Custom domain 'X' exists but status is pending | Certificate still provisioning |
Custom domain 'X' exists but status is failed | Certificate provisioning failed |
Custom domain 'X' exists but status is expired | Certificate expired, needs renewal |
Development mode: If the relay has no database configured, custom domain validation is skipped (allows testing without setup).
Example Workflows
Development Setup
# .localup.yml
defaults:
relay: "relay.localup.io:4443"
tunnels:
- name: api
port: 3000
protocol: https
subdomain: dev-api
- name: frontend
port: 3001
protocol: https
subdomain: dev-frontend
# Start development servers
npm run dev:api &
npm run dev:frontend &
# Start tunnels
localup daemon start
Production with Custom Domains
# .localup.yml
defaults:
relay: "relay.mycompany.com:4443"
token: "${PRODUCTION_TOKEN}"
tunnels:
- name: api
port: 8080
protocol: https
custom_domain: api.mycompany.com
- name: webhooks
port: 8081
protocol: https
custom_domain: webhooks.mycompany.com
Mixed Protocols
defaults:
relay: "relay.example.com:4443"
tunnels:
# HTTP API
- name: api
port: 3000
protocol: https
subdomain: api
# Database access
- name: postgres
port: 5432
protocol: tcp
remote_port: 15432
# Redis access
- name: redis
port: 6379
protocol: tcp
remote_port: 16379
Related Documentation:
- Getting Started Guide - Installation and basic setup
- TCP Relay - Port-based routing for databases
- HTTP/HTTPS Relay - Web application tunnels