Remote CLI Management
Manage Gordon instances remotely using the CLI with the --remote flag or saved remotes.
By default (without --remote), management commands execute locally through in-process services.
What You'll Learn
- Using global
--remoteand--tokenflags - Saving and managing remote connections
- Environment variable configuration
- Token security best practices
- Remote command workflows
Prerequisites
- Gordon CLI installed
- A remote Gordon instance running with admin API enabled
- Authentication token for the remote instance
Understanding the Remote URL
Default: use the Gordon domain configured on the remote instance.
# On the remote Gordon server
[server]
gordon_domain = "gordon.example.com" # Use this as --remote URL
The CLI connects to https://gordon.example.com/admin/* endpoints.
Private tailnet setup (recommended for hardened VPS): keep using the HTTPS domain, point that DNS record to the VPS tailnet IP, and set insecure TLS for self-signed certs.
[!CAUTION]
--insecureandinsecure_tls = truedisable TLS certificate verification. This removes server identity validation and increases man-in-the-middle risk. Use this only for private tailnet/VPN deployments with strict network access controls (restricted CIDRs, firewall allowlists, and no public ingress to admin endpoints). Safer alternatives:
- Use a publicly trusted certificate (for example, Let's Encrypt).
- Use an internal CA and trust that CA on operator machines.
- Use Tailscale certificate generation (
tailscale cert) and serve Gordon with that cert.
# Save remote once
gordon remotes add tailnet-reg https://gordon.example.com --token-env GORDON_TOKEN --insecure
gordon remotes use tailnet-reg
# Use it for auth/admin commands
gordon auth login
gordon routes list
Equivalent remotes.toml entry:
active = "tailnet-reg"
[remotes.tailnet-reg]
url = "https://gordon.example.com"
token_env = "GORDON_TOKEN"
insecure_tls = true
Use this mode when registry/auth/admin access is intentionally restricted to tailnet CIDRs.
Quick Start
One-off Remote Command
gordon routes list --remote https://gordon.mydomain.com --token $TOKEN
Using Environment Variables
export GORDON_REMOTE=https://gordon.mydomain.com
export GORDON_TOKEN=$TOKEN
gordon routes list
Using Saved Remotes
# Add a remote
gordon remotes add prod https://gordon.mydomain.com --token-env PROD_TOKEN
# Set as active
gordon remotes use prod
# Now use without flags
gordon routes list
Global Flags
These flags are available on all commands:
| Flag | Description |
|---|---|
--remote <URL> |
Remote Gordon URL |
--token <TOKEN> |
Authentication token |
--insecure |
Skip TLS verification (self-signed/private certs) |
# List routes on remote
gordon routes list --remote https://gordon.mydomain.com --token $TOKEN
# Manage secrets on remote
gordon secrets list myapp.example.com --remote https://gordon.mydomain.com --token $TOKEN
Environment Variables
| Variable | Description |
|---|---|
GORDON_REMOTE |
Remote Gordon URL |
GORDON_TOKEN |
Authentication token |
Environment variables are useful for CI/CD pipelines and shell sessions:
# Set for current session
export GORDON_REMOTE=https://gordon.mydomain.com
export GORDON_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
# Commands automatically use these
gordon routes list
gordon secrets list myapp.example.com
Saved Remotes
Save frequently used remotes to avoid repeating URLs and tokens.
Configuration File
Remotes are stored in ~/.config/gordon/remotes.toml:
active = "prod"
[remotes.prod]
url = "https://gordon.mydomain.com"
token_env = "PROD_TOKEN"
[remotes.staging]
url = "https://staging.mydomain.com"
token = "eyJ..."
Managing Remotes
List Remotes
gordon remotes list
Output:
Saved Remotes
Name URL Token Status
──────────────────────────────────────────────────────────────────────────────
prod https://gordon.mydomain.com $PROD_TOKEN active
staging https://staging.mydomain.com set
dev https://dev.mydomain.com none
Add a Remote
# Basic (no token)
gordon remotes add prod https://gordon.mydomain.com
# With direct token
gordon remotes add prod https://gordon.mydomain.com --token eyJ...
# With environment variable reference (recommended)
gordon remotes add prod https://gordon.mydomain.com --token-env PROD_TOKEN
| Flag | Description |
|---|---|
--token <TOKEN> |
Store token directly in config |
--token-env <VAR> |
Store env variable name (token resolved at runtime) |
Authenticate with Password Auth
For servers using password authentication, you can log in interactively:
# Login to active remote
gordon auth login
# Login to specific remote
gordon auth login --remote prod
# Pre-fill username
gordon auth login --username admin
This prompts for your username and password, authenticates with the remote server, and stores the returned token automatically.
Note: Only works with servers that have password authentication enabled (
username+password_hashconfigured). For token-only servers, usegordon remotes set-tokeninstead.
Set Token Manually
For servers using token-based auth, or to update a token manually:
# Set token directly
gordon remotes set-token prod eyJhbGciOiJIUzI1NiIs...
# Set token from file
gordon remotes set-token staging $(cat token.txt)
Remove a Remote
# With confirmation prompt
gordon remotes remove staging
# Skip confirmation
gordon remotes remove staging --force
Set Active Remote
gordon remotes use prod
When a remote is active, it's used automatically for all remote-capable commands:
gordon remotes use prod
gordon routes list # Uses prod remote
gordon secrets list app.com # Uses prod remote
Resolution Precedence
When multiple sources specify remote or token, the CLI uses this priority order:
Remote URL:
--remoteflagGORDON_REMOTEenvironment variable- Active remote from
remotes.toml
Token:
--tokenflagGORDON_TOKENenvironment variable- Token from active remote in
remotes.toml
This allows overriding specific values while keeping defaults:
# Active remote is prod, but use different token
gordon routes list --token $TEMPORARY_TOKEN
Commands Supporting Remote
These commands work with remote targeting:
| Command | Description |
|---|---|
gordon routes list |
List all routes |
gordon routes add <domain> <image> |
Add a route |
gordon routes remove <domain> |
Remove a route |
gordon routes deploy <domain> |
Deploy/redeploy a route |
gordon attachments list [target] |
List all or targeted attachments |
gordon attachments add <target> <image> |
Add an attachment |
gordon attachments remove <target> <image> |
Remove an attachment |
gordon secrets list <domain> |
List secrets for a domain |
gordon secrets set <domain> KEY=value |
Set secrets |
gordon secrets remove <domain> <key> |
Remove a secret |
gordon status |
Show server status |
gordon reload |
Reload config and start new routes |
gordon logs |
View Gordon process logs |
gordon logs <domain> |
View container logs |
Remote Logs Requirement
The gordon logs command requires file logging to be enabled on the remote server. Without it, you'll get a "failed to get logs" error.
On the remote Gordon server, add to config.toml:
[logging.file]
enabled = true
# path is optional - defaults to {data_dir}/logs/gordon.log
# path = "/var/log/gordon/gordon.log"
Then restart Gordon. The log directory will be created automatically in your data directory (e.g., ~/.gordon/logs/).
If you specify a custom path, ensure the directory exists and is writable:
sudo mkdir -p /var/log/gordon
sudo chown gordon:gordon /var/log/gordon # adjust user as needed
Note: When running as a systemd service, Gordon logs to journalctl by default. However, the remote admin API cannot read from journalctl—it reads from the configured log file. Both can be used simultaneously.
Token Security
Option 1: Environment Variable Reference (Recommended)
Store the environment variable name, not the actual token:
gordon remotes add prod https://gordon.mydomain.com --token-env PROD_TOKEN
The remotes.toml stores only:
[remotes.prod]
url = "https://gordon.mydomain.com"
token_env = "PROD_TOKEN"
At runtime, Gordon reads $PROD_TOKEN from the environment.
Benefits:
- Token not stored in plaintext config
- Works with secret managers that inject env vars
- Easy rotation without editing config
Option 2: Direct Token Storage
gordon remotes add prod https://gordon.mydomain.com --token eyJ...
The token is stored directly in remotes.toml:
[remotes.prod]
url = "https://gordon.mydomain.com"
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Security note: Ensure remotes.toml has restricted permissions:
chmod 600 ~/.config/gordon/remotes.toml
Option 3: Environment Variables Only
For maximum security, don't save tokens at all:
# Add remote without token
gordon remotes add prod https://gordon.mydomain.com
# Set token via environment
export GORDON_TOKEN=$TOKEN
# Use normally
gordon remotes use prod
gordon routes list
Workflow Examples
Development Workflow
# Add dev and staging remotes
gordon remotes add dev https://gordon.dev.local --token-env DEV_TOKEN
gordon remotes add staging https://gordon.staging.example.com --token-env STAGING_TOKEN
# Work with dev
gordon remotes use dev
gordon routes list
gordon routes add myapp.dev.local myapp:latest
# Switch to staging
gordon remotes use staging
gordon routes list
CI/CD Pipeline
# GitHub Actions example
env:
GORDON_REMOTE: ${{ secrets.GORDON_URL }}
GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
steps:
- name: Deploy to Gordon
run: |
gordon routes deploy myapp.example.com
# GitLab CI example
deploy:
script:
- export GORDON_REMOTE=$GORDON_URL
- export GORDON_TOKEN=$GORDON_TOKEN
- gordon routes deploy myapp.example.com
Multi-Environment Management
# Add all environments
gordon remotes add prod https://gordon.example.com --token-env PROD_TOKEN
gordon remotes add staging https://gordon.staging.example.com --token-env STAGING_TOKEN
gordon remotes add dev https://gordon.dev.example.com --token-env DEV_TOKEN
# Compare routes across environments
gordon routes list --remote https://gordon.example.com --token $PROD_TOKEN
gordon routes list --remote https://gordon.staging.example.com --token $STAGING_TOKEN
# Or switch active
gordon remotes use prod && gordon routes list
gordon remotes use staging && gordon routes list
Troubleshooting
"unauthorized" Error
Token is missing, expired, or invalid.
# Check if token is set
echo $GORDON_TOKEN
# Verify token works
gordon routes list --remote https://gordon.mydomain.com --token $TOKEN
"connection refused" Error
Remote Gordon isn't running or URL is wrong.
# Verify URL is correct
curl https://gordon.mydomain.com/health
# Check if admin API is enabled on remote
# The remote gordon.toml needs:
# [admin]
# enabled = true
Remote Not Found
The specified remote doesn't exist in remotes.toml.
# List available remotes
gordon remotes list
# Add the remote
gordon remotes add myremote https://gordon.mydomain.com
Active Remote Cleared
After removing the active remote, you need to set a new active:
gordon remotes use prod
Or use explicit flags:
gordon routes list --remote https://gordon.mydomain.com --token $TOKEN
"failed to get logs" Error
The remote Gordon server doesn't have file logging enabled.
# Error: failed to get process logs: 500 Internal Server Error: failed to get logs
On the remote server, enable file logging in config.toml:
[logging.file]
enabled = true
path = "/var/log/gordon/gordon.log"
See Remote Logs Requirement for details.