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.1

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.1
File Size Uploaded
ikctl-1.12.1.tar.gz 198.8 kB Details

Built distribution (wheel)

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

Total release size: 250.3 kB

Release files / ikctl-1.12.1.tar.gz

Download URL ikctl-1.12.1.tar.gz
Size 198.8 kB
Tags Source
SHA-256 checksum
How to use checksums
09e6988b71e1ecfd43ecc5986fece2fa6e676788193148a97c825c966bfbbb72
BLAKE2b-256 checksum
How to use checksums
a37f03cc6e963ed23afc97ef263446d10d2113a8e54344b064e3cfc6bd612720
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","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.1-py3-none-any.whl

Download URL ikctl-1.12.1-py3-none-any.whl
Size 51.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
98ad6c3871277f0397a9488c1c895b60f640328551c1567f0d492ca49eb80b84
BLAKE2b-256 checksum
How to use checksums
35297403e64c505ebf9c93db88be91c289f0e8d5bc9b65e03e9a97e20d765aa4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","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

1.12.2

2 release files

This release

1.12.1 This release

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