CLI tool for deploying software to remote and local servers via SSH/SFTP.
Project description
ikctl — Install Kit Control
CLI tool to deploy and execute bash scripts ("kits") on remote servers via SSH/SFTP or on the local machine.
How it works
A kit is a folder containing bash scripts and an ikctl.yaml manifest. ikctl uploads the scripts to the remote server via SFTP and executes them over SSH. Everything is driven by a configuration file at ~/.ikctl/config that defines one or more contexts (sets of servers, kits path and secrets).
~/.ikctl/config ← main config: contexts, active context
~/kits/
ikctl.yaml ← index of available kits
config.yaml ← server groups
show-date/
ikctl.yaml ← kit manifest (uploads + pipeline)
date.sh ← the actual script
Requirements
- Python 3.13+
- uv (recommended) or pip
Installation
From PyPI:
pip install ikctl
# or with uv:
uv tool install ikctl
From source:
git clone <repo>
cd ikctl
uv sync
uv run ikctl --version
Initial setup
On first run, ikctl creates ~/.ikctl/ and ~/kits/ automatically and prompts for confirmation. To skip the prompt:
ikctl --list context # triggers bootstrap if config is missing
Or create the config manually:
# ~/.ikctl/config
context: remote
contexts:
remote:
path_kits: ~/kits
path_servers: ~/kits
path_secrets: ~/.passwords/password
mode: remote
timeout_connect: 30.0
timeout_exec: 120.0
local:
path_kits: ~/kits
path_servers: ~/kits
path_secrets: ~/.passwords/password
mode: local
Server config
# ~/kits/config.yaml
servers:
- name: web
user: ubuntu
hosts: [10.0.0.10, 10.0.0.11]
port: 22
pkey: ~/.ssh/id_ed25519
- name: db
user: root
hosts: [10.0.0.20]
port: 22
password: $PASSWORD
Passwords in YAML can reference environment variables ($PASSWORD). Set them before running:
export PASSWORD="your-password"
Kit structure
# ~/kits/show-date/ikctl.yaml
kits:
uploads:
- date.sh # files to upload to the remote server
pipeline:
- date.sh # scripts to execute (in order)
Register the kit in the index:
# ~/kits/ikctl.yaml
kits:
- show-date/ikctl.yaml
- install-docker/ikctl.yaml
Usage
ikctl [-h] [-l {kits,servers,context,mode}] [-i INSTALL] [-n NAME]
[-p [PARAMETER ...]] [-s {sudo}] [-c CONTEXT] [-m {local,remote}]
[-v] [--dry-run] [--timeout-connect FLOAT] [--timeout-exec FLOAT]
[--parallel-workers N]
List
ikctl --list kits # available kits in the active context
ikctl --list servers # configured server groups
ikctl --list context # contexts, active context and paths
ikctl --list mode # current execution mode
Switch context
ikctl --context production
Run a kit
# Remote (default)
ikctl --install show-date --name web
# With parameters passed to the script
ikctl --install deploy --name web -p v1.2.3
# With sudo
ikctl --install install-docker --name web --sudo sudo
# Local machine (no SSH)
ikctl --install show-date --mode local
Preview without executing
--dry-run shows exactly what would be uploaded and executed, without opening any SSH connection:
ikctl --install deploy --name web -p v1.2.3 --sudo sudo --dry-run
Output:
[DRY RUN] Host: 10.0.0.10
[DRY RUN] UPLOAD: ~/kits/deploy/deploy.sh → .ikctl/deploy/deploy.sh
[DRY RUN] EXEC: echo *** | sudo -S bash deploy.sh v1.2.3
Parallel execution
When a server group has multiple hosts, ikctl runs them concurrently:
ikctl --install show-date --name web --parallel-workers 4
Output includes per-host prefix and a final summary:
[10.0.0.10] UPLOAD: ...
[10.0.0.11] UPLOAD: ...
2 hosts OK, 0 hosts FAILED
Timeouts
# Override SSH connection timeout (default 30s)
ikctl --install show-date --name web --timeout-connect 60
# Override local execution timeout (default 120s)
ikctl --install build --mode local --timeout-exec 300
Timeouts can also be set per context in ~/.ikctl/config (timeout_connect, timeout_exec). CLI values take precedence over config values.
SSH authentication
ikctl supports all standard SSH authentication methods:
| Method | Config key |
|---|---|
| Ed25519 / ECDSA / RSA key | pkey: ~/.ssh/id_ed25519 |
| Password | password: $PASSWORD |
| SSH agent | enabled by default |
| Jump host (ProxyCommand) | configured in SSHOptions |
License
Apache License 2.0 — see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ikctl-1.0.13.tar.gz.
File metadata
- Download URL: ikctl-1.0.13.tar.gz
- Upload date:
- Size: 91.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f3cadf20078c1a84eaeeea02f16e06e25578583544eee019993cf28fe3865f98
|
|
| MD5 |
537d9ea5477c9b1dd8fa17d7a9050716
|
|
| BLAKE2b-256 |
745b02646b1fecd44f3294a899ea6266a51664e784c674d641cae6468d32cd5f
|
File details
Details for the file ikctl-1.0.13-py3-none-any.whl.
File metadata
- Download URL: ikctl-1.0.13-py3-none-any.whl
- Upload date:
- Size: 30.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c2f62c01a0206eed510803dcceaa35512c83db79ca724554c6686bb773f40ace
|
|
| MD5 |
ae88bc56151d410f7d29a64d34ce700b
|
|
| BLAKE2b-256 |
8fefb1d0c61fdd00a7a69f4ee05933424697794f643b0f4c9d978fa11afa80be
|