awsx2
A fast AWS management CLI and interactive TUI built in Rust. Manages EC2 instances, SSM tunnels, local reverse proxies, and AWS Client VPN with SAML authentication through a single tool.
awsx2 # launch interactive TUI
awsx2 list # CLI mode — list all instances
Features
- Dual-mode — full-screen TUI for interactive use, CLI for scripts and automation
- EC2 management — list, start, stop, force-stop, switch instance types (GPU/CPU)
- Smart tunneling — SSM port-forwarding with ALB-aware routing, security group analysis, and bastion fallback
- Client VPN — AWS Client VPN with SAML/SSO authentication, headless browser MFA, and automatic DNS configuration
- Reverse proxy — auto-configures nginx +
/etc/hostsso internal URLs work directly in the browser - Cross-platform — macOS (Homebrew) and Linux (Debian/Ubuntu, RHEL/CentOS, Amazon Linux)
Prerequisites
- AWS CLI v2 with SSO configured
- Session Manager Plugin
- SSM Agent running on target EC2 instances
- nginx (only for
--proxyfeature) - Chromium/Chrome (only for
vpn connect— headless SAML auth) - AWS VPN Client or OpenVPN (only for
vpn connect)
Installation
CLI Usage
Run awsx2 <command>. Instance commands accept --name or read from the INSTANCE_NAME environment variable.
Instance Management
Authentication
DNS Resolution
Traces the full path: hostname → DNS → ALB → target group → EC2/Fargate backend.
Tunnels
Direct tunnel to an EC2 instance by name pattern:
# ^pattern ^local ^remote
URL tunnel with smart ALB resolution (auto-detects bastion and remote port):
The resolution chain: URL → ALB match → healthy target group → security group rules → SSM-online hop instance. Falls back to trying all available bastions if ALB resolution fails.
URL tunnel with reverse proxy so the URL works directly in the browser:
This additionally:
- Writes an nginx config forwarding port 80 → localhost:8080
- Adds
127.0.0.1 app.internal.example.comto/etc/hosts - Reloads nginx and flushes DNS cache
DNS tunnel (resolve hostname, tunnel to the resolved IP):
Remote tunnel via a specific bastion to an arbitrary host:
# ^bastion ^target ^local ^remote
Tunnel management:
VPN
Connect to AWS Client VPN endpoints that use SAML/SSO authentication. Credentials are saved locally so you only need to enter the MFA code each time.
# One-time setup — saves credentials to ~/.config/awsx2/vpn.json
# Connect (prompts for MFA if not provided)
# Check status
# Disconnect
The connect flow:
- Sends initial auth to VPN server to obtain SAML challenge URL
- Launches headless Chromium to complete SSO login (username, password, MFA)
- Captures SAML response via local HTTP callback
- Reconnects to VPN with the SAML token (uses AWS patched OpenVPN if available)
- Configures DNS routing via
resolvectlfor the specified domain
Requires sudo -E to create the tun interface and configure DNS. The -E flag preserves your AWS environment variables.
TUI
Launch with awsx2 (no arguments). Navigate with keyboard — no mouse required.
Global Keys
| Key | Action |
|---|---|
Tab / Shift+Tab |
Switch tabs |
? |
Toggle help overlay |
q / Ctrl+c |
Quit |
Instances Tab
| Key | Action |
|---|---|
j / k / Up / Down |
Navigate |
g / G |
Jump to first / last |
/ |
Filter by name, ID, or type |
Esc |
Clear filter |
s |
Start instance |
S |
Stop instance |
f |
Force-stop instance |
r |
Refresh |
Columns: Instance ID, Name, Type, State, SSM Status, Tunnel, Private IP. States are color-coded: green = running, red = stopped, yellow = pending/stopping.
Tunnels Tab
| Key | Action |
|---|---|
j / k / Up / Down |
Navigate |
n |
New tunnel by instance name (wizard) |
u |
New tunnel by URL (smart ALB resolution) |
b |
New tunnel via bastion (wizard) |
d / Delete |
Stop selected tunnel |
A |
Stop all tunnels |
r |
Refresh |
Each tunnel shows real-time status with latency measurement:
● OK 42ms— tunnel active, measured round-trip▲ OPEN— port open, not yet probed◌ DOWN— tunnel unreachable
Tunnels auto-refresh every ~15 seconds.
Tools Tab
| Key | Action |
|---|---|
j / k / Up / Down |
Navigate menu |
Enter |
Execute |
Available tools:
- Switch Profile — select from
~/.aws/configprofiles - Switch Region — change AWS region
- Login — SSO login
- Resolve URL — trace DNS to backend resource
- Test Port — check if a tunnel port is open
- Stop All Tunnels — kill all SSM sessions
VPN Tab
| Key | Action |
|---|---|
j / k / Up / Down |
Navigate menu |
Enter |
Execute |
r |
Refresh status |
Available actions:
- Connect — enter MFA code and connect to VPN
- Disconnect — stop active VPN session
- Setup — configure SSO credentials and .ovpn path (multi-step wizard)
- Status — check VPN connection state, IP, and PID
Reverse Proxy
The --proxy flag on tunnel-url sets up nginx so the original hostname works in your browser over the SSM tunnel.
How It Works
- Writes a site config to nginx (
proxy_passto the tunnel's local port) - Adds a
/etc/hostsentry pointing the hostname to127.0.0.1 - Reloads nginx and flushes the DNS cache
awsx2 tunnel-stopcleans everything up automatically
Platform Support
| macOS (Homebrew) | Linux (Debian/Ubuntu) | Linux (RHEL/CentOS) | |
|---|---|---|---|
| Config path | /opt/homebrew/etc/nginx/servers/ |
sites-available/ + symlink to sites-enabled/ |
/etc/nginx/conf.d/ |
| Nginx reload | nginx -s reload |
systemctl reload nginx |
systemctl reload nginx |
| DNS flush | dscacheutil + mDNSResponder |
resolvectl / systemd-resolve |
resolvectl / nscd |
nginx Installation
# macOS
# Debian / Ubuntu
# RHEL / CentOS / Amazon Linux
Architecture
awsx2
├── main.rs # Entry point, CLI (clap) + TUI event loop
├── aws.rs # AWS CLI wrapper (EC2, SSM, ALB, SG, DNS)
├── tunnel.rs # SSM tunnel lifecycle (start, detect, stop, probe)
├── proxy.rs # nginx reverse proxy + /etc/hosts management
├── vpn.rs # Client VPN with SAML auth (headless Chrome, config persistence)
├── models.rs # Domain types (Instance, TunnelProcess, VpnConfig, etc.)
├── error.rs # Error types (AppError enum with thiserror)
└── tui/
├── app.rs # Application state, background task channels
├── ui.rs # Layout, colors, popup rendering
└── pages/
├── instances.rs # Instances tab (table + key handlers)
├── tunnels.rs # Tunnels tab (table + creation wizards)
├── tools.rs # Tools tab (menu + actions)
└── vpn.rs # VPN tab (connect, disconnect, setup)
Key design decisions:
- Shells out to
awsCLI rather than using the AWS SDK — leverages existing SSO/credential configuration with zero extra setup - Tunnels are detached child processes, discovered by parsing
psoutput forsession-manager-plugin - TUI runs background operations on threads, communicates via
mpscchannels - No runtime dependencies beyond the AWS CLI and session manager plugin
Dependencies
| Crate | Purpose |
|---|---|
ratatui |
Terminal UI framework |
crossterm |
Terminal I/O (raw mode, key events) |
clap |
CLI argument parsing with env var support |
serde + serde_json |
AWS CLI JSON output parsing |
thiserror |
Error type derivation |
libc |
Unix signal handling (SIGTERM for tunnel cleanup) |
headless_chrome |
Chrome DevTools Protocol for SAML browser automation |
tiny_http |
Lightweight HTTP server for SAML callback listener |
regex |
Parsing SAML URL and session ID from OpenVPN output |
url |
URL parsing for SAML form data extraction |
dirs |
Platform-correct config directory (~/.config/awsx2/) |
tempfile |
Secure temporary files for OpenVPN configs and credentials |
Environment Variables
| Variable | Used by |
|---|---|
AWS_PROFILE |
Default profile for all AWS operations |
AWS_DEFAULT_REGION |
Default region |
INSTANCE_NAME |
Default instance name for CLI commands |
License
MIT