Opinionated Debian server bootstrapper
  • Shell 96.6%
  • PowerShell 3.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-24 09:03:47 +02:00
.scripts Regenerate checksum manifest from a clean tree (drop stray tool state) 2026-07-12 18:20:21 +02:00
installer Handle AuthorizedKeysFile 'none' when installing the root key 2026-07-12 16:46:42 +02:00
tests Harden SSH, adjust update.sh, add validator tests, naming cleanup 2026-06-25 01:15:20 +02:00
.editorconfig Commit .editorconfig instead of gitignoring it 2026-06-23 15:03:14 +02:00
.gitattributes Harden installer reliability, security, and idempotency 2026-06-12 22:01:54 +02:00
.gitignore Commit .editorconfig instead of gitignoring it 2026-06-23 15:03:14 +02:00
AGENTS.md Preserve accumulated local work 2026-08-24 07:53:28 +02:00
CHANGELOG.md Preserve accumulated local work 2026-08-24 07:53:28 +02:00
checksums.sha256 Regenerate checksum manifest from a clean tree (drop stray tool state) 2026-07-12 18:20:21 +02:00
cspell.json Preserve accumulated local work 2026-08-24 07:53:28 +02:00
kInit.sh Regenerate checksum manifest from a clean tree (drop stray tool state) 2026-07-12 18:20:21 +02:00
kInit.vars now shorter and cooler 2025-12-01 20:19:19 +01:00
LICENSE add license 2025-05-08 15:47:49 +02:00
README.md Preserve accumulated local work 2026-08-24 07:53:28 +02:00
uninstall.sh Fix audit findings: lockout guards, apt hardening, injection & integrity 2026-07-12 16:39:49 +02:00

kInit - Automated System Setup & Configuration

kInit is a modular, opinionated, and extensible Bash-based installer for quickly setting up and configuring Debian/Ubuntu servers. It automates system hardening, package installation, monitoring, and maintenance tasks, with a focus on best practices and maintainability.


Warning: Read Before Executing

Never execute random scripts from the internet without reading them first. This installer downloads and executes code on your system. Always review the scripts and understand what they do before running. Visit the repository to inspect the code before using this installer.

Security Notice

This installer enables key-based root SSH login (PermitRootLogin prohibit-password — password root login stays disabled) and, when it installs a key, disables password authentication entirely (PasswordAuthentication no, override with SSH_PASSWORD_AUTH="yes"). It modifies authentication settings; ensure you understand the security implications before use, especially on public-facing servers. The root-login policy is configurable via SSH_PERMIT_ROOT_LOGIN (e.g. no for the CIS-recommended posture).


Table of Contents


Quick Start

Recommended: Two-Step Download (Safer)

Download and review before executing:

# Step 1: Download the installer
wget https://kleb.sh/kInit.sh

# Step 2: Review the script
less kInit.sh

# Step 3: Run as root
bash kInit.sh

One-Liner (Use with Caution)

For quick deployments, you can use piped execution (less safe - script not reviewed):

bash <(wget -qO- https://kleb.sh/kInit.sh)

or

bash <(curl -fsSL https://kleb.sh/kInit.sh)

The one-liner trusts the downloaded kInit.sh completely. Embedded checksums only protect the files that kInit.sh downloads after it starts; they cannot prove the first script was authentic. For production, prefer the two-step download, review, and run flow above, or pin the installer hash through your deployment tooling.

Remote Setup Profile Bootstrap

If you are consuming a setup profile published from kUtils, point kInit at the generated bootstrap URL:

bash kInit.sh --setup-profile-url https://example.com/setup/alice/base/bootstrap.sh

You can also provide the decrypt passphrase up front:

KINIT_SETUP_PASSPHRASE='correct horse battery staple' \
  bash kInit.sh --setup-profile-url https://example.com/setup/alice/base

Requirements

  • Supported OS: Debian 11/12, Ubuntu 20.04/22.04/24.04 (x86_64, amd64)
  • Privileges: Must be run as root
  • Network: Internet access required for package downloads

Security

What We Do to Keep You Safe

Bootstrap Validation

  • kInit validates utils.sh using an embedded SHA256 checksum before executing
  • This protects the second-stage helper download after a trusted kInit.sh has started
  • Validation is performed automatically — no action is needed from you

Checksum Verification

  • Files downloaded through the standard module flow are verified against the pinned SHA256 manifest
  • Corrupted or tampered files are rejected with clear error messages
  • Checksums are regenerated during development using .scripts/unix/checksum.sh
  • Exception: a --setup-profile-url bootstrap is not in the manifest. It must use https:// and must be pinned via KINIT_SETUP_BOOTSTRAP_SHA256; without a pin it refuses to run unless you explicitly set KINIT_SETUP_BOOTSTRAP_ALLOW_UNVERIFIED=1

Signature Verification (optional)

  • Hash pinning proves a file matches kInit.sh, but not that kInit.sh and its embedded hashes are authentic. A detached minisign signature over checksums.sha256, made with a key held off-repo, closes that gap.
  • To enable: generate a keypair (minisign -G -p kinit.pub -s kinit.key), paste the public key into KINIT_MINISIGN_PUBKEY in kInit.sh, and sign each release with .scripts/unix/checksum.sh --sign (publishing checksums.sha256.minisig alongside the manifest).
  • When KINIT_MINISIGN_PUBKEY is empty (the default) signature verification is skipped; when set, kInit fails closed if the signature is missing or invalid.

Input Validation

  • All user inputs (hostnames, ports, SSH keys, timezones) are validated
  • Dangerous characters and injection attempts are rejected
  • SSH keys are validated for format and strength
  • Cron jobs are validated to prevent command injection

Secure Temporary Files

  • Temporary files are created with restrictive permissions (chmod 700)
  • Cron operations use secure temporary directories
  • Debug logs are created with permission mode 600 (readable only by owner)

Command Injection Prevention

  • Internal command wrappers execute commands as argv arrays instead of parsing command strings through a shell
  • User inputs that reach configuration files, cron entries, or service commands are validated before use

What You Should Do

Before Running

  1. Download the script first: wget https://kleb.sh/kInit.sh
  2. Review the code carefully before execution
  3. Run on a test system or fresh VM first
  4. Never use the one-liner pipe method on production systems

Protecting Credentials

  • SSH keys and other credentials should be protected with restrictive file permissions
  • Use local configuration files (.vars.local) for sensitive settings - these are git-ignored
  • Never commit passwords, API keys, or private keys to the repository
  • Debug logs may contain sensitive data — use shred -u to securely delete them

Checksum Bypass (Development Only)

  • Use KINIT_SKIP_CHECKSUMS=1 to skip validation during development
  • Requires interactive confirmation by typing "I UNDERSTAND THE RISKS"
  • Never use in production - checksums are critical for security

Reporting Security Issues

If you discover a security vulnerability, please report it responsibly:

  • Do NOT open a public GitHub issue
  • Contact the maintainers directly
  • Allow time for a fix before public disclosure

Architecture

Entry Point & Execution Flow

  1. kInit.sh - Main entry point that orchestrates the installation

    • Downloads utils.sh (shared utilities) and kInit.vars (module toggle config)
    • Executes enabled modules in order: System → Utilities → Software → Miscellaneous
    • Each module is downloaded, checksum-validated, and executed as a child script
    • Can optionally execute a remote kUtils setup profile bootstrap instead of the default module flow
  2. installer/utils.sh - Shared utility library sourced by all modules

    • Progress/logging functions (logInfo, logError, updateProgress, runWithSpinner)
    • Download with retry and checksum validation
    • Package installation utilities
    • File operations and service management
    • Cron and shell configuration helpers

Module Structure

Each module follows a consistent pattern:

  • installer/<module>/<module>.sh - Main script with lifecycle functions
  • installer/<module>/<module>.vars - Configuration variables
  • installer/<module>/files/ - Additional files (scripts, configs) deployed by the module

Available Modules:

  • system - Locale, timezone, SSH keys, virtualization detection, MOTD, Fish shell setup
  • utilities - Maintenance scripts (update.sh, clean.sh) and cron jobs
  • software - Zabbix Agent installation and monitoring addons
  • miscellaneous - Post-install tasks (runs update/clean scripts, reboot check)

What Gets Installed (Default Configuration)

The current configuration will install and configure the following components:

1. System Essentials

  • Packages installed: bc, curl, ethtool, fish, gnupg, btop, inotify-tools, lsb-release, moreutils, net-tools, nfs-common, sudo, unzip, wget, zip, cron, wtmpdb, bat, jq
  • Locale: Set to en_US.UTF-8
  • Timezone: Set to Europe/Berlin
  • SSH Keys: Installs datacenter-specific public SSH keys for root login, selected based on IP range detection
  • SSH Configuration: Enables MOTD and disables PrintLastLog in SSH
  • MOTD: Installs custom Message of the Day script, refreshed every 15 minutes via cron
  • Virtualization: Detects and installs guest agents for KVM/Proxmox, VMware, and LXC as needed
  • Shell: Installs and configures Fish shell with optional theme and custom aliases

2. Utilities

Two maintenance scripts are installed to $HOME and scheduled to run daily:

update.sh - System package updates

Refreshes the package lists, then upgrades all installed packages (pulling in new dependencies such as a new kernel) with appropriate dpkg options to avoid configuration conflicts. It does not remove packages — it is a plain upgrade, not a full-upgrade/dist-upgrade:

  • apt-get update
  • apt-get upgrade --with-new-pkgs
clean.sh - System cleanup

Performs regular maintenance:

  • Rotates and vacuums systemd journal
  • Runs apt autoremove and apt clean
  • Prunes Docker images (if Docker is installed)
  • Cron: Both scripts are scheduled to run @daily with MAILTO configured (empty by default)
  • Cleanup controls: CLEAN_VACUUM_JOURNAL, CLEAN_JOURNAL_VACUUM_TIME, and CLEAN_DOCKER_PRUNE are written to /etc/default/kinit-clean so cleanup behavior can be adjusted without editing the installed script.

3. Monitoring

  • Zabbix Agent 2 (default): Installed for system monitoring. Zabbix Agent 1 can be enabled via software.vars if required. The bundled per-distro zabbix.deb files are the small Zabbix repository-configuration package (zabbix-release, currently 7.4), not the agent itself; the agent binary is then installed from the official Zabbix apt repo (with apt's normal key verification). Refresh the bundled packages with .scripts/unix/download/zabbix.sh.
  • APT Monitoring: Includes Zabbix APT addon, scheduled to run every 5 minutes
  • LXC Monitoring (Agent 1 only, optional): The Zabbix LXC addon can be enabled and is installed when running in an LXC container.
  • Auto-detection: Zabbix server/proxy and hostname are automatically detected based on IP range, with configurable prefixes and suffixes

4. Miscellaneous

  • Runs update and clean scripts once after installation
  • Checks if system reboot is required and logs a notification

What Settings Are Changed

System Configuration

Setting Configuration
Locale en_US.UTF-8 in /etc/locale.gen and via update-locale
Timezone Europe/Berlin in /etc/localtime and /etc/timezone

SSH Configuration

  • Enables datacenter-specific public keys for root (IP range-based selection); a host whose IP matches no SSH_IP_RANGES entry installs no key unless SSH_KEY_DEFAULT_DC is set
  • Sets PermitRootLogin to prohibit-password (root login by SSH key only; password root login stays disabled), configurable via SSH_PERMIT_ROOT_LOGIN (set no for the CIS-recommended posture, using a separate sudo user instead)
  • When a key is installed, disables password authentication (PasswordAuthentication no + KbdInteractiveAuthentication no) so the installed key is the access path and no brute-force surface is left open; override with SSH_PASSWORD_AUTH="yes". This is only applied on hosts where a key was installed, so a host matching no SSH_IP_RANGES entry is never locked out
  • Sets LoginGraceTime to 60 (override via SSH_LOGIN_GRACE_TIME) to shrink the pre-auth window
  • Configures AuthorizedKeysFile (.ssh/authorized_keys) for key-based authentication
  • Applies these via /etc/ssh/sshd_config.d/00-kinit.conf when the host supports drop-ins (remove that file to revert), else edits /etc/ssh/sshd_config in place after backing it up, and validates with sshd -t before reloading
  • Enables PrintMotd, disables PrintLastLog
  • Comments out pam_mail.so in /etc/pam.d/sshd
  • Restarts SSH service with changes

Services and Cron

  • MOTD: Replaces /etc/update-motd.d/* with custom script and cron refresh job
  • Crontab: Adds jobs for update, clean, and MOTD refresh with MAILTO configuration
  • Zabbix: Installs and configures Zabbix Agent 2, APT monitoring, and LXC monitoring as per environment
  • Idempotency: Cron jobs, Fish aliases, and file-based settings are only added if missing, so rerunning the installer does not duplicate entries.

Shell Configuration

Fish shell is configured with the following features (if enabled in system.vars):

  • Set as default shell for root
  • Fisher package manager installed
  • Catppuccin Mocha theme applied
  • Custom aliases:
    • batbatcat (requires batcat package)
    • pcnetstat -tupln (displays listening ports)
  • Aliases stored in ~/.config/fish/conf.d/aliases.fish

Customization

Editing Settings

Each module has a .vars configuration file:

  • system.vars - System module configuration
  • utilities.vars - Utilities module configuration
  • software.vars - Software/monitoring configuration
  • miscellaneous.vars - Miscellaneous module configuration
  • checksums.sha256 - File integrity checksums

To customize the installer:

  1. Download the relevant .vars file:

    wget https://kleb.sh/installer/system/system.vars
    
  2. Edit the variables to your needs

  3. Run the installer with your custom configuration:

    bash <(wget -qO- https://kleb.sh/kInit.sh) --base-url https://yourdomain
    

Available URL options:

  • --system-url - Custom system configuration
  • --utilities-url - Custom utilities configuration
  • --local-files - Resolve bundled module assets from BASE_URL instead of https://kleb.sh
  • --software-url - Custom software configuration
  • --miscellaneous-url - Custom miscellaneous configuration
  • --checksum-url - Custom checksum file URL used for download verification
  • --checksum-sha256 - Expected SHA256 for a custom integrity manifest URL

Additional CLI flags:

  • --continue-on-error - Continue execution even if a module download or script fails
  • --analyze - Print configuration and module results before cleanup (CI/CD mode)
  • --setup-profile-url - Execute a remote setup profile bootstrap URL instead of the default module flow (must be https://)
  • --setup-passphrase - Provide the passphrase for a remote setup profile (prefer the KINIT_SETUP_PASSPHRASE env var; a value passed here is visible in process listings)
  • --log-view <auto|tty|off> - Live log view mode (default: auto)
  • --log-tty <number> - Virtual terminal for the live log view (default: 2)
  • --help - Show the built-in usage/help text

Recommendation: For advanced customizations, fork this repository and maintain your own installer scripts and variable files for easier long-term management. Sanitized starting points are provided as installer/system/system.vars.example and installer/software/software.vars.example — copy them to the corresponding .vars and replace the placeholders with your own keys, IP ranges, and Zabbix server. Never commit real SSH keys or internal addresses to a public fork.

Cleanup Configuration

The Utilities module installs /root/clean.sh and writes /etc/default/kinit-clean from utilities.vars:

  • CLEAN_VACUUM_JOURNAL="TRUE" - rotate and vacuum systemd journal logs during cleanup
  • CLEAN_JOURNAL_VACUUM_TIME="7d" - journal retention passed to journalctl --vacuum-time (set lower only if you deliberately want shorter retention; 1s erases almost the entire journal)
  • CLEAN_DOCKER_PRUNE="TRUE" - prune Docker images older than 24 hours when Docker is installed (dangling/untagged layers only by default)
  • CLEAN_DOCKER_PRUNE_ALL="FALSE" - set to TRUE to also remove all unused tagged images older than 24h (docker image prune -a); leave FALSE to preserve the image cache

Remote Setup Profiles

kInit can execute a remote setup profile bootstrap generated by kUtils.

  • --setup-profile-url / -sp points to the published bootstrap URL or its parent setup profile URL
  • --setup-passphrase / -spp pre-seeds the decryption passphrase for non-interactive use
  • KINIT_SETUP_PROFILE_URL provides the same URL through the environment
  • KINIT_SETUP_PASSPHRASE and KUTILS_SETUP_PASSPHRASE are both honored for generated bootstraps

When a setup profile URL is provided, kInit downloads the remote bootstrap into a secure temporary directory, executes it, and skips the default kInit.vars module-download flow for that run.

Disabling/Enabling Modules

Edit kInit.vars to enable or disable specific installation modules:

  • SYSTEM_EXECUTE="TRUE" or "FALSE" - System configuration
  • UTILITIES_EXECUTE="TRUE" or "FALSE" - Maintenance utilities
  • SOFTWARE_EXECUTE="TRUE" or "FALSE" - Zabbix monitoring
  • MISCELLANEOUS_EXECUTE="TRUE" or "FALSE" - Post-install tasks

Fish Shell Configuration

Customize Fish shell behavior by editing system.vars:

  • FISH_DEFAULT_SHELL="TRUE" - Set Fish as default shell
  • FISH_INSTALL_FISHER="TRUE" - Install Fisher package manager
  • FISHER_SHA256="<sha256>" - Required when Fisher installation is enabled
  • FISH_INSTALL_CATPPUCCIN="TRUE" - Apply Catppuccin Mocha theme
  • FISH_ALIAS_BAT="TRUE" - Enable batbatcat alias
  • FISH_ALIAS_PC="TRUE" - Enable pcnetstat -tupln alias

Breaking Changes

Version 3.3+

Removed Features

  • --skip-checksums CLI flag has been removed for security reasons
  • Use environment variable instead: KINIT_SKIP_CHECKSUMS=1

Changed Behavior

  • Checksum bypass now requires interactive confirmation
  • Users must type "I UNDERSTAND THE RISKS" to skip validation
  • Bootstrap validation is enabled by default (validates utils.sh before sourcing)
  • All inputs are now validated (hostnames, ports, SSH keys, etc.)

Migration Guide

If you're using the old --skip-checksums flag:

# OLD (no longer works)
bash kInit.sh --skip-checksums

# NEW (requires confirmation)
KINIT_SKIP_CHECKSUMS=1 bash kInit.sh
# Then type: I UNDERSTAND THE RISKS

New environment variables:

  • KINIT_SKIP_CHECKSUMS=1 - Skip checksum validation (requires confirmation)
  • KINIT_SKIP_BOOTSTRAP_VALIDATION=1 - Skip utils.sh validation (development only)
  • KINIT_SETUP_PROFILE_URL=<url> - Remote setup profile bootstrap or setup URL
  • KINIT_SETUP_PASSPHRASE=<value> - Remote setup-profile passphrase
  • KUTILS_SETUP_PASSPHRASE=<value> - Alternate passphrase variable for generated kUtils setup bootstraps
  • AUTO_DELETE_DEBUG_LOG=TRUE - Auto-delete debug logs after execution

Development

Line Ending Conversion

Before committing changes, ensure Unix line endings for all shell scripts:

bash .scripts/unix/unix-format.sh

Generating Checksums

After modifying any files under installer/, regenerate the integrity manifest:

cd .scripts/unix
bash checksum.sh

Running Tests

Unit tests for the validation helpers (SSH keys, cron lines, hostnames, ports, timezones, secret redaction) live in tests/ and run with bats-core:

bats tests/

Run these together with ShellCheck and sha256sum -c checksums.sha256 before committing changes.

Local Testing

Test the installer locally by serving the repository and pointing both module scripts and bundled assets at that local server:

python3 -m http.server 8000
bash kInit.sh --base-url "http://localhost:8000" --local-files --checksum-sha256 "<sha256_of_local_checksums.sha256>"

Uninstallation / Restoration

This installer makes system-level changes. A best-effort uninstall.sh is provided:

sudo bash uninstall.sh

It restores the config backups kInit creates (*.kinit-bak-*), removes the /etc/ssh/sshd_config.d/00-kinit.conf drop-in, deletes kInit-installed files and cron jobs, and reloads SSH only if the config still validates. It deliberately does not remove installed packages or SSH authorized keys.

To finish reverting manually:

  • Review/remove keys in ~/.ssh/authorized_keys if desired
  • Remove installed packages using apt remove or apt purge (e.g. zabbix-agent2, fish)
  • Delete the leftover *.kinit-bak-* backups once satisfied

Recommendation: Take a snapshot or create a backup before running the installer on production systems.


Disclaimer

This project is provided "as is" without any warranties or guarantees, express or implied.

Risk Acknowledgment:

  • Use this software at your own risk
  • The authors and contributors are not responsible for damage, data loss, or issues arising from use
  • Review all code and configuration before use, especially in production
  • No support or maintenance is guaranteed
  • Features may change or be removed without notice
  • By using this project, you accept full responsibility for consequences

Always back up your data and thoroughly test in a safe environment before deploying to production.


License

This project is licensed under the MIT License. See the LICENSE file for details.


Feedback

Questions, suggestions, or issues?