DDEV Share Providers README ================ #ddev-generated Share providers are scripts that create internet-accessible tunnels to your local DDEV project. ## Built-in Providers - **ngrok** (default): Uses ngrok.com service - **cloudflared**: Uses Cloudflare Tunnel (free, no account required) ## Usage ```bash # Use default provider (ngrok) ddev share # Use specific provider ddev share --provider=cloudflared # Set default provider for project ddev config --share-default-provider=cloudflared ``` ## Configuration In `.ddev/config.yaml`: ```yaml share_default_provider: ngrok share_provider_args: "--basic-auth username:password" ``` ## Customizing Providers ### Take Ownership of Built-in Provider 1. Edit the provider script (e.g., `ngrok.sh`) 2. Remove the `#ddev-generated` line at the top 3. Make your changes 4. DDEV will never overwrite this file again ### Create Custom Variant ```bash # Copy built-in provider cp .ddev/share-providers/ngrok.sh .ddev/share-providers/my-ngrok.sh # Edit my-ngrok.sh: # - Remove '#ddev-generated' line # - Customize as needed # Use your variant ddev share --provider=my-ngrok ``` ### Create New Provider Create a new executable script in `.ddev/share-providers/`: ```bash #!/usr/bin/env bash set -euo pipefail # Start your tunnel tool mytunnel http "$DDEV_LOCAL_URL" & TUNNEL_PID=$! # Capture public URL (however your tool exposes it) URL=$(get-tunnel-url) # Output URL to stdout (CRITICAL: first line only) echo "$URL" # Wait for tunnel to exit wait $TUNNEL_PID ``` ## Provider Script Contract Every share provider must follow this contract: ### Input (Environment Variables) - `DDEV_LOCAL_URL`: Local URL to tunnel (e.g., `http://127.0.0.1:8080`) - `DDEV_SHARE_ARGS`: Provider-specific arguments (optional) - All standard DDEV environment variables ### Output - **stdout**: Public URL (first line only - captured by DDEV) - **stderr**: Logs, status messages (passed through to user) ### Lifecycle 1. Validate tool is installed 2. Validate required environment variables 3. Start tunnel process in background 4. Capture public URL (via API, stdout, file, etc.) 5. Output URL to stdout 6. Wait for tunnel process to exit ### Signal Handling - Must handle SIGINT (Ctrl+C) and SIGTERM gracefully - Use `trap` to cleanup background processes on exit - Example: ```bash cleanup() { if kill -0 $PID 2>/dev/null; then kill $PID 2>/dev/null || true fi } trap cleanup EXIT ``` ### Error Handling - Exit with non-zero status on errors - Write error messages to stderr (not stdout) - Provide helpful error messages (missing tool, timeout, etc.) ## Examples ### Simple Provider (stdout parsing) ```bash #!/usr/bin/env bash set -euo pipefail # Start tunnel, parse URL from output localtunnel --port 8080 | grep -o 'https://[^[:space:]]*' | head -1 # Note: This simple example doesn't handle background process or signals ``` ### API Polling Provider ```bash #!/usr/bin/env bash set -euo pipefail # Start tunnel mytunnel http "$DDEV_LOCAL_URL" & TUNNEL_PID=$! trap "kill $TUNNEL_PID 2>/dev/null || true" EXIT # Poll API for URL for i in {1..30}; do URL=$(curl -s http://localhost:4040/api | jq -r '.url' || echo "") if [[ -n "$URL" ]]; then echo "$URL" break fi sleep 1 done wait $TUNNEL_PID ``` ### File-based Provider ```bash #!/usr/bin/env bash set -euo pipefail # Start tunnel (writes URL to file) mytunnel --url-file /tmp/tunnel.url "$DDEV_LOCAL_URL" & TUNNEL_PID=$! trap "kill $TUNNEL_PID 2>/dev/null || true" EXIT # Wait for URL file for i in {1..30}; do if [[ -f /tmp/tunnel.url ]]; then cat /tmp/tunnel.url break fi sleep 1 done wait $TUNNEL_PID ``` ## Hooks Integration After the tunnel URL is captured, DDEV sets the `DDEV_SHARE_URL` environment variable and runs pre-share hooks. This allows you to: - Register webhooks with external services - Update DNS records - Send notifications - Configure SSO callbacks Example `.ddev/config.yaml`: ```yaml hooks: pre-share: - exec: | echo "Tunnel URL: $DDEV_SHARE_URL" curl -X POST https://api.example.com/webhook \ -d "url=$DDEV_SHARE_URL" ``` ## Troubleshooting ### Provider not found ``` Error: share provider 'foo' not found ``` **Solution**: Check that `.ddev/share-providers/foo.sh` exists and is executable: ```bash ls -la .ddev/share-providers/ chmod +x .ddev/share-providers/foo.sh ``` ### Provider outputs no URL ``` Error: provider 'ngrok' did not output a URL ``` **Causes**: - Tool not installed or not in PATH - Tool requires authentication (e.g., ngrok account) - API endpoint not responding - Timeout (30 seconds) **Debug**: Run the provider script directly: ```bash export DDEV_LOCAL_URL=http://127.0.0.1:8080 .ddev/share-providers/ngrok.sh ``` ### Invalid URL output ``` Error: provider 'foo' output invalid URL: not-a-url ``` **Solution**: Provider must output URL starting with `http://` or `https://` ## Platform Compatibility - **Linux**: Fully supported - **macOS**: Fully supported - **Windows**: Requires Git Bash or WSL Provider scripts should use `bash` (not `sh`) and avoid platform-specific commands where possible. ## More Information - [DDEV Sharing Documentation](https://docs.ddev.com/en/stable/users/topics/sharing/) - [ngrok Documentation](https://ngrok.com/docs) - [Cloudflare Tunnel Documentation](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/)