GitHub - asd-engineering/asd-cli · GitHub
Skip to content

asd-engineering/asd-cli

Repository files navigation

ASD CLI User Manual

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.


Table of Contents

  1. Welcome
  2. Quick Start
  3. Understanding HTTPS Tunnels
  4. Three Ways to Create Tunnels
  5. Web Terminal (ttyd)
  6. VS Code Server (codeserver)
  7. Security & Authentication
  8. Access Patterns
  9. Troubleshooting
  10. Reference Links
  11. Tunnel Protocols
  12. Plugins & Extensibility
  13. Resources & Community
  14. Vault — Secret Management
  15. Docker Containers

1. Welcome

What ASD Does

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

Who It's For

  • Developers sharing work-in-progress with teammates
  • Teams needing remote access to development environments
  • Anyone who wants to access local services from anywhere

What You'll Learn

This manual teaches you how to:

  1. Expose any local port as a public HTTPS URL
  2. Run a web-based terminal (ttyd) for remote shell access
  3. Run VS Code in a browser (code-server) for remote development
  4. Secure your services with authentication

OS & Platform Support

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.

What is Tunneling?

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 expose is 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

2. Quick Start

Get a public URL in seconds.

Step 1: Install

Linux / macOS:

curl -fsSL https://raw.githubusercontent.com/asd-engineering/asd-cli/main/install.sh | bash

Windows CMD (recommended):

curl -fsSL https://raw.githubusercontent.com/asd-engineering/asd-cli/main/install.cmd -o %TEMP%\install.cmd && %TEMP%\install.cmd

Windows PowerShell:

Note: The irm | iex pattern 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 | iex

Self-update (all platforms):

asd update

Windows 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

Step 2: Start Your Local Server

Run any local server. Example with Python:

python -m http.server 3000

Or Node.js:

npx serve -p 3000

Step 3: Expose It

asd expose 3000

You'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.

First-Time Setup

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_secret

For longer sessions: Create tunnel credentials at asd.host → Account → Tunnel Tokens, then set in .env:

ASD_TUNNEL_TOKEN=your-token
ASD_TUNNEL_USER=your-user

Note: CLI-based login (asd login) is coming in the next release.


3. Understanding HTTPS Tunnels

How It Works

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
Loading
  1. ASD creates an SSH tunnel from your machine to the ASD cloud
  2. ASD cloud provides a public HTTPS URL with automatic certificates
  3. Anyone with the URL can access your local service securely

Tunnel URL Format

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

What You Get Automatically

  • 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 Lifetime

Tunnel duration varies by plan. Tunnels auto-reconnect if connection drops.

See asd.host/pricing for current plan details.


4. Three Ways to Create Tunnels

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

Method 1: Quick Expose (asd expose)

The fastest way to share a local port.

Basic usage:

asd expose 3000

With a custom name:

asd expose 3000 --name myapp
# Result: https://myapp-abc123.cicd.eu1.asd.engineer

The --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 proxy

Use --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 port

Example 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.

Method 2: Project Config (asd.yaml)

For ongoing development, define services in your project.

Setup:

cd your-project
asd init                  # Creates asd.yaml and workspace

Edit 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/callback

The 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 dashboard

TUI 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.


5. Web Terminal (ttyd)

Access your terminal from any browser, anywhere.

What is ttyd?

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

Quick Start

1. Set credentials (in .env or environment):

ASD_TTYD_USERNAME=admin
ASD_TTYD_PASSWORD=your-secure-password

2. Start the terminal:

asd terminal start

3. 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 stop

Three Ways to Access

After 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

Configuration

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=zsh

Remote Access Setup

To access your terminal from anywhere:

1. Start terminal and tunnel:

asd terminal start
asd net apply --tunnel

2. Get the tunnel URL:

asd terminal
# Shows tunnel URL in the menu

3. Share the URL - Anyone with the URL and credentials can access your terminal.

Security Notes

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.

Troubleshooting

"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 binaries

6. VS Code Server (codeserver)

Run Visual Studio Code in your browser with full extension support.

What is codeserver?

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 Availability

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:

  1. Recommended: Install WSL2 with Ubuntu
  2. Run ASD CLI inside WSL: asd code start
  3. 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

Quick Start

1. Start code-server:

asd code start

2. 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 stop

Three Ways to Access

Same 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

Configuration

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-123

No authentication (local only):

ASD_CODESERVER_AUTH=none
# Safe for local-only access

Remote Access Setup

1. Enable password authentication:

# In .env:
ASD_CODESERVER_AUTH=password
ASD_CODESERVER_PASSWORD=your-secure-password

2. Start code-server and tunnel:

asd code start
asd net apply --tunnel

3. Get the tunnel URL:

asd code
# Shows tunnel URL in menu

Features

code-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

Security Notes

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_auth in asd.yaml for extra protection
  • Stop when not needed - asd code stop

Authentication Layers

code-server can have two authentication layers:

  1. Caddy basic auth - Protects the route (browser login prompt)
  2. 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-password

This ensures code-server manages its own session, regardless of Caddy's auth layer.

Troubleshooting

"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

7. Security & Authentication

Protect your services from unauthorized access.

Security Levels

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]
Loading

Level 1: Open Access (Default)

When you expose without service auth:

asd expose 3000
# → https://myapp-abc123.cicd.eu1.asd.engineer

Your 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

Level 2: Basic Password Protection

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-here

What 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"

Security-Sensitive Services

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-password

codeserver credentials:

ASD_CODESERVER_AUTH=password
ASD_CODESERVER_PASSWORD=your-code-password

Level 3: CLI Login & Tunnel Credentials

ASD 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

Method 1: Interactive Login (asd login)

The simplest way to authenticate. Opens a browser for OAuth:

asd login
# Opens browser → sign in → credentials saved automatically

After 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 out

Method 2: API Key Login (asd login key)

For 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.

Method 3: SSH Key in Docker & Containers

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 works

ASD 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 3000

The 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-def

Method 4: Ephemeral Token (Quick Testing)

No 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

Method 5: Tunnel Token (Dashboard)

  1. Sign up at asd.host
  2. Go to Account → Tunnel Tokens → Create
  3. Set credentials in .env or CI secrets:
ASD_TUNNEL_TOKEN=your-token-from-dashboard
ASD_TUNNEL_USER=your-user-id
asd expose 3000

Choosing the Right Level

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!

Password Best Practices

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: K7mX9pQr2sT8vW1yB4cF6dH3

8. Access Patterns

Every ASD service can be accessed three ways.

Caddy as Security Layer

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: true

ASD Caddy Client: ASD includes npm tooling for Caddy API configuration.

Future Authentication (Roadmap)

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.

Overview

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
Loading

Pattern 1: Local Direct

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

Pattern 2: Caddy Routes

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

Pattern 3: Tunnel Remote

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)

Built-in Service URLs

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/

Finding Your URLs

For quick expose:

asd expose 3000
# Output shows all URLs

For project services:

asd net
# TUI shows all service URLs

For built-in services:

asd terminal    # Shows ttyd URLs
asd code        # Shows codeserver URLs

9. Troubleshooting

Common Issues

Command 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 $PATH
Windows: asd not found after install

The install directory may not be in PATH. Either:

Option 1: Run with full path:

%LOCALAPPDATA%\asd\bin\asd --version

Option 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 .cmd wrapper 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 (not cmd /c start)
  • No direct cmd.exe or powershell.exe spawning 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:

  1. Whitelist the install directory: Add %LOCALAPPDATA%\asd\ to your AV exclusion list
  2. Report the false positive: Submit asd.exe to your AV vendor's false positive portal:
  3. Verify integrity: Run asd --version to 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.cmd wrapper 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 3001
Tunnel not connecting

Authentication or network issues.

# Check auth status
asd auth status

# Re-login
asd login

# Reset tunnels
asd net expose reset
Service not appearing in TUI

Registry out of sync.

# Refresh services
asd net refresh

# Or full reset
rm .asd/workspace/network/registry.json
asd net apply
Caddy won't start

Caddy configuration issue.

# Stop and remove state
asd caddy stop
rm -rf .asd/workspace/caddy/

# Restart
asd caddy start
asd net apply
Full 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 --tunnel
Debug Mode

Enable verbose logging:

ASD_DEBUG=1 asd net apply
View Logs
asd logs caddy      # Caddy proxy logs
asd logs tunnel     # Tunnel logs

# Logs are in .asd/workspace/logs/

Getting Help


10. Reference Links

Command Reference

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

Configuration Reference

Service Reference

Platform Guides

Status Legend

Throughout the documentation:

Symbol Meaning
Production - fully tested, recommended
🟢 Stable - works reliably
🟡 Beta - functional, may have rough edges
🟠 Alpha - experimental

11. Tunnel Protocols

ASD supports different tunnel protocols for different use cases.

HTTP Tunneling (Default)

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 tunnel

TCP Tunneling

TCP 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.sh

The 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 login first 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.

Tunnel Protocol Comparison

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 Support

WebSocket connections work automatically through HTTP tunnels. This is how ttyd (web terminal) works:

  1. Browser connects via HTTPS to tunnel URL
  2. HTTP connection upgrades to WebSocket
  3. Caddy's reverse proxy handles the upgrade correctly
  4. 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)

When to Use Each

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

Tips & Tricks: Faster Connections

Direct OpenSSH (Advanced)

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

API Token Requests

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.


12. Supabase Integration

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.

Enable in asd.yaml

project:
  name: "my-app"
  plugins: [supabase]

What you get

When enabled, ASD:

  1. Detects running Supabase services
  2. Registers them in the network
  3. Creates Caddy routes for each service
  4. Makes them available in the asd net TUI

Services:

Service Port Description
supabase:studio 54323 Database GUI
supabase:kong 54321 API Gateway
supabase:mailpit 54324 Email testing UI

Commands

# 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 extract

The 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 more

Future Integrations

We plan to add more integrations over time (Redis, Meilisearch, MinIO, etc.). If you need a specific integration sooner, let us know.


13. Resources & Community

Get in Touch


Quick Reference Card

Install:

curl -fsSL https://raw.githubusercontent.com/asd-engineering/asd-cli/main/install.sh | bash

Initialize workspace:

asd init --yes

Start development:

asd run dev               # Run 'dev' task from asd.yaml

Expose a service:

asd expose 3000

Diagnose connection:

asd diagnose

Switch tunnel server:

asd server                # Interactive picker
asd server list           # Show all servers

Web terminal:

asd terminal start

VS Code in browser:

asd code start

Stop everything:

asd down                  # Stop workspace services

14. Vault — Secret Management

🟠 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.

Quick Start

# 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

Commands

Command Description
asd vault list List secrets (name, category, scope — no values)
asd vault get <name> Print decrypted value to stdout
asd vault set <name> [value] Create or update a secret
asd vault delete <name> Soft-delete a secret
asd vault import <directory> Bulk import secrets from a directory
asd vault export <directory> Export all secrets to files
asd vault inject <template> Substitute asd:// references in a template
asd vault run --env-file <tpl> -- <cmd> Run command with secrets injected as env vars

Storing Secrets

# 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

Injecting Secrets into Processes

# 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 & Export

# 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/

Scopes

  • Personal (--scope user, default): Only you can access
  • Organisation (--scope org): Shared with org admins

Plan Limits

See asd.host/pricing for current vault quotas and addon options.

Web Dashboard

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.

Security

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.


15. Docker Containers

ASD provides pre-built Docker containers for portable development environments and lightweight tunnel automation. For the full reference, see um_docker.md.

ASD Sandbox

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 3000

Features:

  • Interactive menu with system info, running services, and active tunnel URLs
  • Tmux session management (detach with Ctrl+B D, reattach with docker start -ai)
  • Automatic login and tunnel provisioning via ASD_API_KEY
  • Project workspace mounted at /workspace

ASD Tunnel (Lightweight)

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:3000

Zero 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/.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

Contributors