Skip to main content

ikctl — Install Kit Control

CLI tool to deploy and execute bash scripts ("kits") on remote servers via SSH/SFTP or on the local machine. Supports parallel execution, DAG-based pipeline orchestration, and git-based kit repositories.

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.

A pipeline is a YAML file that chains multiple kits across different server groups, with dependencies, parallel execution and output passing between steps.

Everything is driven by ~/.ikctl/config, which defines one or more contexts (server groups, kits source, secrets).

~/.ikctl/config          ← main config: contexts, active context
~/kits/
  config.yaml            ← server groups
  show-date/
    ikctl.yaml           ← kit manifest (uploads + pipeline + outputs)
    date.sh              ← the actual script
~/kits/pipelines/
  deploy.yaml            ← pipeline YAML

Kits are auto-discovered — no index file needed. Any folder under path_kits that contains an ikctl.yaml is a kit.

Requirements

  • Python 3.13+
  • git (for git-based kit repositories)

Installation

Recommended — pipx (isolated, no system conflicts):

pipx install ikctl

With uv:

uv tool install ikctl

With pip (on Debian/Ubuntu you may need --break-system-packages):

pip install ikctl --break-system-packages

With the install script (pip --user + automatic PATH fix for bash/zsh):

curl -fsSL https://raw.githubusercontent.com/3nueves/ikctl/main/install.sh | bash
# or, after cloning:
bash install.sh

The script installs ikctl with pip install --user and appends ~/.local/bin to your shell's rc file if it is not already on PATH.

From source:

git clone <repo>
cd ikctl
uv sync
uv run ikctl --version

Initial setup

On first run, ikctl creates ~/.ikctl/ and ~/kits/ automatically.

Minimal ~/.ikctl/config:

context: production
contexts:
  production:
    path_kits: ~/kits               # where your kits live (auto-discovered)
    path_servers: ~/kits            # where config.yaml lives
    path_secrets: ~/.passwords/pw   # file containing the sudo/ssh password
    path_pipelines: ~/kits/pipelines # optional: pipelines directory
    mode: remote
    timeout_connect: 30.0           # SSH connect timeout (seconds)
    timeout_exec: 120.0             # local command timeout (seconds)
    exclude:                        # optional: kits to hide from discovery
      - internal/debug-kit

Git-based kits (optional)

Pull kits from a git repository instead of a local directory:

contexts:
  production:
    kits_repo: git@gitlab.com:company/kits.git   # SSH repo
    kits_ref: main                                # branch, tag or commit
    # kits_token: $GITLAB_TOKEN                  # for private HTTPS repos
    path_servers: ~/kits/production
    path_secrets: ~/.passwords/password
    mode: remote

For private HTTPS repos:

    kits_repo: https://gitlab.com/company/kits.git
    kits_token: $GITLAB_TOKEN    # references an env variable
export GITLAB_TOKEN=glpat-xxxxxxxxxxxx
ikctl --list kits   # clones on first use, pulls on subsequent runs

Server config

# ~/kits/config.yaml
servers:
  - name: workers
    user: ubuntu
    hosts: [10.0.0.10, 10.0.0.11, 10.0.0.12]
    port: 22
    pkey: ~/.ssh/id_ed25519        # key-based auth

  - name: master
    user: ubuntu
    hosts: [10.0.0.5]
    port: 22
    pkey: ~/.ssh/id_ed25519

  - name: db
    user: root
    hosts: [10.0.0.20]
    port: 22
    password: $PASSWORD             # password auth (env var)

SSH authentication

Config key Auth method Notes
pkey: ~/.ssh/id_ed25519 Public key only Ed25519, ECDSA or RSA
password: $PASSWORD Password only
Neither SSH agent + ~/.ssh/ discovery

pkey and password are mutually exclusive — only one is attempted.

Kit structure

# ~/kits/kubeadm-init/ikctl.yaml
kits:
  uploads:
    - kubeadm-init.sh     # files to upload to the remote server
  pipeline:
    - kubeadm-init.sh     # scripts to execute in order
  outputs:                # optional: documents KEY=VALUE the script emits
    JOIN_TOKEN: "kubeadm join token for worker nodes"
    JOIN_ENDPOINT: "API server endpoint (IP:6443)"

The outputs: field documents what KEY=VALUE lines the script writes to stdout. These values are available to subsequent pipeline steps via {{ steps.<id>.KEY }}.

Usage

ikctl [-l {kits,servers,context,mode,pipelines}] [-i INSTALL] [-n NAME]
      [-p [PARAM ...]] [-s {sudo}] [-c CONTEXT] [-m {local,remote}]
      [-v] [--dry-run] [--debug] [--describe KIT]
      [--pipeline FILE] [--timeout-connect F] [--timeout-exec F]
      [--parallel-workers N]

List

ikctl --list kits       # all discovered kits (shows declared outputs)
ikctl --list servers    # configured server groups
ikctl --list context    # active context and all paths
ikctl --list pipelines  # pipeline YAML files in path_pipelines

Inspect a kit

ikctl --describe kubeadm-init

Shows the kit's scripts and declared outputs:

╭─ Kit ───────────────╮
│  kubeadm-init       │
╰─────────────────────╯
Uploads:  kubeadm-init.sh
Pipeline: kubeadm-init.sh
Outputs:
  JOIN_TOKEN    → kubeadm join token for worker nodes
  JOIN_ENDPOINT → API server endpoint (IP:6443)

Switch context

ikctl --context staging

Run a kit

# Remote (default)
ikctl --install show-date --name workers

# With parameters passed to the script
ikctl --install deploy --name workers -p v2.1.0

# With sudo
ikctl --install install-docker --name workers --sudo sudo

# Local machine (no SSH)
ikctl --install show-date --mode local

# Preview without executing
ikctl --install deploy --name workers -p v2.1.0 --dry-run

Parallel execution

When a server group has multiple hosts, ikctl runs them concurrently:

ikctl --install show-date --name workers --parallel-workers 4

A spinner appears while connecting to each host and a progress bar during uploads. Output is prefixed with the host IP.

Pipeline orchestration

A pipeline chains kits across server groups with DAG dependencies and output passing:

# ~/kits/pipelines/install-kubernetes.yaml
name: install-kubernetes

steps:
  - id: prepare
    kit: packages
    servers: all-nodes
    sudo: true

  - id: init-master
    kit: kubeadm-init
    servers: master
    sudo: true
    needs: [prepare]
    params:
      - "{{ params.POD_CIDR }}"      # from CLI: -p POD_CIDR=192.168.0.0/16

  - id: join-workers
    kit: join-in-kubes
    servers: workers
    sudo: true
    needs: [init-master]
    params:
      - "{{ steps.init-master.JOIN_TOKEN }}"    # output from previous step
      - "{{ steps.init-master.JOIN_ENDPOINT }}" # output from previous step
# Run pipeline by name (requires path_pipelines in config)
ikctl --pipeline install-kubernetes -p POD_CIDR=192.168.0.0/16

# Or by full path
ikctl --pipeline ~/kits/pipelines/install-kubernetes.yaml -p POD_CIDR=192.168.0.0/16

# Preview
ikctl --pipeline install-kubernetes -p POD_CIDR=192.168.0.0/16 --dry-run

Steps without needs run in parallel. Steps fail gracefully — dependents are marked as skipped.

Debug mode

# Show all internal logs (paramiko included)
ikctl --install show-date --name workers --debug

Without --debug, only useful output is shown (Rich formatted).

Timeouts

ikctl --install show-date --name workers --timeout-connect 60
ikctl --install build --mode local --timeout-exec 300

Or set per context in ~/.ikctl/config with timeout_connect and timeout_exec.

License

Apache License 2.0 — see LICENSE for details.

Metadata

Release files for ikctl 1.12.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ikctl 1.12.2
File Size Uploaded
ikctl-1.12.2.tar.gz 199.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ikctl 1.12.2
File Interpreter ABI Platform
ikctl-1.12.2-py3-none-any.whl Python 3 none any Details

Total release size: 251.4 kB

Release files / ikctl-1.12.2.tar.gz

Download URL ikctl-1.12.2.tar.gz
Size 199.8 kB
Tags Source
SHA-256 checksum
How to use checksums
a83cbba9d05b91cc5a65d3fcdaf18854c40f95638de993be3da0451e88af6a60
BLAKE2b-256 checksum
How to use checksums
4b814e31bc6df259a757dc3d3fc8e8f7fd9c9415d192ed038261088161e4d0a9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / ikctl-1.12.2-py3-none-any.whl

Download URL ikctl-1.12.2-py3-none-any.whl
Size 51.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
19b9296967732c54a57d8b53973b10034aa953513aa4b382094ad0ff1bd2dbdf
BLAKE2b-256 checksum
How to use checksums
349ebd63882f275834ca1bd6e4b221fbf2d3fd6fd50d3c9deb151f0f7c796202
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

1.12.2 This release

2 release files

1.12.1

2 release files

1.9.0

2 release files

1.8.0

2 release files

1.7.0

2 release files

1.6.0

2 release files

1.5.4

2 release files

1.5.3

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.4

2 release files

1.4.3

2 release files

1.4.2

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.3

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.1.4

2 release files

1.1.3

2 release files

1.0.1

1 release file

0.6.4

2 release files

0.6.3

2 release files

0.6.2

1 release file

0.6.1

1 release file

0.6.0

1 release file

0.5.9

1 release file

0.5.8

1 release file

0.5.6

1 release file

0.5.5

1 release file

0.5.4

1 release file

0.5.3

1 release file

0.5.2

1 release file

0.4.9

1 release file

0.4.5

1 release file

0.4.4

1 release file

0.4.3

1 release file

0.4.2

1 release file

0.4.1

1 release file

0.3.1

1 release file

0.3.0

1 release file

0.2.16

1 release file

0.2.15

1 release file

0.2.14

1 release file

0.2.12

1 release file

0.2.11

1 release file

0.1.10

1 release file

0.1.9

1 release file

0.1.7

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page