| name | asd-expose |
| description | Guide for exposing services via ASD tunnels — asd expose, asd.yaml network config, with/without Caddy, auth rules |
| user_invocable | true |
| arg_description | What to expose, e.g. 'port 3000', 'angular dev server', 'expose without caddy', 'add tunnel to asd.yaml' |
ASD Expose — Service Exposure Guide
Expose any local service to the internet via ASD tunnels. Two approaches: quick ad-hoc or declarative via asd.yaml.
Live Documentation
Always consult the ASD CLI's built-in docs — they match your installed version:
asd rules routing
asd rules auth
asd schema
asd schema --ai
Install ASD skills for deeper AI assistance:
asd skills install
Quick Expose (Ad-Hoc)
Expose any port instantly — no asd.yaml changes needed:
asd expose 3000
asd expose 3000 myapp --name api
asd expose 3000 myapp --auth=basic
asd expose 3000 myapp --auth=none
asd expose 3000 --local-only
Manage Exposed Services
asd expose list
asd expose stop api
asd expose stop 3000
asd expose cleanup
Declarative Expose (asd.yaml)
For persistent services, define them in asd.yaml under network.services:
tunnels:
mode: 'caddy'
network:
caddy:
enable: true
tls:
enabled: true
auto: true
services:
my-api:
dial: 127.0.0.1:3000
host: api.localhost
subdomain: ${{ env.ENV_PREFIX }}api
tunnelPort: 3000
tunnelProtocol: http
public: true
description: My API server
Then apply:
asd net apply --seed --caddy --tunnel
asd net apply --caddy
asd net apply --tunnel
With Caddy vs Without Caddy
With Caddy (Recommended)
All traffic flows through Caddy for TLS + auth:
Internet -> ASD Tunnel -> Caddy:443 -> basic auth -> reverse_proxy -> service:port
tunnels:
mode: 'caddy'
- Single tunnel serves all services via path/subdomain routing
- Basic auth applied automatically for private services
- TLS termination at Caddy
Without Caddy (Direct)
Tunnel connects directly to service port — no auth layer:
asd expose 3000 --local-only
Warning: Direct tunneling (--direct or tunnels.mode: 'direct') bypasses Caddy entirely. No auth middleware applies. Only use for public services that handle their own auth.
Architecture Rule
Caddy owns auth. Services (ttyd, code-server) skip their own auth when Caddy handles it. One auth layer at the proxy. Never tunnel directly to service ports unless you explicitly want no auth.
Auth Configuration
Auth rules are seeded from asd.yaml service definitions:
public value | Auth behavior |
|---|
true | No auth required |
false | Caddy basic auth (auto-generated credentials) |
Override credentials via .env:
ASD_BASIC_AUTH_USER=myuser
ASD_BASIC_AUTH_PASS=mypass
Sync after changing:
asd caddy sync-auth
This Project's Services
Current asd.yaml exposes:
| Service | Port | Subdomain | Public |
|---|
angular:dev | 4200 | {prefix}app | Yes |
supabase:studio | 54323 | {prefix}studio | Yes |
codeserver | auto | via hub | No (basic auth) |
ttyd | auto | via hub | No (basic auth) |
Useful Commands
asd net
asd caddy list
asd caddy routes
asd caddy config