docs: add readme, changelog, contributing and man page
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## [0.1.1] - 2026-09-12
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Parser**: directory `Include` targets (e.g. `conf.d/`) no longer crash validation with `IsADirectoryError`; `parse_file` converts read errors to `ParseError`
|
||||
- **Init**: generated `Include conf.d/` now writes a proper glob (`conf.d/*.conf`)
|
||||
- **Config**: `config set` no longer recurses infinitely when no `Host *` block exists (now prepends one)
|
||||
- **Config**: `validate_options`/`heal` now detect lowercase option typos (`hostname` → `HostName`)
|
||||
- **Jump**: comments with leading whitespace in `.internal_ssids` are now filtered correctly
|
||||
- **CLI**: fixed undefined `HostBlock` name in host edit and broken `jump_auto` indentation
|
||||
- **Types**: mypy strict clean across all 45 source/test files (jump, setup, configops, events)
|
||||
|
||||
### Added
|
||||
|
||||
- **Packaging**: Arch Linux `PKGBUILD` (`linux/arch/`)
|
||||
- **Tests**: coverage suites for events, logutil, cleanup, configops, jump (161 tests)
|
||||
- **Metadata**: repo URL unified to `https://src.panahifar.ir/ahp/sshctl`
|
||||
|
||||
### Changed
|
||||
|
||||
- Version bumped to 0.1.1; coverage gate aligned to 45% (CI and Makefile)
|
||||
|
||||
## [0.1.0] - 2026-07-16
|
||||
|
||||
### Added
|
||||
|
||||
- **Core**: SSH config parser with `Include` resolution, glob support, continuation lines
|
||||
- **Core**: SSH config generator with deterministic option ordering
|
||||
- **Core**: Host resolver via `ssh -G` subprocess
|
||||
- **Core**: Config validator with structural validation
|
||||
- **Operations**: Async DNS/TCP/SSH connectivity checker with semaphore concurrency
|
||||
- **Operations**: Parallel SSH command executor
|
||||
- **Export**: CSV inventory export
|
||||
- **Export**: Ansible inventory generation from `conf.d/` directory tree
|
||||
- **Export**: SSH directory permission fix and check
|
||||
- **CLI**: `init` — initialize SSH config directory structure
|
||||
- **CLI**: `host list`, `host show`, `host add` — host alias management
|
||||
- **CLI**: `check` — connectivity check across hosts
|
||||
- **CLI**: `exec` — parallel command execution
|
||||
- **CLI**: `csv` — CSV inventory export
|
||||
- **CLI**: `chmod` — permission fix/check
|
||||
- **CLI**: `ansible` — Ansible inventory generation
|
||||
- **CLI**: `validate` — config validation
|
||||
- **CLI**: `tree` — config directory tree viewer
|
||||
- **CLI**: `diff` — compare generated vs current config
|
||||
- **CLI**: `backup` / `restore` — SSH directory backup and restore
|
||||
- **CLI**: `install-completion` — shell completion installation
|
||||
- **Architecture**: Modular subpackage layout (cli/, core/, config/, operations/, export/)
|
||||
- **Infrastructure**: GitHub Actions CI (test + build wheel + deb)
|
||||
- **Infrastructure**: pre-commit hooks (ruff, mypy, linting)
|
||||
- **Infrastructure**: Debian packaging (`debian/`)
|
||||
- **Infrastructure**: Makefile with test/lint/build targets
|
||||
- **Infrastructure**: Coverage config (80% threshold)
|
||||
- **Config**: Pydantic-settings with YAML and env variable support
|
||||
- **Models**: ZonePath hierarchical addressing (universe/sector/cluster/zone/vlan)
|
||||
@@ -0,0 +1,66 @@
|
||||
# Contributing
|
||||
|
||||
## Development Setup
|
||||
|
||||
```bash
|
||||
git clone https://src.panahifar.ir/ahp/sshctl.git
|
||||
cd sshctl
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
make dev
|
||||
```
|
||||
|
||||
## Code Quality
|
||||
|
||||
Before submitting a PR, run the full check suite:
|
||||
|
||||
```bash
|
||||
make check
|
||||
```
|
||||
|
||||
This runs lint, format-check, typecheck, and tests in sequence.
|
||||
|
||||
## Code Conventions
|
||||
|
||||
- **Python 3.13+** — use modern typing (`str | None`, `list[str]`, etc.)
|
||||
- **`from __future__ import annotations`** — required in every file
|
||||
- **`@dataclass`** — preferred for data models
|
||||
- **Imports** — lazy imports in CLI layer, top-level imports in domain modules
|
||||
- **Async** — `asyncio` with `Semaphore` for all network operations
|
||||
- **Testing** — pytest with `tmp_path` for files, `pytest.raises` for exceptions
|
||||
- **Type annotations** — required on all public functions
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
src/sshctl/
|
||||
cli/ CLI interface (app.py)
|
||||
core/ Shared foundation (models, exceptions, config, logging)
|
||||
config/ SSH config lifecycle (parser, generator, resolver, validator)
|
||||
operations/ Active operations (checker, executor)
|
||||
export/ Export/integration (exporter, inventory, permissions)
|
||||
```
|
||||
|
||||
## Pull Request Process
|
||||
|
||||
1. Ensure `make check` passes
|
||||
2. Add tests for new functionality
|
||||
3. Update CHANGELOG.md
|
||||
4. Update README.md if user-facing changes
|
||||
|
||||
## Release Process
|
||||
|
||||
```bash
|
||||
# Update version in src/sshctl/core/_version.py
|
||||
# Update CHANGELOG.md
|
||||
git commit -m "Release v0.x.y"
|
||||
git tag v0.x.y
|
||||
git push origin main --tags
|
||||
# CI builds and publishes wheel + deb
|
||||
```
|
||||
|
||||
Or manually:
|
||||
|
||||
```bash
|
||||
make release
|
||||
```
|
||||
@@ -0,0 +1,359 @@
|
||||
# sshctl
|
||||
|
||||
SSH configuration management toolkit — parse, validate, generate, and manage SSH configs at scale.
|
||||
|
||||
[]()
|
||||
[](LICENSE)
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- **Parse** — Full SSH config parser supporting `Host`, `Include`, glob patterns, and continuation lines
|
||||
- **Generate** — Programmatic SSH config generation with deterministic option ordering
|
||||
- **Validate** — Validate SSH config structure, check required options and missing includes
|
||||
- **Check** — Parallel DNS/TCP/SSH connectivity checking across all hosts
|
||||
- **Exec** — Run commands concurrently across all hosts via SSH
|
||||
- **Export** — Export host inventory to CSV
|
||||
- **Ansible** — Generate Ansible inventory from your SSH config directory tree
|
||||
- **Permissions** — Fix or verify SSH directory permissions (0700 dirs, 0600 keys, 0644 public keys)
|
||||
- **CLI** — Full-featured `typer` CLI with rich output (tables, trees, status)
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### pip (wheel)
|
||||
|
||||
```bash
|
||||
pip install sshctl # once published to PyPI
|
||||
# or install the built wheel directly from a release
|
||||
pip install ./sshctl-0.1.1-py3-none-any.whl
|
||||
```
|
||||
|
||||
### dpkg (Debian/Ubuntu)
|
||||
|
||||
```bash
|
||||
# Download from latest release
|
||||
wget https://src.panahifar.ir/ahp/sshctl/releases/download/v0.1.1/sshctl_0.1.1-1_all.deb
|
||||
sudo dpkg -i sshctl_0.1.1-1_all.deb
|
||||
```
|
||||
|
||||
### From source
|
||||
|
||||
```bash
|
||||
git clone https://src.panahifar.ir/ahp/sshctl.git
|
||||
cd sshctl
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
Download the latest `.whl` or `.deb` from the [releases page](https://src.panahifar.ir/ahp/sshctl/releases).
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Initialize SSH config directory structure
|
||||
sshctl init
|
||||
|
||||
# List all hosts
|
||||
sshctl host list
|
||||
|
||||
# Show a specific host
|
||||
sshctl host show server1
|
||||
|
||||
# Validate config
|
||||
sshctl validate
|
||||
|
||||
# Check host connectivity
|
||||
sshctl check
|
||||
|
||||
# Run a command across all hosts in parallel
|
||||
sshctl exec "uptime"
|
||||
|
||||
# Export inventory as CSV
|
||||
sshctl csv --output hosts.csv
|
||||
|
||||
# Generate Ansible inventory
|
||||
sshctl ansible
|
||||
|
||||
# Fix SSH directory permissions
|
||||
sshctl chmod
|
||||
|
||||
# Only check permissions (no fixes)
|
||||
sshctl chmod --check
|
||||
|
||||
# Show conf.d directory tree
|
||||
sshctl tree
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
~/.ssh/
|
||||
├── config # Main SSH config (Include conf.d/)
|
||||
├── conf.d/ # Modular host configurations
|
||||
│ ├── internal/ # Internal infrastructure universe
|
||||
│ │ ├── AZ/ # Sector (e.g., region)
|
||||
│ │ │ └── cluster1/
|
||||
│ │ │ └── 8xx-serverfarm/
|
||||
│ │ │ └── 82-k8s/
|
||||
│ │ │ └── hosts.conf
|
||||
│ │ └── ...
|
||||
│ └── external/ # External/dedicated universe
|
||||
│ └── ...
|
||||
├── control.d/ # SSH control master sockets
|
||||
├── keys.d/ # Private keys (auto-protected by sshctl chmod)
|
||||
├── keys.pub/ # Public keys
|
||||
├── report/ # Generated reports
|
||||
└── inventory.d/ # Generated Ansible inventory
|
||||
└── hosts.yml
|
||||
```
|
||||
|
||||
### ZonePath Convention
|
||||
|
||||
The `conf.d/` hierarchy follows a **ZonePath** addressing model:
|
||||
|
||||
```
|
||||
conf.d/{universe}/{sector}/{cluster}/{zone}/{vlan}
|
||||
```
|
||||
|
||||
| Level | Description | Example |
|
||||
|----------|--------------------------|------------------------|
|
||||
| universe | `internal` or `external` | `internal` |
|
||||
| sector | Geographic/segment | `AZ` |
|
||||
| cluster | Data center / DC | `cluster1` |
|
||||
| zone | Server farm / role | `8xx-serverfarm` |
|
||||
| vlan | Network segment | `82-k8s` |
|
||||
|
||||
---
|
||||
|
||||
## CLI Reference
|
||||
|
||||
### Global Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-V`, `--version` | Show version |
|
||||
| `-v`, `--verbose` | Verbose logging |
|
||||
| `-c`, `--config` | Path to SSH config file |
|
||||
|
||||
### Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `init` | Initialize SSH config directory structure |
|
||||
| `host list` | List all host aliases |
|
||||
| `host show` | Show details for a specific host |
|
||||
| `host add` | Add a new host to the SSH config |
|
||||
| `check` | Check connectivity to all hosts |
|
||||
| `exec` | Run a command in parallel across hosts |
|
||||
| `csv` | Export host inventory to CSV |
|
||||
| `chmod` | Fix or check SSH directory permissions |
|
||||
| `validate` | Validate SSH config structure |
|
||||
| `diff` | Show differences between generated and current config |
|
||||
| `backup` | Create timestamped backup of SSH config directory |
|
||||
| `restore <path>` | Restore SSH config from a backup |
|
||||
| `ansible` | Generate Ansible inventory from SSH config |
|
||||
| `tree` | Show the conf.d directory tree |
|
||||
| `install-completion` | Install shell completions (bash/zsh/fish) |
|
||||
|
||||
---
|
||||
|
||||
## Python API
|
||||
|
||||
```python
|
||||
from pathlib import Path
|
||||
from sshctl.parser import parse_file, resolve_includes
|
||||
from sshctl.models import HostBlock, SshConfig
|
||||
from sshctl.generator import generate_config_text, write_config_file
|
||||
from sshctl.validator import validate_config
|
||||
from sshctl.resolver import resolve_host, resolve_all_hosts
|
||||
from sshctl.exporter import export_csv
|
||||
from sshctl.permissions import fix_ssh_permissions, check_permissions
|
||||
from sshctl.inventory import generate_inventory
|
||||
|
||||
# Parse an SSH config
|
||||
config = parse_file(Path("~/.ssh/config").expanduser())
|
||||
|
||||
# Resolve includes recursively
|
||||
full_config = resolve_includes(Path("~/.ssh/config"))
|
||||
|
||||
# Find hosts
|
||||
block = config.find("server1")
|
||||
blocks = config.find_all("web*")
|
||||
|
||||
# Validate
|
||||
result = validate_config(Path("~/.ssh/config"))
|
||||
if not result.passed:
|
||||
for issue in result.issues:
|
||||
print(f"[{issue.severity}] {issue.message}")
|
||||
|
||||
# Resolve a host (uses ssh -G)
|
||||
resolved = resolve_host("server1", Path("~/.ssh/config"))
|
||||
|
||||
# Generate config text
|
||||
text = generate_config_text(full_config)
|
||||
|
||||
# Generate Ansible inventory
|
||||
inventory = generate_inventory(Path("~/.ssh"))
|
||||
|
||||
# Fix permissions
|
||||
counts = fix_ssh_permissions(Path("~/.ssh"))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
sshctl can be configured via YAML or environment variables.
|
||||
|
||||
### YAML (`~/.ssh/sshctl.yaml`)
|
||||
|
||||
```yaml
|
||||
ssh_dir: ~/.ssh
|
||||
config_file: config
|
||||
verbose: false
|
||||
timeout: 10
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
All settings can be overridden with `SSHCTL_` prefix:
|
||||
|
||||
```bash
|
||||
export SSHCTL_VERBOSE=true
|
||||
export SSHCTL_TIMEOUT=30
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Development
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
git clone https://src.panahifar.ir/ahp/sshctl.git
|
||||
cd sshctl
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -e ".[dev]"
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
pytest
|
||||
```
|
||||
|
||||
### Lint & Type Check
|
||||
|
||||
```bash
|
||||
ruff check src/ tests/
|
||||
ruff format --check src/ tests/
|
||||
mypy src/ tests/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
sshctl/
|
||||
├── src/
|
||||
│ └── sshctl/
|
||||
│ ├── __init__.py # Package init, re-exports from core
|
||||
│ ├── __main__.py # Entry point for python -m sshctl
|
||||
│ │
|
||||
│ ├── cli/ # CLI layer (user-facing)
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── app.py # Typer CLI application
|
||||
│ │ └── __main__.py # Module entry point
|
||||
│ │
|
||||
│ ├── core/ # Core domain (shared foundation)
|
||||
│ │ ├── __init__.py # Exports __version__
|
||||
│ │ ├── _version.py # Version string
|
||||
│ │ ├── config.py # Pydantic settings (SshctlConfig)
|
||||
│ │ ├── exceptions.py # Exception hierarchy
|
||||
│ │ ├── logutil.py # Structured logging (structlog)
|
||||
│ │ └── models.py # Data models (HostBlock, SshConfig, ZonePath)
|
||||
│ │
|
||||
│ ├── config/ # SSH config lifecycle
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── parser.py # SSH config parser + include resolution
|
||||
│ │ ├── generator.py # SSH config text generation
|
||||
│ │ ├── resolver.py # Host resolution via ssh -G
|
||||
│ │ └── validator.py # Config validation
|
||||
│ │
|
||||
│ ├── operations/ # Active operations
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── checker.py # DNS/TCP/SSH connectivity checks
|
||||
│ │ └── executor.py # Parallel SSH command execution
|
||||
│ │
|
||||
│ └── export/ # Export/integration
|
||||
│ ├── __init__.py
|
||||
│ ├── exporter.py # CSV export
|
||||
│ ├── inventory.py # Ansible inventory generation
|
||||
│ └── permissions.py # SSH directory permissions
|
||||
│
|
||||
├── tests/
|
||||
│ ├── conftest.py # Pytest fixtures
|
||||
│ ├── test_config.py
|
||||
│ ├── test_exceptions.py
|
||||
│ ├── test_exporter.py
|
||||
│ ├── test_generator.py
|
||||
│ ├── test_inventory.py
|
||||
│ ├── test_models.py
|
||||
│ ├── test_parser.py
|
||||
│ ├── test_permissions.py
|
||||
│ └── test_validator.py
|
||||
│
|
||||
├── pyproject.toml # Build config, ruff, mypy, pytest
|
||||
├── .editorconfig
|
||||
├── .gitignore
|
||||
├── LICENSE
|
||||
└── README.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
sshctl follows a **modular layered architecture** organized into subpackages:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ cli/ (app.py) │
|
||||
│ Typer CLI, Rich output, orchestration │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
┌────────────┼────────────────┬────────────────┐
|
||||
▼ ▼ ▼ ▼
|
||||
┌──────────┐ ┌───────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ config/ │ │operations │ │ export/ │ │ core/ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ parser │ │ checker │ │ exporter │ │ models │
|
||||
│ generator│ │ executor │ │ inventory │ │ exceptions │
|
||||
│ resolver │ │ │ │ permissions │ │ config │
|
||||
│ validator│ │ │ │ │ │ logutil │
|
||||
└──────────┘ └───────────┘ └──────────────┘ └──────────────┘
|
||||
▲
|
||||
│
|
||||
(shared foundation)
|
||||
```
|
||||
|
||||
**Key design decisions:**
|
||||
|
||||
- **Models first** — `HostBlock`, `SshConfig`, `ZonePath` are plain dataclasses; the entire pipeline operates on them
|
||||
- **Parser is lossy by design** — it extracts enough structure for management, not a perfect SSH config round-trip
|
||||
- **Resolver delegates to `ssh -G`** — rather than reimplementing SSH's full inheritance logic, sshctl shells out for the canonical resolved view
|
||||
- **Async everywhere** — checker and executor use `asyncio` with semaphore-controlled concurrency
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
MIT — see [LICENSE](LICENSE)
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
.TH SSHCTL 1 "2026-09-12" "sshctl v0.1.1" "SSH Configuration Management"
|
||||
.SH NAME
|
||||
sshctl \- SSH configuration management toolkit
|
||||
.SH SYNOPSIS
|
||||
.B sshctl
|
||||
[\fIoptions\fR] \fIcommand\fR [\fIargs\fR]
|
||||
.SH DESCRIPTION
|
||||
sshctl is a CLI toolkit for managing SSH configurations, including host definitions,
|
||||
proxy jumps, permissions, connectivity checks, and shell completions.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-V, \-\-version
|
||||
Show version.
|
||||
.TP
|
||||
.B \-v, \-\-verbose
|
||||
Verbose output.
|
||||
.TP
|
||||
.B \-c, \-\-config \fIPATH\fR
|
||||
Path to ssh_config file (default: ~/.ssh/config).
|
||||
.TP
|
||||
.B \-\-install-completion
|
||||
Install shell completion for the current shell.
|
||||
.TP
|
||||
.B \-\-show-completion
|
||||
Show shell completion script.
|
||||
.TP
|
||||
.B \-\-help
|
||||
Show help message.
|
||||
.SH COMMANDS
|
||||
.SS Core
|
||||
.TP
|
||||
.B init
|
||||
Initialize an SSH config directory structure.
|
||||
.TP
|
||||
.B validate
|
||||
Validate SSH config structure and option correctness.
|
||||
.TP
|
||||
.B diff
|
||||
Show differences between generated and current SSH config.
|
||||
.TP
|
||||
.B tree
|
||||
Show the conf.d directory tree with host counts.
|
||||
.TP
|
||||
.B backup
|
||||
Create a timestamped backup of the SSH config directory.
|
||||
.TP
|
||||
.B restore \fIPATH\fR
|
||||
Restore SSH config from a backup.
|
||||
.TP
|
||||
.B cleanup [\-n]
|
||||
Remove stale SSH control master sockets. Use \-n for dry-run.
|
||||
.TP
|
||||
.B log [\-n \fICOUNT\fR] [\-f]
|
||||
Show recent sshctl activity log. Use \-f to follow (tail mode).
|
||||
.TP
|
||||
.B check [\-p \fIPATTERN\fR] [\-t \fISECS\fR] [\-c \fIMAX\fR]
|
||||
Check connectivity to all hosts in parallel.
|
||||
.TP
|
||||
.B exec \fICOMMAND\fR [\-p \fIPATTERN\fR] [\-t \fISECS\fR]
|
||||
Run a command in parallel across hosts.
|
||||
.TP
|
||||
.B csv [\-o \fIFILE\fR]
|
||||
Export host inventory to CSV.
|
||||
.TP
|
||||
.B ansible [\-o \fIFILE\fR] [\-\-group-by \fIFIELD\fR]
|
||||
Generate Ansible inventory from SSH config.
|
||||
.TP
|
||||
.B chmod [\-\-fix]
|
||||
Check (and optionally fix) SSH directory permissions.
|
||||
.SS Config Management
|
||||
.TP
|
||||
.B config show
|
||||
Show all global Host * options.
|
||||
.TP
|
||||
.B config set \fIKEY\fR \fIVALUE\fR
|
||||
Set an option in the Host * block.
|
||||
.TP
|
||||
.B config unset \fIKEY\fR
|
||||
Remove an option from the Host * block.
|
||||
.SS Host Management
|
||||
.TP
|
||||
.B host list
|
||||
List all host aliases with HostName and ProxyJump.
|
||||
.TP
|
||||
.B host show \fIALIAS\fR
|
||||
Show options for a specific host.
|
||||
.TP
|
||||
.B host add \fIALIAS\fR \fIHOSTNAME\fR [\-u \fIUSER\fR] [\-p \fIPORT\fR] [\-j \fIJUMP\fR]
|
||||
Add a new host alias.
|
||||
.TP
|
||||
.B host edit \fIALIAS\fR \-\-option \fIOPT\fR \-\-value \fIVAL\fR
|
||||
Set an option on an existing host.
|
||||
.TP
|
||||
.B host remove \fIALIAS\fR [\-f]
|
||||
Remove a host from its config file (with confirmation).
|
||||
.SS ProxyJump
|
||||
.TP
|
||||
.B jump on
|
||||
Restore all saved ProxyJump directives.
|
||||
.TP
|
||||
.B jump off
|
||||
Save and remove all ProxyJump lines from conf.d files.
|
||||
.TP
|
||||
.B jump status
|
||||
List all hosts with ProxyJump and show saved state.
|
||||
.TP
|
||||
.B jump auto [\-\-subnet] [\-\-no-subnet]
|
||||
Auto-detect network environment:
|
||||
- Probes jump gateways via TCP (respects HostName/Port from SSH config)
|
||||
- Falls back to SSID matching against known internal networks
|
||||
- Enables or disables ProxyJump accordingly.
|
||||
.TP
|
||||
.B jump networks [list|add|remove] [\-\-ssid \fIPATTERN\fR]
|
||||
Manage internal SSID patterns for auto-detection (defaults: MobinNet*, Mobin*).
|
||||
.SS Setup
|
||||
.TP
|
||||
.B setup completions [\-\-shell \fIbash|zsh|fish\fR]
|
||||
Install shell completions.
|
||||
.TP
|
||||
.B setup agent [start|stop|restart|status]
|
||||
Manage the ssh-agent systemd user service.
|
||||
.TP
|
||||
.B setup timer [cleanup|check] [\-a enable|disable|status]
|
||||
Manage systemd timers.
|
||||
.TP
|
||||
.B setup git
|
||||
Initialize git tracking in ~/.ssh.
|
||||
.TP
|
||||
.B setup init
|
||||
Full setup: git + agent + timers + completions.
|
||||
.SS Diagnostics
|
||||
.TP
|
||||
.B heal [\-\-dry-run]
|
||||
Detect and fix config issues (typos, invalid options).
|
||||
.SH FILES
|
||||
.TP
|
||||
.I ~/.ssh/config
|
||||
Main SSH configuration file.
|
||||
.TP
|
||||
.I ~/.ssh/conf.d/
|
||||
Directory containing host definition files.
|
||||
.TP
|
||||
.I ~/.ssh/control.d/
|
||||
SSH control master socket directory.
|
||||
.TP
|
||||
.I ~/.ssh/keys.d/
|
||||
SSH key files.
|
||||
.TP
|
||||
.I ~/.ssh/scripts/
|
||||
Helper scripts and systemd unit files.
|
||||
.TP
|
||||
.I ~/.ssh/report/events.ndjson
|
||||
Activity event log (NDJSON format).
|
||||
.TP
|
||||
.I ~/.ssh/.proxyjump_save
|
||||
Saved ProxyJump state (temporary, created by \fBjump off\fR).
|
||||
.TP
|
||||
.I ~/.ssh/.internal_ssids
|
||||
Internal SSID patterns for auto-detect.
|
||||
.SH ENVIRONMENT
|
||||
.TP
|
||||
.B SSH_AUTH_SOCK
|
||||
SSH agent socket path. Set to \fI$XDG_RUNTIME_DIR/ssh-agent.socket\fR when using
|
||||
the built-in systemd ssh-agent service.
|
||||
.SH EXAMPLES
|
||||
.TP
|
||||
Initialize a new SSH config directory:
|
||||
sshctl init
|
||||
.TP
|
||||
List all hosts:
|
||||
sshctl host list
|
||||
.TP
|
||||
Show host details:
|
||||
sshctl host show myserver
|
||||
.TP
|
||||
Disable all ProxyJump directives (internal network):
|
||||
sshctl jump off
|
||||
.TP
|
||||
Auto-detect network and toggle ProxyJump:
|
||||
sshctl jump auto
|
||||
.TP
|
||||
Add current Wi-Fi as internal network:
|
||||
sshctl jump networks add
|
||||
.TP
|
||||
Check all hosts connectivity:
|
||||
sshctl check
|
||||
.TP
|
||||
View activity log:
|
||||
sshctl log \-n 20
|
||||
.TP
|
||||
Validate and fix config issues:
|
||||
sshctl heal
|
||||
.SH BUGS
|
||||
Report issues at https://git.panahifar.ir/ahp/sshctl/issues
|
||||
.SH AUTHOR
|
||||
Amir Husayn Panahifar
|
||||
.SH SEE ALSO
|
||||
.BR ssh (1),
|
||||
.BR ssh_config (5),
|
||||
.BR sshd (8)
|
||||
Reference in New Issue
Block a user