Tailscale Integration
Tailscale gives you a private network without port forwarding, VPN gateways, or firewall rules. Every device on your tailnet can reach every other device by name, with encrypted WireGuard tunnels negotiated automatically.
Elide has deep Tailscale integration. You can bind to your Tailscale IP, get a Tailscale-issued TLS certificate, expose your server to the public internet via Funnel, authenticate requests by Tailscale identity, or run as a standalone Tailscale node with no daemon installed. This is not a bolt-on -- Tailscale networking is a first-class path through the runtime.
Quick start
The simplest path: serve your app on your tailnet with automatic TLS.
elide orb --config server.pkl --tailscaleElide detects your node's Tailscale IP and DNS name, provisions a TLS certificate from the Tailscale CA, binds to port 443 on the Tailscale IP, and registers MagicDNS for all tailnet peers. The output tells you where to find it:
Serving on https://my-laptop.tail1234.ts.net (tailnet IP 100.64.0.42)
MagicDNS registered: 5 peers in tailnet 'tail1234.ts.net'Any device on your tailnet can now reach your server at https://my-laptop.tail1234.ts.net with a browser-trusted certificate. No certificate setup, no DNS configuration, no firewall changes.
Daemon mode vs. standalone mode
Elide supports two fundamentally different ways of connecting to a Tailscale network. Understanding when to use each one will save you time.
Daemon mode (--tailscale)
Daemon mode talks to the local tailscaled daemon over its Unix domain socket. This is the mode you want when Tailscale is already installed on the machine. It gives you the full feature set: browser-trusted TLS certificates from the Tailscale CA, Funnel for public exposure, and whois-based identity authentication.
tailscaled running, machine enrolled in a tailnet (tailscale up).
elide orb --config server.pkl --tailscaleStandalone mode (--tailscale-direct)
Standalone mode embeds the TS2021 control plane client directly in the Elide binary. No daemon, no sidecar, no system-wide installation. Elide authenticates with a pre-auth key, polls the network map, discovers peers, registers MagicDNS entries, and spawns a userspace WireGuard data plane via boringtun.
Prerequisites: A pre-auth key from the Tailscale admin console. Nothing else. elide orb --config server.pkl --tailscale-direct --tailscale-auth-key tskey-auth-...When to use which
| Feature | Daemon mode | Standalone mode |
|---|---|---|
| Tailscale IP assignment | Yes | Yes |
| MagicDNS for peer names | Yes | Yes |
| Network map polling | Yes | Yes |
| WireGuard data plane | Kernel | Userspace (boringtun) |
| DISCO peer discovery + STUN | Via tailscaled | Built-in |
| Browser-trusted TLS (Tailscale CA) | Yes | No (use —self-signed or —auto-tls) |
| Tailscale Funnel | Yes | No |
| Whois peer identification | Yes | Not yet |
| TUN device (system-wide tunnel) | N/A | Yes (elide tun up or orb —tun) |
| ACL packet filtering | Handled by tailscaled | Parsed from netmap (not yet applied) |
Generating a pre-auth key
Create one in the Tailscale admin console or via the API:
# Reusable, ephemeral, tagged key (recommended for automation)
tailscale api keys create --reusable --ephemeral --tags tag:elide-serverPass it via --tailscale-auth-key (on orb) or --auth-key (on tun up), or set the TAILSCALE_AUTH_KEY environment variable.
Tailscale Funnel
Funnel exposes your server to the entire internet -- not just your tailnet -- through Tailscale's relay infrastructure. Anyone with the URL can reach your server at https://your-node.tail1234.ts.net.
elide orb --config server.pkl --funnelThe --funnel flag implies --tailscale. When Funnel is active, Elide configures the Tailscale serve config via the local API to route incoming HTTPS traffic to the local server. The configuration is cleaned up automatically on shutdown.
When Funnel is active, whois identity authentication is disabled -- public internet traffic does not carry Tailscale identity.
MagicDNS
When any Tailscale mode is active, Elide builds a DNS resolver from the Tailscale peer table and registers it as the process-wide resolver. All DNS lookups within Elide -- HTTP client requests, TLS connections, STUN, DERP -- can resolve tailnet names without going through getaddrinfo or system DNS.
The resolution order is straightforward:
1. If the hostname matches a known tailnet peer (e.g., other-node.tail1234.ts.net), resolve it directly from the cached peer table.
2. Otherwise, fall back to system DNS.
3. IP literals bypass DNS entirely.
The resolver is thread-safe and registered once at startup. In standalone mode, the peer table refreshes on every network map poll (background thread), so new peers appear within seconds of joining the tailnet.
TLS certificates
How Elide handles TLS depends on the Tailscale mode:
Daemon mode provisions browser-trusted certificates from the Tailscale CA (backed by Let's Encrypt). These work in every browser and every HTTP client with no extra configuration. This is the zero-friction path to real HTTPS on your tailnet. Standalone mode cannot obtain certificates from the Tailscale CA. Use--self-signed to generate an ephemeral TLS certificate for the tailnet domain:
elide orb --config server.pkl --tailscale-direct --tailscale-auth-key tskey-auth-...The self-signed cert uses ECDSA P-256 with 365-day validity, includes the tailnet domain and all Tailscale IPs as Subject Alternative Names, and is cached to disk (regenerated when older than 30 days). It will trigger browser warnings but is fine for development and internal services.
Identity-based authentication
Daemon mode includes a whois authentication middleware that identifies the user and device behind every incoming request. For each request from a Tailscale IP, Elide resolves:| Field | Description | Example |
|---|---|---|
login_name | The user's login (typically an email) | alice@example.com |
display_name | Human-readable name | Alice |
node_hostname | Short hostname of the originating device | alice-laptop |
node_dns_name | Fully-qualified tailnet DNS name | alice-laptop.tail1234.ts.net |
tags | ACL tags applied to the originating node | ["tag:server", "tag:prod"] |
os | Operating system of the originating node | linux |
user_id | Numeric user ID (if available) | 123 |
inject_headers is enabled (the default for --tailscale).
Access control policies
Elide supports per-route access control policies evaluated against the resolved Tailscale identity. Policies use a deny-first model:
1. All deny rules are checked first. If any deny rule matches, the request is rejected. 2. If no deny rule matches, the first matching allow rule grants access. 3. If no rules match at all, the request is denied (closed by default).| Rule | Description |
|---|---|
AllowAll | Unconditionally allow all authenticated tailnet users |
DenyAll | Unconditionally deny |
AllowUsers(["alice@example.com"]) | Allow specific users by login name |
DenyUsers(["blocked@example.com"]) | Deny specific users by login name |
AllowTags(["tag:web"]) | Allow nodes carrying specific ACL tags |
DenyTags(["tag:quarantine"]) | Deny nodes carrying specific ACL tags |
AllowAll and DenyTags(["tag:quarantine"]) will allow everyone except quarantined nodes. Tag matching is exact -- tag:web-staging does not match tag:web.
DERP relay
DERP (Designated Encrypted Relay for Packets) relays traffic when direct peer-to-peer WireGuard connections are not possible due to NAT. Elide can run a DERP relay in two ways.
Alongside your server: elide orb --config server.pkl --derp
elide orb --config server.pkl --derp --derp-port 4000The relay runs independently of the HTTP server. Default port is 3340.
As a standalone relay: elide tun derp
elide tun derp --port 4000 --host 0.0.0.0
elide tun derp --mesh-with relay2.example.com,relay3.example.com
elide tun derp --tls-cert /path/to/cert.pem --tls-key /path/to/key.pemThe standalone relay supports multi-region mesh, TLS, and STUN.
WireGuard tunnel (elide tun)
The tun command provides system-wide WireGuard tunneling. This creates a real TUN device and routes traffic through the tailnet.
elide tun requires root or CAP_NET_ADMIN for TUN device creation. Linux and macOS only.
Bringing up a tunnel
elide tun up --auth-key tskey-auth-...This authenticates with Tailscale, fetches the network map, installs MagicDNS, creates a TUN device (elide0 by default), adds routes for all peer AllowedIPs, spawns the WireGuard data plane, starts background control polling, and blocks until SIGINT/SIGTERM.
# Advertise this node as an exit node
elide tun up --auth-key tskey-auth-... --exit -node
# Route all traffic through a specific peer
elide tun up --auth-key tskey-auth-... --use-exit -node alice-laptop elide tun up --auth-key tskey-auth-... --advertise-routes 10.0.0.0/24,192.168.1.0/24 --accept-routesChecking tunnel status
elide tun status
elide tun status --peers --routes
elide tun status --jsonCLI reference
Flags on elide serve
| Flag | Default | Description |
|---|---|---|
—tailscale | false | Bind to Tailscale IP, provision TLS, register MagicDNS. Requires tailscaled. |
—funnel | false | Expose via Tailscale Funnel. Implies —tailscale. |
—tailscale-direct | false | Standalone Tailscale node (no daemon). Requires —tailscale-auth-key. |
—tailscale-auth-key | none | Pre-auth key for standalone mode. Also reads TAILSCALE_AUTH_KEY env var. |
—self-signed | false | Generate self-signed TLS for the tailnet domain. ECDSA P-256, 365-day validity, cached. |
—derp | false | Start a DERP relay alongside the HTTP server. |
—derp-port | 3340 | Port for the DERP relay. |
Flags on elide orb
| Flag | Default | Description |
|---|---|---|
—tailscale | false | Bind to Tailscale IP, provision TLS, enable identity auth. Unix only. |
—funnel | false | Expose via Funnel. Unix only. Disables whois auth. |
—tailscale-direct | false | Standalone Tailscale node. Requires —tailscale-auth-key. |
—tailscale-auth-key | none | Pre-auth key for standalone mode. |
—tun | false | Create a TUN device for system-wide routing (with —tailscale-direct). |
—derp | false | Start a DERP relay alongside the server. |
—derp-port | 3340 | DERP relay port. |
Flags on elide tun up
| Flag | Default | Description |
|---|---|---|
—auth-key | required | Pre-authentication key for Tailscale. |
—control-url | Tailscale production | Custom control server URL. |
—dev | elide0 | TUN device name. |
—mtu | 1280 | MTU for the TUN interface. |
—accept-routes | false | Accept subnet routes from peers. |
—exit-node | false | Advertise as exit node. |
—use-exit-node | none | Route all traffic through a specific peer. |
—advertise-routes | none | Advertise subnets (comma-separated CIDRs). |
—self-signed | false | Generate self-signed TLS certificate. |
—serve | none | Also start an HTTP server on the tunnel. |
—json | false | Output in JSON format. |
Troubleshooting
"Cannot connect to tailscaled"
Daemon mode requires the tailscaled daemon to be running. Verify with:
tailscale statusIf it is not running, start it (sudo tailscaled or via your init system) and ensure the machine is enrolled (tailscale up).
On macOS, if you installed Tailscale from the App Store, the daemon runs as part of the app. Make sure the Tailscale app is open.
"Pre-auth key rejected" in standalone mode
Pre-auth keys expire. Check the key's status in the Tailscale admin console. If the key is single-use and was already consumed, create a new one. For automation, use reusable ephemeral keys.
Funnel not working
Funnel requires explicit ACL policy approval. In your Tailscale ACL policy, ensure the node (or its tags) is allowed to use Funnel. See the Tailscale Funnel docs for the exact ACL syntax.
Also confirm you are in daemon mode. Funnel is not available in standalone mode.
Self-signed certificate warnings
Expected behavior in standalone mode. The self-signed cert is valid and encrypted, but not issued by a trusted CA. For browser access, click through the warning. For programmatic access, pass your HTTP client's equivalent of --insecure or add the cert to your trust store.
If you need trusted certificates, use daemon mode -- the Tailscale CA issues Let's Encrypt-backed certs automatically.
MagicDNS names not resolving
MagicDNS is registered at Elide startup. If a peer joined the tailnet after Elide started, the name may not be in the resolver yet. In standalone mode, the peer table refreshes on every map poll (roughly every 30 seconds). In daemon mode, the peer table comes from tailscaled and updates are immediate.
If names still do not resolve, check that MagicDNS is enabled in your Tailscale admin console DNS settings.
---
Examples
Serve on your tailnet (daemon)
elide orb --config server.pkl --tailscaleExpose to the public internet via Funnel
elide orb --config server.pkl --funnelStandalone node with self-signed TLS
elide orb --config server.pkl --tailscale-direct --tailscale-auth-key tskey-auth-... --self-signedStandalone node in a container
FROM ghcr.io/elide-dev/elide:latest
COPY ./dist /app
CMD ["elide", "orb", "--config", "/app/server.pkl", "--tailscale-direct", "--tailscale-auth-key", "${TAILSCALE_AUTH_KEY}", "--no-tui"]System-wide WireGuard tunnel
elide tun up --auth-key tskey-auth-... --accept-routesTailnet server with DERP relay
elide orb --config server.pkl --tailscale --derpStandalone DERP relay
elide tun derp --port 4000 --host 0.0.0.0---
See also
- elide serve -- Full HTTP server documentation: TLS, static files, reverse proxy, middleware
- CLI Reference -- Complete reference for all Elide commands and global options