Deployment
Run the funnel server
The server is a single binary that handles HTTP API, QUIC tunnel connections, and optionally TLS termination.
Minimal startup
With the embedded Turso database (no external dependencies):
funnel-server --seed-api-keyThis starts the server on port 8080 (HTTP) and 4433 (QUIC), creates an embedded database at ./funnel.db, and prints a seed API key to stdout.
With PostgreSQL
funnel-server \
--database-url postgres://user:pass@localhost/funnel \
--seed-api-keyMigrations run automatically on startup. The server verifies schema version compatibility before accepting connections.
Configuration
All options can be set via CLI flags or environment variables.
| Flag | Env | Default | Description |
|---|---|---|---|
--host | FUNNEL_HOST | 0.0.0.0 | Bind address |
--port | FUNNEL_PORT | 8080 | HTTP port |
--quic-port | FUNNEL_QUIC_PORT | 4433 | QUIC port for tunnel connections |
--database-url | DATABASE_URL | - | PostgreSQL connection URL |
--db-max-connections | FUNNEL_DB_MAX_CONNECTIONS | 10 | Connection pool size |
--turso-db-path | FUNNEL_TURSO_DB_PATH | ./funnel.db | Embedded database path |
--seed-api-key | FUNNEL_SEED_API_KEY | false | Create a seed API key on startup |
--initial-admin-email | FUNNEL_INITIAL_ADMIN_EMAIL | - | Auto-promote this email to admin on first login |
--enable-tcp-tunnels | FUNNEL_ENABLE_TCP_TUNNELS | false | Enable TCP/TLS tunnel support |
--stream-port-min | FUNNEL_STREAM_PORT_MIN | 10000 | Lowest port for TCP tunnel allocation |
--stream-port-max | FUNNEL_STREAM_PORT_MAX | 60000 | Highest port for TCP tunnel allocation |
For TLS and OAuth options, see TLS and authentication.
TCP tunnels
TCP tunnels are disabled by default because they allocate ports directly on the server. To enable them:
funnel-server --enable-tcp-tunnelsWhen enabled, tunnels allocate ports from the stream-port-min to stream-port-max range. Make sure these ports are open in your firewall:
funnel-server --enable-tcp-tunnels --stream-port-min 20000 --stream-port-max 20100
sudo ufw allow 20000:20100/tcpWithout --enable-tcp-tunnels, clients requesting TCP or TLS tunnels receive an unsupported_tunnel_type error.
Database choice
PostgreSQL is the production choice. It supports concurrent access, has proper ACID guarantees, and scales with connection pooling.
Embedded Turso (libsql) is useful for development, single-user setups, or environments where running PostgreSQL is impractical. Data is stored in a single file. No external process needed.
If --database-url is set, PostgreSQL is used. Otherwise the server falls back to the embedded database at --turso-db-path.
Docker
OCI images are published for linux/amd64 and linux/arm64:
docker run \
-p 8080:8080 \
-p 4433:4433/udp \
-p 10000-60000:10000-60000 \
ghcr.io/karol-broda/funnel-serverThe port range 10000-60000 is for TCP tunnels. If you don't need TCP tunnels, omit it. To use a smaller range:
docker run \
-p 8080:8080 \
-p 4433:4433/udp \
-p 20000-20100:20000-20100 \
-e FUNNEL_STREAM_PORT_MIN=20000 \
-e FUNNEL_STREAM_PORT_MAX=20100 \
ghcr.io/karol-broda/funnel-serverNixOS
For declarative NixOS deployments with systemd hardening, see the NixOS module.