Version: 2.6.0 | Last Updated: 2026-04-20
Share local services over HTTPS with anyone, anywhere. No port forwarding, no firewall rules, no certificates to manage.
For the list of changes in each release, see CHANGELOG.md (authoritative, Keep a Changelog format). GitHub release pages on .asd and asd-cli mirror the relevant section per release.
- Welcome
- Quick Start
- Understanding HTTPS Tunnels
- Three Ways to Create Tunnels
- Web Terminal (ttyd)
- VS Code Server (codeserver)
- Security & Authentication
- Access Patterns
- Troubleshooting
- Reference Links
- Tunnel Protocols
- Plugins & Extensibility
- Resources & Community
- Vault — Secret Management
- Docker Containers
ASD CLI creates secure HTTPS tunnels from your local machine to the internet. With one command, you can:
- Share a local development server with a teammate
- Receive webhook callbacks from external APIs (payment providers, CI/CD pipelines, etc.)
- Access your terminal or VS Code from any browser
- Monitor all services from a built-in dashboard (
asd net) - Demo your work without deploying
- Developers sharing work-in-progress with teammates
- Teams needing remote access to development environments
- Anyone who wants to access local services from anywhere
This manual teaches you how to:
- Expose any local port as a public HTTPS URL
- Run a web-based terminal (ttyd) for remote shell access
- Run VS Code in a browser (code-server) for remote development
- Secure your services with authentication
ASD CLI is cross-platform. For detailed feature status, see FEATURE_MATURITY.md.
Quick Status:
- Linux - Primary platform, extensively tested
- macOS/Windows - Functional, actively improving
- Android (Termux) - Supported, see um_termux.md
Contributing: Found an issue on your platform? We welcome bug reports and contributions at our GitHub repository.
ASD creates secure tunnels from your local machine to the internet.
HTTP Tunneling (default):
- Web apps, REST APIs, WebSockets
- Your service stays local, gets public HTTPS URL
- Zero port-forwarding on your firewall
TCP Tunneling (via direct SSH):
- Databases (PostgreSQL, MySQL, Redis)
- SSH servers, custom protocols
- Use direct SSH:
ssh -p 2223 -R 5432:localhost:5432 user@tunnel.asd.sh - Note:
asd exposeis HTTP-only; TCP requires direct SSH commands
Key Use Cases:
- Share localhost with teammates in 30 seconds
- Expose services in Docker/K8s containers
- Create terminal access (ttyd) to any machine
- Test webhooks from external services
Get a public URL in seconds.
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/asd-engineering/asd-cli/main/install.sh | bashWindows CMD (recommended):
curl -fsSL https://raw.githubusercontent.com/asd-engineering/asd-cli/main/install.cmd -o %TEMP%\install.cmd && %TEMP%\install.cmdWindows PowerShell:
Note: The
irm | iexpattern may be blocked by Windows Defender (AMSI). If so, use the CMD method above.
irm https://raw.githubusercontent.com/asd-engineering/asd-cli/main/install.ps1 | iexSelf-update (all platforms):
asd updateWindows notes:
- Binary installs to
%LOCALAPPDATA%\asd\bin\asd.exe. Add to PATH if prompted.- For the best experience, use Git Bash (recommended), Windows Terminal + PowerShell, or CMD.exe.
- If you skip the PATH prompt, run directly:
%LOCALAPPDATA%\asd\bin\asd --version
Run any local server. Example with Python:
python -m http.server 3000Or Node.js:
npx serve -p 3000asd expose 3000You'll see output like:
Local: http://localhost:3000
Caddy: http://app.localhost
Tunnel: https://app-abc123.cicd.eu1.asd.engineer
That's it! Share the tunnel URL with anyone. It's HTTPS, secure, and works from anywhere.
Before using tunnels, you need credentials. Choose one:
Quick testing (no account):
# Get 5-minute ephemeral credentials
curl -X POST https://asd.engineer/functions/v1/create-ephemeral-token
# Use the returned tunnel_client_id and tunnel_client_secretFor longer sessions: Create tunnel credentials at asd.host → Account → Tunnel Tokens, then set in .env:
ASD_TUNNEL_TOKEN=your-token
ASD_TUNNEL_USER=your-userNote: CLI-based login (
asd login) is coming in the next release.
When you run asd expose 3000, here's what happens:
flowchart LR
subgraph Your Computer
A[localhost:3000]
end
subgraph ASD Cloud
B[asd.engineer<br/>HTTPS + auto-cert]
end
subgraph Anyone
C[User Browser]
end
A -->|SSH tunnel| B
C -->|HTTPS| B
- ASD creates an SSH tunnel from your machine to the ASD cloud
- ASD cloud provides a public HTTPS URL with automatic certificates
- Anyone with the URL can access your local service securely
Your tunnel URL looks like:
https://<prefix>-<client-id>.<region>.asd.engineer
^^^^^^^ ^^^^^^^^^^ ^^^^^^
| | |
Your name Unique ID Server location
(optional)
Example: https://myapp-x7k9m2.cicd.eu1.asd.engineer
- HTTPS - Encrypted connection, no certificate setup needed
- Public URL - Accessible from anywhere on the internet
- Firewall bypass - No port forwarding or router configuration
- Instant setup - Works in seconds, not hours
Tunnel duration varies by plan. Tunnels auto-reconnect if connection drops.
See asd.host/pricing for current plan details.
Choose the method that fits your workflow:
| Need | Method | Complexity |
|---|---|---|
| Share something RIGHT NOW | asd expose |
Simplest |
| Daily development workflow | asd.yaml config |
Medium |
| CI/CD automation | Tunnel tokens | Advanced |
The fastest way to share a local port.
Basic usage:
asd expose 3000With a custom name:
asd expose 3000 --name myapp
# Result: https://myapp-abc123.cicd.eu1.asd.engineerThe --name sets a prefix. The URL is always <name>-<client-id>.cicd.eu1.asd.engineer.
Direct tunnel (skip Caddy):
asd expose 3000 myapp --direct
# Creates tunnel directly without local Caddy proxyUse --direct when you only need the public tunnel URL and don't need local routing through Caddy.
Managing exposed services:
asd expose list # List all exposed services (shows tunnel URLs!)
asd expose stop myapp # Stop by name
asd expose stop 3000 # Stop by portExample asd expose list output:
myapp
Port: 3000
Local: http://myapp.localhost
Tunnel: https://myapp-abc123.cicd.eu1.asd.engineer
Status: ✅ Online
Uptime: 🕐 2h 15m
Interactive prompts:
When running in a terminal, asd expose will interactively prompt you if:
- The tunnel binary needs to be installed
- You need to login to create tunnels
This makes first-time setup seamless without pre-configuration.
When to use: Quick demos, one-off sharing, testing webhooks.
For ongoing development, define services in your project.
Setup:
cd your-project
asd init # Creates asd.yaml and workspaceEdit asd.yaml:
version: 1
project:
name: "my-app"
network:
services:
frontend:
dial: "127.0.0.1:3000"
host: "app.localhost" # Local hostname
public: true # Enable tunnel
subdomain: "frontend" # Tunnel subdomain prefix
api:
dial: "127.0.0.1:8080"
paths: ["/api"] # Path-based routing
public: true
subdomain: "api"Automatic environment variables:
Services can declare env vars that are automatically written to .env when tunnels are created. This is useful for apps that need their own public URL (e.g., OAuth callbacks, CORS origins):
network:
services:
frontend:
dial: "127.0.0.1:5173"
public: true
subdomain: "frontend"
env:
PUBLIC_URL: "${{ macro.exposedOrigin() }}"
AUTH_CALLBACK_URL: "${{ macro.exposedOrigin() }}/auth/callback"After asd net apply, .env will contain:
PUBLIC_URL=https://frontend-abc123.cicd.eu1.asd.engineer
AUTH_CALLBACK_URL=https://frontend-abc123.cicd.eu1.asd.engineer/auth/callbackThe parameterless exposedOrigin() reads the subdomain from the same service definition. Values support all template macros: ${{ env.* }} for env vars, ${{ macro.* }} for dynamic values. If tunnel credentials aren't available yet, the env var is simply skipped (not written as empty).
See Template Macros Reference for the full list of available macros including port allocation, random strings, bcrypt hashing, and more.
Apply and start:
asd net apply --caddy --tunnel
asd net # Open TUI dashboardTUI Controls:
| Key | Action |
|---|---|
Tab |
Cycle tabs (Services, Projects, Logs) |
Enter |
Actions menu for selected service |
Ctrl+R |
Refresh health status |
Ctrl+Q |
Quit |
| Arrow keys | Navigate services |
When to use: Daily development, team projects, multiple services.
Access your terminal from any browser, anywhere.
ttyd gives you a full shell session in your web browser. Perfect for:
- Remote debugging from your phone
- Sharing terminal access with teammates
- Accessing your dev machine from anywhere
1. Set credentials (in .env or environment):
ASD_TTYD_USERNAME=admin
ASD_TTYD_PASSWORD=your-secure-password2. Start the terminal:
asd terminal start3. Access it:
| Method | URL |
|---|---|
| Local Direct | http://localhost:<port>/ |
| Via Caddy | http://asd.localhost/asde/terminal/ |
| Via Tunnel | https://xxx.cicd.eu1.asd.engineer/asde/terminal/ |
4. Stop when done:
asd terminal stopAfter starting, asd terminal shows you a menu with all access URLs:
Terminal (ttyd) - Web Terminal Access
=====================================
Status: Running on port 7681
Access URLs:
Local: http://admin:***@localhost:7681/
Caddy: http://asd.localhost/asde/terminal/
Tunnel: https://hub-abc123.cicd.eu1.asd.engineer/asde/terminal/
Actions:
[1] Open in browser
[2] Copy tunnel URL
[3] Stop terminal
| Access Method | When to Use |
|---|---|
| Local Direct | On the same machine |
| Caddy Route | Local network, other devices on LAN |
| Tunnel | Remote access from anywhere |
All ttyd settings go in your .env file:
| Variable | Default | Description |
|---|---|---|
ASD_TTYD_PORT |
(auto) | Port number (auto-assigned if not set) |
ASD_TTYD_USERNAME |
(required) | Login username |
ASD_TTYD_PASSWORD |
(required) | Login password |
ASD_TTYD_SHELL_CMD |
bash |
Shell to run (bash, zsh, fish) |
ASD_TTYD_CWD |
workspace | Starting directory |
ASD_TTYD_PATH |
/ |
URL path prefix |
Example .env:
ASD_TTYD_USERNAME=developer
ASD_TTYD_PASSWORD=dev-secret-123
ASD_TTYD_SHELL_CMD=zshTo access your terminal from anywhere:
1. Start terminal and tunnel:
asd terminal start
asd net apply --tunnel2. Get the tunnel URL:
asd terminal
# Shows tunnel URL in the menu3. Share the URL - Anyone with the URL and credentials can access your terminal.
ttyd is security-sensitive. It provides full shell access to your machine.
- Always use strong passwords - At least 12 characters, mixed case/numbers
- Don't share credentials - Give each user their own account if possible
- Use tunnels carefully - Anyone with the URL + password has shell access
- Stop when not needed -
asd terminal stop
When project-level authentication is enabled, ttyd automatically gets protected.
"Missing username or password":
# Set in .env:
ASD_TTYD_USERNAME=admin
ASD_TTYD_PASSWORD=your-password"Port already in use":
asd terminal stop
# Or manually: kill the process using the port
lsof -i :7681 | grep ttyd
kill <pid>"Can't connect via tunnel":
# Ensure tunnel is active:
asd net # Check hub service has tunnel URL
asd net apply --tunnel # Re-apply if needed"Binary not found":
asd init # Re-downloads binariesRun Visual Studio Code in your browser with full extension support.
code-server runs VS Code in a browser. Get the full VS Code experience from any device:
- Edit code on a tablet or Chromebook
- Use your powerful desktop from a laptop
- Share a development environment with teammates
| Platform | Status | Notes |
|---|---|---|
| Linux | ✅ Supported | Primary platform, recommended |
| macOS | ✅ Supported | Works natively |
| Windows (WSL) | ✅ Supported | Use WSL2 with Ubuntu/Debian |
| Windows (native) | ❌ Not available | No native Windows builds |
Windows Users: code-server does not provide native Windows builds. To use code-server on Windows:
- Recommended: Install WSL2 with Ubuntu
- Run ASD CLI inside WSL:
asd code start - Access from your Windows browser at the provided URL
We are actively exploring alternatives for native Windows support. Options under consideration include:
- VS Code tunnels (official Microsoft remote development)
- OpenVSCode Server
- Other browser-based IDE solutions
1. Start code-server:
asd code start2. Access it:
| Method | URL |
|---|---|
| Local Direct | http://localhost:<port>/ |
| Via Caddy | http://asd.localhost/asde/codeserver/ |
| Via Tunnel | https://xxx.cicd.eu1.asd.engineer/asde/codeserver/ |
3. Stop when done:
asd code stopSame pattern as ttyd. Run asd code for the interactive menu:
VS Code Server - Browser-based IDE
==================================
Status: Running on port 8080
Access URLs:
Local: http://localhost:8080/
Caddy: http://asd.localhost/asde/codeserver/
Tunnel: https://hub-abc123.cicd.eu1.asd.engineer/asde/codeserver/
Actions:
[1] Open in browser
[2] Copy tunnel URL
[3] Stop code-server
Configure in .env:
| Variable | Default | Description |
|---|---|---|
ASD_CODESERVER_PORT |
(auto) | Port number |
ASD_CODESERVER_AUTH |
none |
Auth mode: none or password |
ASD_CODESERVER_PASSWORD |
- | Password (when auth=password) |
ASD_CODESERVER_WORKSPACE |
project root | Folder to open |
Example .env:
ASD_CODESERVER_AUTH=password
ASD_CODESERVER_PASSWORD=vscode-secret-123No authentication (local only):
ASD_CODESERVER_AUTH=none
# Safe for local-only access1. Enable password authentication:
# In .env:
ASD_CODESERVER_AUTH=password
ASD_CODESERVER_PASSWORD=your-secure-password2. Start code-server and tunnel:
asd code start
asd net apply --tunnel3. Get the tunnel URL:
asd code
# Shows tunnel URL in menucode-server provides the full VS Code experience:
- Extensions - Install from Open VSX marketplace
- Integrated Terminal - Full shell access
- Git Integration - Full source control
- Settings Sync - Your preferences everywhere
- Multiple Files - Tabs, split views, everything
code-server is security-sensitive. It provides code editing and terminal access.
- Use password auth for remote access - Set
ASD_CODESERVER_AUTH=password - Strong passwords - At least 12 characters
- Project-level auth - Enable
basic_authinasd.yamlfor extra protection - Stop when not needed -
asd code stop
code-server can have two authentication layers:
- Caddy basic auth - Protects the route (browser login prompt)
- codeserver internal auth - Application-level password
Known limitation: When using Caddy basic auth (basic_auth in asd.yaml), the credentials are NOT forwarded to code-server. Caddy strips the Authorization header before proxying.
This means:
- Caddy validates the user at the gateway
- code-server doesn't know who logged in via Caddy
Recommendation for remote access:
Use code-server's internal authentication instead of (or in addition to) Caddy basic auth:
# In .env
ASD_CODESERVER_AUTH=password
ASD_CODESERVER_PASSWORD=your-secure-passwordThis ensures code-server manages its own session, regardless of Caddy's auth layer.
"Can't install extensions":
code-server uses Open VSX, not the Microsoft marketplace. Most popular extensions are available, but some Microsoft-specific ones aren't.
"Port conflict":
asd code stop
# Or kill manually:
lsof -i :8080 | grep code-server
kill <pid>"Authentication failing":
# Check your auth settings:
grep ASD_CODESERVER .env
# Ensure you're using the right password"Slow performance":
- Close unused tabs and terminals
- Disable unnecessary extensions
- Use a stable network connection
Protect your services from unauthorized access.
ASD provides three levels of security:
| Level | Who Can Access | When to Use |
|---|---|---|
| No Auth | Anyone with URL | Local development, testing |
| Basic Password | Anyone with URL + password | Remote access, demos |
| Tunnel Tokens | Authenticated users | CI/CD, automation |
flowchart LR
subgraph "Level 1: No Auth"
A1[Anyone with URL]
end
subgraph "Level 2: Basic Auth"
A2[URL + Password]
end
subgraph "Level 3: Tunnel Tokens"
A3[Authenticated Users]
end
A1 --> Local[Local Dev]
A2 --> Remote[Remote Access]
A3 --> CI[CI/CD Automation]
When you expose without service auth:
asd expose 3000
# → https://myapp-abc123.cicd.eu1.asd.engineerYour local service on localhost:3000 becomes accessible via a public HTTPS URL.
Traffic flow: Internet → HTTPS → SSH tunnel (encrypted) → Caddy → your service
Good for: Quick demos, teammate collaboration, trusted sharing
Add password for: Sensitive data, long-running tunnels, public demos
Safe for:
- Local-only access (
localhost) - Trusted networks
- Quick demos where you can rotate the URL
Not safe for:
- Services with sensitive data
- Long-running tunnels
- Production environments
Add HTTP Basic Authentication to your services.
Project-wide authentication:
# asd.yaml
network:
caddy:
basic_auth:
enabled: true
realm: "My Project"Set credentials in .env:
ASD_BASIC_AUTH_USERNAME=admin
ASD_BASIC_AUTH_PASSWORD=your-secure-password-hereWhat users see:
When accessing your service, browsers show a login dialog asking for username and password.
Per-service override:
# asd.yaml
network:
caddy:
basic_auth:
enabled: true
services:
public-api:
dial: "127.0.0.1:3000"
basic_auth:
enabled: false # No auth for this service
admin-panel:
dial: "127.0.0.1:8080"
basic_auth:
enabled: true
realm: "Admin Only"Some services are automatically treated as security-sensitive:
| Service | Default Behavior |
|---|---|
| ttyd | Always requires credentials |
| codeserver | Recommends password auth |
These services provide shell or code access - they should always have authentication when publicly accessible.
ttyd credentials:
ASD_TTYD_USERNAME=admin
ASD_TTYD_PASSWORD=your-ttyd-passwordcodeserver credentials:
ASD_CODESERVER_AUTH=password
ASD_CODESERVER_PASSWORD=your-code-passwordASD provides multiple authentication methods for tunnel access. Choose based on your environment:
| Method | Best For | Account Required |
|---|---|---|
asd login |
Interactive (laptop, desktop) | Yes |
asd login key |
CI/CD, headless servers | Yes (API key) |
| SSH key import | Docker, new machines | No (existing key) |
| Ephemeral token | Quick testing (5 min) | No |
| Tunnel token | Dashboard-created token | Yes |
The simplest way to authenticate. Opens a browser for OAuth:
asd login
# Opens browser → sign in → credentials saved automaticallyAfter login, all tunnel commands (asd expose, asd net apply --tunnel) work automatically.
asd auth status # Check if logged in
asd auth whoami # Show current user info
asd logout # Sign outFor headless environments (CI/CD, servers) where no browser is available:
# Pass key directly
asd login key sk_your_api_key_here
# Or via environment variable
export ASD_API_KEY=sk_your_api_key_here
asd login key
# Interactive prompt (when running in a terminal)
asd login key
# Enter API key: _Get your API key from asd.host → Account → API Keys.
Three ways to use your SSH key credentials inside Docker containers:
Option A: Volume mount (simplest)
Mount your credential directory into the container:
docker run -v ~/.config/asd/tunnel:/root/.config/asd/tunnel:ro my-image
# Inside container: asd expose 3000 ← just worksASD automatically resolves key paths even when the host path differs from the container path.
Option B: Environment variables
Pass SSH key content as env vars — no file mounting needed:
# Export credentials (convenience command)
eval $(asd auth export)
# Or with Docker flags
docker run \
$(asd auth export --docker) \
my-image asd expose 3000The asd auth export command outputs:
export ASD_TUNNEL_KEY="<base64-encoded-private-key>"
export ASD_TUNNEL_KEY_ID="<key-uuid>"
export ASD_TUNNEL_HOST="tunnel.asd.sh"
export ASD_TUNNEL_PORT="2222"Use --docker for Docker -e flag format instead of shell exports.
Option C: Import existing key
If you have a copy of your SSH key file (e.g., copied to a server):
# Auto-detect key_id from server (requires network)
asd init --key /path/to/private_key
# Or specify key_id explicitly (works offline)
asd init --key /path/to/private_key --key-id abc-123-defNo account needed. Get 5-minute credentials instantly:
curl -X POST https://asd.engineer/functions/v1/create-ephemeral-token
# Response includes:
# - tunnel_client_id: "guest-xyz123"
# - tunnel_client_secret: "abc123..."
# - expires_at: 5 minutes from now- Sign up at asd.host
- Go to Account → Tunnel Tokens → Create
- Set credentials in
.envor CI secrets:
ASD_TUNNEL_TOKEN=your-token-from-dashboard
ASD_TUNNEL_USER=your-user-id
asd expose 3000| Scenario | Recommended |
|---|---|
| Local development | No auth |
| Quick demo (< 1 hour) | No auth (URL is secret enough) |
| Remote access to your machine | Basic password |
| Sharing with teammates | Basic password |
| CI/CD pipelines | asd login key or SSH key env vars |
| Docker containers | Volume mount or asd auth export |
| Production | Don't use ASD tunnels! |
For ASD_BASIC_AUTH_PASSWORD, ASD_TTYD_PASSWORD, and ASD_CODESERVER_PASSWORD:
- Minimum 12 characters
- Mix of letters, numbers, symbols
- Never reuse passwords
- Don't commit to git - Use
.env(already gitignored)
Generate a strong password:
openssl rand -base64 24
# Example output: K7mX9pQr2sT8vW1yB4cF6dH3Every ASD service can be accessed three ways.
ASD uses Caddy as a local reverse proxy between the tunnel and your services:
Internet → ASD Cloud → SSH Tunnel → Caddy (local) → Your Service
↑
Security layer
Currently Available:
- ✅ HTTPS on all Caddy routes
- ✅ HTTP Basic Authentication (password protection)
- ✅ Health check endpoints
- ✅ Request routing (host + path based)
Configuration:
network:
caddy:
basic_auth:
enabled: trueASD Caddy Client: ASD includes npm tooling for Caddy API configuration.
These are planned but not yet implemented:
- ⏳ OIDC (OpenID Connect)
- ⏳ JWT validation at edge
- ⏳ LDAP / Active Directory
- ⏳ 2FA / MFA enforcement
- ⏳ Edge authentication (ASD Cloud level)
For current options, see BASIC_AUTH.md.
| Pattern | URL Example | Use Case |
|---|---|---|
| Local Direct | http://localhost:3000 |
Same machine |
| Caddy Route | http://asd.localhost/myapp/ |
Local network, LAN |
| Tunnel Remote | https://myapp-abc123.cicd.eu1.asd.engineer/ |
Anywhere |
flowchart TB
subgraph Access Patterns
direction TB
L[Local Direct<br/>localhost:3000]
C[Caddy Route<br/>app.localhost]
T[Tunnel Remote<br/>app-xxx.asd.engineer]
end
L --> App[Your App]
C --> Caddy[Caddy :80] --> App
T --> Cloud[ASD Cloud] --> Tunnel[SSH Tunnel] --> Caddy
Direct connection to the service port.
http://localhost:<port>/
Example: http://localhost:3000/
When to use:
- Developing on the same machine
- Maximum performance (no proxy)
- Debugging network issues
How it works:
Browser --> localhost:3000 --> Your App
Access through the local Caddy reverse proxy.
Host-based routing:
http://<service>.localhost/
Example: http://myapp.localhost/
Path-based routing:
http://asd.localhost/<path>/
Example: http://asd.localhost/api/
Built-in services use the /asde/ path prefix:
- terminal:
http://asd.localhost/asde/terminal/ - codeserver:
http://asd.localhost/asde/codeserver/
When to use:
- Multiple services with nice URLs
- Testing with realistic hostnames
- Accessing from other devices on LAN
How it works:
Browser --> Caddy (:80) --> localhost:3000 --> Your App
Access through the public HTTPS tunnel.
https://<prefix>-<id>.cicd.eu1.asd.engineer/
Example: https://myapp-abc123.cicd.eu1.asd.engineer/
When to use:
- Remote access from anywhere
- Sharing with external users
- Testing webhooks from external services
- Accessing from mobile devices
How it works:
Browser --> ASD Cloud --> SSH Tunnel --> Caddy --> Your App
(encrypted)
| Service | Local | Caddy | Tunnel |
|---|---|---|---|
| Your app | http://localhost:3000 |
http://myapp.localhost |
https://myapp-xxx.cicd.eu1.asd.engineer |
| terminal | http://localhost:7681 |
http://asd.localhost/asde/terminal/ |
https://hub-xxx.../asde/terminal/ |
| codeserver | http://localhost:8080 |
http://asd.localhost/asde/codeserver/ |
https://hub-xxx.../asde/codeserver/ |
For quick expose:
asd expose 3000
# Output shows all URLsFor project services:
asd net
# TUI shows all service URLsFor built-in services:
asd terminal # Shows ttyd URLs
asd code # Shows codeserver URLsCommand not found: asd
The CLI isn't installed or not in PATH.
# Reinstall
curl -fsSL https://raw.githubusercontent.com/asd-engineering/asd-cli/main/install.sh | bash
# Or check PATH
echo $PATHWindows: asd not found after install
The install directory may not be in PATH. Either:
Option 1: Run with full path:
%LOCALAPPDATA%\asd\bin\asd --versionOption 2: Add to PATH (run in Admin PowerShell):
$installDir = "$env:LOCALAPPDATA\asd\bin"
$path = [Environment]::GetEnvironmentVariable("PATH", "User")
[Environment]::SetEnvironmentVariable("PATH", "$path;$installDir", "User")Restart your terminal after adding to PATH.
Windows: Antivirus flags asd as suspicious
ASD's binary installer downloads and manages tool binaries (Caddy, ttyd, GitHub CLI, etc.) on your behalf. This involves operations that antivirus heuristics sometimes flag:
- Downloading executables from the internet
- Extracting zip archives via PowerShell
- Creating
.cmdwrapper scripts for Unix compatibility
Why this happens: Windows Defender and other AV engines use behavioral heuristics that flag patterns common in both legitimate DevOps tools and malware. Compiled JavaScript runtimes (Bun/Node.js) are especially prone to false positives.
What we do to prevent it:
- All PowerShell calls use
execFileSync("powershell.exe", [args])with argument arrays (not string interpolation) - Browser opening uses
explorer.exe(notcmd /c start) - No direct
cmd.exeorpowershell.exespawning for shell commands - No detached hidden processes (
detached: true+stdio: "ignore") - Automated AV pattern scanning in CI catches risky code patterns before release
If your AV blocks asd:
- Whitelist the install directory: Add
%LOCALAPPDATA%\asd\to your AV exclusion list - Report the false positive: Submit
asd.exeto your AV vendor's false positive portal:- Microsoft Defender (select "Software developer")
- BitDefender
- Verify integrity: Run
asd --versionto confirm the binary is authentic
Windows: Post-installation details
See Quick Start > Step 1: Install for all install commands (PowerShell, CMD, Linux/macOS).
After installation:
Binary downloads (Caddy, ttyd, gh, busybox) are managed automatically. On Windows:
- Zip archives are extracted via PowerShell
Expand-Archive(AV-safe) - A
bash.cmdwrapper is created for Unix shell compatibility via BusyBox - All binaries are stored in
%LOCALAPPDATA%\asd\bin\
Port already in use
Another process is using the port.
# Find what's using the port
lsof -i :3000
# Kill it
kill <pid>
# Or use a different port
asd expose 3001Tunnel not connecting
Authentication or network issues.
# Check auth status
asd auth status
# Re-login
asd login
# Reset tunnels
asd net expose resetService not appearing in TUI
Registry out of sync.
# Refresh services
asd net refresh
# Or full reset
rm .asd/workspace/network/registry.json
asd net applyCaddy won't start
Caddy configuration issue.
# Stop and remove state
asd caddy stop
rm -rf .asd/workspace/caddy/
# Restart
asd caddy start
asd net applyFull Reset (Nuclear Option)
When everything is broken:
# Stop all processes
pkill -f "caddy run"
pkill -f "asd-tunnel"
# Remove all state
rm -rf .asd/workspace/
# Reinitialize
asd init
asd net apply --caddy --tunnelDebug Mode
Enable verbose logging:
ASD_DEBUG=1 asd net applyView Logs
asd logs caddy # Caddy proxy logs
asd logs tunnel # Tunnel logs
# Logs are in .asd/workspace/logs/- GitHub Issues: https://github.com/asd-engineering/asd-cli/issues
- Documentation: https://asd.host/docs
Quick reference of most-used commands:
| Command | Description |
|---|---|
asd init |
Initialize project workspace |
asd run <task> |
Run automation task from asd.yaml |
asd expose <port> |
Expose a port instantly |
asd login |
Login for tunnels (OAuth; asd login key for API-key / CI flow) |
asd net |
Open network TUI |
asd net apply |
Apply configuration |
asd terminal |
Web terminal menu |
asd code |
VS Code server menu |
asd config validate |
Validate asd.yaml configuration |
asd skill install |
Install AI assistant skills |
asd update |
Update ASD CLI |
Full command reference: um_commands.md
- asd.yaml options: um_asd_yaml.md
- Basic auth details: BASIC_AUTH.md
- Tunnel architecture: TUNNELING.md
- All services: um_service.md
- Feature maturity: FEATURE_MATURITY.md
- Android/Termux: um_termux.md
Throughout the documentation:
| Symbol | Meaning |
|---|---|
| ✅ | Production - fully tested, recommended |
| 🟢 | Stable - works reliably |
| 🟡 | Beta - functional, may have rough edges |
| 🟠 | Alpha - experimental |
ASD supports different tunnel protocols for different use cases.
Most services use HTTP tunneling over ports 80 and 443:
- Web applications
- REST APIs
- WebSocket connections (like ttyd)
- GraphQL endpoints
HTTP tunnels are the default and require no special configuration:
# asd.yaml - HTTP tunnel (default)
network:
services:
my-app:
dial: "127.0.0.1:3000"
public: true # Creates HTTPS tunnelTCP port forwarding works via direct SSH commands. Any port other than 80/443 is forwarded as raw TCP.
Use cases:
- Databases (PostgreSQL, MySQL, Redis)
- SSH servers
- Custom binary protocols
- Game servers
Examples:
# Expose PostgreSQL on a random public port
ssh -p 2223 -R 5432:localhost:5432 $ASD_CLIENT_ID@tunnel.asd.sh
# Expose MySQL
ssh -p 2223 -R 3306:localhost:3306 $ASD_CLIENT_ID@tunnel.asd.sh
# Expose Redis
ssh -p 2223 -R 6379:localhost:6379 $ASD_CLIENT_ID@tunnel.asd.shThe server assigns a random public port and reports it back in the SSH session output.
Note: The asd expose command currently supports HTTP tunnels only. For TCP:
- Use direct SSH forwarding as shown above
- Authenticate via
asd loginfirst to get credentials
Private TCP aliases (e.g., ssh -R mydb:5432:localhost:5432 ...) require the --tcp-aliases flag on the server. ASD public servers have this disabled for security. Self-hosted servers can enable it.
| Protocol | Ports | Use Case | Encryption |
|---|---|---|---|
| HTTP/HTTPS | 80, 443 | Web apps, APIs, WebSockets | TLS via Caddy |
| TCP | Any (random assigned) | Databases, SSH, custom | SSH tunnel encryption |
| TCP Alias | Private (self-hosted only) | Team-only access | SSH tunnel + no public port |
WebSocket connections work automatically through HTTP tunnels. This is how ttyd (web terminal) works:
- Browser connects via HTTPS to tunnel URL
- HTTP connection upgrades to WebSocket
- Caddy's reverse proxy handles the upgrade correctly
- Real-time bidirectional communication established
No special configuration needed - Caddy's vulcand/oxy forwarding library handles WebSocket upgrades transparently.
Example: ttyd WebSocket flow:
Browser --HTTPS--> Tunnel --> Caddy --WS--> ttyd:7681
(upgrade handled)
| Scenario | Protocol | Example |
|---|---|---|
| Web app demo | HTTP | asd expose 3000 |
| API testing | HTTP | public: true in asd.yaml |
| Database access | TCP | ssh -R 5432:localhost:5432 ... |
| SSH access | TCP | ssh -R 22:localhost:22 ... |
| Team-only database | TCP Alias | Self-hosted with --tcp-aliases |
For maximum control, you can bypass asd and connect directly via OpenSSH:
# Using sshpass for non-interactive auth
sshpass -p "$ASD_CLIENT_SECRET" ssh \
-o PreferredAuthentications=password \
-o StrictHostKeyChecking=no \
-p 2223 \
-R "myapp:80:localhost:3000" \
"$ASD_CLIENT_ID@s1.eu1.asd.engineer"When to use:
- CI/CD pipelines needing minimal dependencies
- Custom scripting scenarios
- Debugging connection issues
You can request tokens programmatically via the ASD API:
# Request an ephemeral token (5-minute TTL, no auth required)
curl -X POST https://asd.engineer/functions/v1/create-ephemeral-token \
-H "Content-Type: application/json"For authenticated API access with longer-lived tokens, see API Reference.
ASD includes built-in Supabase support. When enabled, ASD automatically detects running Supabase services, routes them through Caddy, and makes them available in the asd net TUI.
project:
name: "my-app"
plugins: [supabase]When enabled, ASD:
- Detects running Supabase services
- Registers them in the network
- Creates Caddy routes for each service
- Makes them available in the
asd netTUI
Services:
| Service | Port | Description |
|---|---|---|
supabase:studio |
54323 | Database GUI |
supabase:kong |
54321 | API Gateway |
supabase:mailpit |
54324 | Email testing UI |
# Bootstrap Supabase + extract env vars to .env
asd supabase bootstrap
# Start/stop Supabase services
asd supabase start
asd supabase stop
# Extract environment variables to .env
asd supabase extractThe bootstrap command extracts credentials from Supabase and adds them to .env:
PUBLIC_SUPABASE_ANON_KEY=eyJ...
SUPABASE_SERVICE_ROLE_KEY=eyJ...
SUPABASE_API_URL_LOCAL=http://127.0.0.1:54321
SUPABASE_DB_URL_LOCAL=postgresql://postgres:postgres@127.0.0.1:54322/postgres
# ... and moreWe plan to add more integrations over time (Redis, Meilisearch, MinIO, etc.). If you need a specific integration sooner, let us know.
- GitHub Issues: Report bugs, request features
- Contact: hello@asd.engineer
Install:
curl -fsSL https://raw.githubusercontent.com/asd-engineering/asd-cli/main/install.sh | bashInitialize workspace:
asd init --yesStart development:
asd run dev # Run 'dev' task from asd.yamlExpose a service:
asd expose 3000Diagnose connection:
asd diagnoseSwitch tunnel server:
asd server # Interactive picker
asd server list # Show all serversWeb terminal:
asd terminal startVS Code in browser:
asd code startStop everything:
asd down # Stop workspace services🟠 Alpha Feature — Ready for testing. API may change between releases. Report issues via GitHub.
ASD Vault provides encrypted secret management backed by Supabase Vault (pgsodium). Secrets are encrypted at rest and never stored in plaintext on disk.
# Requires authentication
asd login
# Store a secret
asd vault set DATABASE_URL "postgres://user:pass@host:5432/db"
# Retrieve a secret
asd vault get DATABASE_URL
# List all secrets (metadata only, no values)
asd vault list# From argument
asd vault set API_KEY "sk-abc123"
# From stdin (for multiline or piped values)
cat ~/.kube/config | asd vault set kubeconfig --stdin
# From file
asd vault set tls/cert --file ./cert.pem
# With category and description
asd vault set db/PASSWORD "s3cret" --category database --description "Production DB password"
# Organisation-scoped (shared with team)
asd vault set SHARED_TOKEN "xyz" --scope org# Run a command with secrets as environment variables
asd vault run --env-file .env.tpl -- node server.js
# Template file (.env.tpl) uses asd:// references:
# DATABASE_URL=asd://db/PASSWORD
# API_KEY=asd://API_KEY
# Substitute references in a config file
asd vault inject config.tpl config.json# Import all files from a directory (file names become secret names)
asd vault import ./secrets/
# Export all secrets back to files (round-trip faithful)
asd vault export ./backup/- Personal (
--scope user, default): Only you can access - Organisation (
--scope org): Shared with org admins
See asd.host/pricing for current vault quotas and addon options.
Manage secrets at /workspace/vault/ in the admin dashboard. The web UI shows secret metadata (name, category, scope) but never displays decrypted values — use asd vault get from the CLI for that.
Secrets are encrypted at rest using pgsodium AEAD (XChaCha20-Poly1305). The encryption root key is managed by Supabase KMS and never stored in the database. Access is enforced via Row Level Security per user/organisation.
ASD provides pre-built Docker containers for portable development environments and lightweight tunnel automation. For the full reference, see um_docker.md.
A complete development environment in a container (~750 MB). Includes ASD CLI, Caddy, asd-tunnel, ttyd, VS Code Server, Claude Code, and tmux.
# Interactive sandbox (recommended)
asd sandbox shell
# Autostart mode: starts all services, drops into interactive menu
docker run -it --network host \
-e ASD_API_KEY=sk_your_key \
-v "$(pwd):/workspace" \
asd-stack.cr.de-fra.ionos.com/asd-sandbox:latest autostart
# Autostart + expose port 3000 via tunnel
docker run -it --network host \
-e ASD_API_KEY=sk_your_key \
-v "$(pwd):/workspace" \
asd-stack.cr.de-fra.ionos.com/asd-sandbox:latest \
autostart expose 3000Features:
- Interactive menu with system info, running services, and active tunnel URLs
- Tmux session management (detach with
Ctrl+B D, reattach withdocker start -ai) - Automatic login and tunnel provisioning via
ASD_API_KEY - Project workspace mounted at
/workspace
A minimal (~20 MB) scratch container for CI/CD pipelines and automation:
# Expose port 3000 — that's it
docker run --rm --network host \
asd-stack.cr.de-fra.ionos.com/asd-tunnel:latest \
connect --api-key sk_your_key -F myapp:3000
# Run in background for CI
docker run -d --network host --name tunnel \
asd-stack.cr.de-fra.ionos.com/asd-tunnel:latest \
connect --api-key sk_your_key -F myapp:3000Zero OS, zero shell — just the statically compiled asd-tunnel binary and CA certificates.
See um_docker.md for environment variables, volume mounts, GitHub Actions examples, and more.
For detailed technical reference, see the documents in .asd/docs/.
