Shell installer scripts
Shell Installer Scripts
Self-contained Bash installers for VPS setup. All Telegram-aware scripts read credentials from /etc/telegram.conf (owner root:root, permissions 600). Scripts that require it interactively prompt for missing values during execution; install-shutdown-notify.sh is the exception and performs a hard abort if the file is absent.
Remote execution pattern (all scripts):
curl -s https://coolscript.net/download/shell/<script-name>.sh | sudo bash
Security: piping curl to bash executes unreviewed remote code — only use against URLs you control.
install-sudo.sh
- Run on VPS
su -c 'curl -s https://coolscript.net/download/shell/install-sudo.sh | bash'
Installs sudo (if missing) and adds a target non-root user to the sudo group. This is required first on Debian systems that start without sudo preinstalled. No Telegram dependency.
Root required. Run as root (for example: su -) before executing. You can pass a username as the first script argument; if omitted, the script uses $SUDO_USER or prompts.
Installation Flow
[ run as root ] ──► detect target user (arg / $SUDO_USER / prompt)
│
▼
user exists?
├── NO → abort
└── YES → continue
│
▼
sudo installed?
├── YES → skip install
└── NO → apt update && apt install sudo
│
▼
user in sudo group?
├── YES → skip
└── NO → usermod -aG sudo <user>
Notes
- Required first step for minimal Debian images that do not include
sudo - Group change applies on next login session
install-telegram-ssh-alert.sh
- Run on VPS
curl -s https://coolscript.net/download/shell/install-telegram-ssh-alert.sh | sudo bash
Hooks a Telegram alert into the PAM SSH stack so every successful SSH login sends a message. Uses pam_exec with the optional keyword — alert failure never blocks login. The installer is idempotent (checks for existing PAM line before appending).
/etc/telegram.conf
Must exist and contain valid non-empty values. If absent or incomplete the installer pauses and prompts interactively — credentials can be entered inline during curl | bash execution.
# Telegram Alert Configuration TELEGRAM_CHAT_ID="-1xxx" TELEGRAM_BOT_TOKEN="53xxxxx"
TELEGRAM_CHAT_ID: negative values are group/channel IDs. TELEGRAM_BOT_TOKEN: issued by @BotFather. Permissions applied automatically; to reapply manually:
chown root:root /etc/telegram.conf && chmod 600 /etc/telegram.conf
Alert Script
Written to /usr/local/bin/telegram-ssh-alert.sh. Fires only on PAM_TYPE=open_session; ignores auth failures and session close. Sent asynchronously (curl ... &) — zero login latency impact.
| Variable | Source | Content |
|---|---|---|
PAM_USER |
PAM | Logged-in username |
PAM_RHOST |
PAM | Remote client IP |
hostname |
syscall | VPS hostname |
date |
syscall | Timestamp YYYY-MM-DD HH:MM:SS
|
Message format (HTML parse mode):
🚨 SSH Access Alert ─────────────── 👤 User: testuser 🖥️ Host: my-vps-hostname 🌐 IP Address: 203.0.113.42 ⏰ Time: 2026-07-27 14:35:00 ───────────────
API call:
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-d "chat_id=${TELEGRAM_CHAT_ID}" \
-d "parse_mode=HTML" \
-d "text=${MESSAGE}" > /dev/null 2>&1 &
PAM Line
session optional pam_exec.so /usr/local/bin/telegram-ssh-alert.sh
Installation Flow
[ curl | bash ] ──► root check
│
▼
/etc/telegram.conf exists?
├── YES → variables non-empty? ──► YES → continue
│ └── NO → prompt
└── NO → prompt
│
▼
Write + chmod +x /usr/local/bin/telegram-ssh-alert.sh
│
▼
PAM line in /etc/pam.d/sshd?
├── YES → skip
└── NO → append
│
▼
Live test: PAM_TYPE=open_session PAM_USER=InstallerTest PAM_RHOST=127.0.0.1
Files
| File | Perm | Role |
|---|---|---|
/etc/telegram.conf |
600 | Credentials — must be valid |
/usr/local/bin/telegram-ssh-alert.sh |
+x | PAM-invoked alert script |
/etc/pam.d/sshd |
— | PAM config (one line appended) |
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| No notification on login | /etc/telegram.conf missing or placeholder values |
Recreate from template; rerun installer |
| Login blocked | PAM line uses required instead of optional |
Edit /etc/pam.d/sshd to use optional
|
| Test works, live SSH does not | PAM cannot read config (wrong permissions) | chmod 600 /etc/telegram.conf, owner must be root
|
curl: command not found |
curl absent | apt install curl / yum install curl
|
| Duplicate PAM entries | Installer run multiple times | Remove duplicate lines from /etc/pam.d/sshd
|
install-boot-notify.sh
- Run on VPS
curl -s https://coolscript.net/download/shell/install-boot-notify.sh | sudo bash
Installs a systemd one-shot service (After=network-online.target) that sends hostname, local IP, public IP (ifconfig.me), and timestamp to Telegram on every boot.
Root required. Interactive — prompts for credentials if /etc/telegram.conf is absent or incomplete (same flow as SSH alert installer). Config file created with chmod 600 automatically.
Files
| File | Perm | Role |
|---|---|---|
/usr/local/bin/telegram-boot-notify.sh |
700 | Notification script |
/etc/systemd/system/telegram-boot-notify.service |
— | Systemd unit (enabled automatically) |
/etc/telegram.conf |
600 | Credentials — created if absent |
Systemd Unit
[Unit] Description=Send Telegram notification with IP address on startup After=network-online.target Wants=network-online.target [Service] Type=oneshot ExecStart=/usr/local/bin/telegram-boot-notify.sh RemainAfterExit=yes [Install] WantedBy=multi-user.target
RemainAfterExit=yes keeps the unit active after script exit so systemctl status shows the last run result.
Notification
🚀 Server Boot Notification 🖥 Host: my-vps-hostname 📅 Date & Time: 2026-07-27 09:00:00 UTC 📡 IP Addresses: • Local IP: 10.0.0.5 • Public IP: 203.0.113.42
Uses Markdown parse mode. Local IP via ip route get 1.1.1.1; public IP via curl ifconfig.me (10 s timeout, falls back to "Unavailable").
install-shutdown-notify.sh
- Run on VPS
curl -s https://coolscript.net/download/shell/install-shutdown-notify.sh | sudo bash
Installs a systemd service that fires a Telegram notification on shutdown or reboot. Detects event type by inspecting active systemd jobs at stop time.
Root required. /etc/telegram.conf must already exist with valid values — this script performs a hard abort if missing or empty. It does not prompt interactively.
Validate before running:
source /etc/telegram.conf && echo "$TELEGRAM_BOT_TOKEN" && echo "$TELEGRAM_CHAT_ID"
Files
| File | Perm | Role |
|---|---|---|
/usr/local/bin/telegram-shutdown-notify.sh |
700 | Notification script |
/etc/systemd/system/telegram-shutdown-notify.service |
— | Systemd unit (enabled automatically) |
Systemd Unit
[Unit] Description=Send Telegram notification on system shutdown or reboot DefaultDependencies=no After=network-online.target time-sync.target Requires=network-online.target [Service] Type=oneshot ExecStart=/bin/true ExecStop=/usr/local/bin/telegram-shutdown-notify.sh RemainAfterExit=yes [Install] WantedBy=multi-user.target
The notification runs from ExecStop — triggered when systemd stops the unit during shutdown, while the network is still up. DefaultDependencies=no prevents default shutdown ordering from running the unit too late.
Event Detection
| Detected job | Message label |
|---|---|
reboot.target starting |
Rebooting 🔄 |
poweroff.target / halt.target starting |
Shutting Down 🛑 |
| None matched | Stopping / Shutting Down 🛑 |
Notification
🛑 Server Event: Shutting Down 🛑 🖥 Host: my-vps-hostname 📅 Date & Time: 2026-07-27 23:59:00 UTC ⏱ Uptime before event: up 3 days, 4 hours, 12 minutes
install-clean-shutdown.sh
- Run on VPS
curl -s https://coolscript.net/download/shell/install-clean-shutdown.sh | sudo bash
Installs a udev rule that triggers shutdown -h now when a USB stick with the filesystem label RASPI-CLEAN-SHUTDOWN is inserted. Designed for Raspberry Pi but works on any udev-based Linux system. No Telegram dependency.
Primarily used on Raspberry Pi hosts for clean power-off without keyboard/network access.
Root required. If the script or rule already exists the installer asks before overwriting; declining skips that component without aborting.
Files
| File | Role |
|---|---|
/usr/local/bin/usb-clean-shutdown.sh |
Logs via logger -t raspi-shutdown then calls shutdown -h now
|
/etc/udev/rules.d/90-raspi-shutdown.rules |
udev rule — watches block devices for the label |
udev Rule
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="RASPI-CLEAN-SHUTDOWN", RUN+="/usr/local/bin/usb-clean-shutdown.sh"
Fires on ACTION==add (insert), SUBSYSTEM==block, label match is case-sensitive.
Prepare the USB Stick
# FAT32 mkfs.vfat -n RASPI-CLEAN-SHUTDOWN /dev/sdX # ext4 mkfs.ext4 -L RASPI-CLEAN-SHUTDOWN /dev/sdX
Verify the label before use: lsblk -o NAME,LABEL. Confirm syslog entry after trigger: journalctl -t raspi-shutdown.
install-fzf.sh
- Run on VPS
curl -s https://coolscript.net/download/shell/install-fzf.sh | bash
Installs fzf via apt-get and appends the keybinding source line to ~/.bashrc. Idempotent — skips append if the line is already present. No root required (uses sudo internally for apt). No Telegram dependency.
Apply after install: source ~/.bashrc
Keybindings
| Key | Action |
|---|---|
| Ctrl+R | Fuzzy search shell history |
| Ctrl+T | Fuzzy-find file, paste path to prompt |
| Alt+C | Fuzzy-find directory and cd into it
|
The installer auto-detects the keybindings file from three standard paths (/usr/share/doc/fzf/examples/, /usr/share/fzf/, /usr/share/doc/fzf/). Exits with an error if none exist — this can occur on non-Debian distributions.
install-prompt.sh
- Run on VPS
curl -s https://coolscript.net/download/shell/install-prompt.sh | bash
Sets a colourful PS1 prompt in ~/.bashrc. No root required. No Telegram dependency. Idempotent — checks for ANSI codes 01;31m and 01;35m before appending.
Apply after install: source ~/.bashrc
Prompt
user@hostname /current/directory $
| Element | Colour |
|---|---|
\u (user) |
Bold red 01;31m
|
\h (host) |
Bold cyan 01;36m
|
\w (path) |
Bold yellow 01;33m
|
$ |
Bold magenta 01;35m
|
install-neofetch.sh
- Run on VPS
curl -s https://coolscript.net/download/shell/install-neofetch.sh | sudo bash
Installs neowofetch via apt and creates a global profile trigger at /etc/profile.d/neowofetch-ssh.sh that automatically runs neowofetch for any user logging in via SSH. No Telegram dependency.
Apply immediately without rebooting: open a new SSH session.
Files
| File | Perm | Role |
|---|---|---|
/etc/profile.d/neowofetch-ssh.sh |
644 | Global profile trigger — runs neowofetch on SSH login
|
Profile Trigger
# Auto-run neowofetch on SSH login for all users
if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
# Run only if standard output is a TTY and NOT running under sudo/sudo -i
if [ -t 1 ] && [ -z "$SUDO_USER" ]; then
neowofetch
fi
fi
Conditions for execution:
SSH_CLIENTorSSH_TTYis set — real SSH session- stdout is a TTY (
-t 1) — suppresses output in non-interactive contexts (e.g.,scp, automated scripts) SUDO_USERis unset — does not fire again forsudo -ishells inside an existing session
install-core-tools.sh
- Run on VPS
curl -s https://coolscript.net/download/shell/install-core-tools.sh | sudo bash
Installs a comprehensive set of development, networking, and shell utility packages via apt in a single pass. No Telegram dependency.
Packages
| Group | Packages |
|---|---|
| Build tools | build-essential, gdb, valgrind, cmake, ninja-build, pkg-config
|
| Version control | git, git-lfs
|
| Python | python3, python3-pip, python3-venv
|
| Dev libraries | libssl-dev, libffi-dev, zlib1g-dev
|
| Network (config) | iproute2, net-tools, iputils-ping, traceroute, mtr-tiny, dnsutils
|
| Network (probe) | curl, wget, nmap, tcpdump, socat, netcat-openbsd
|
| Network (monitor) | iftop, nload
|
| Shell utilities | htop, jq, tree, tmux
|
install-docker.sh
- Run on VPS
curl -s https://coolscript.net/download/shell/install-docker.sh | sudo bash
Installs Docker CE from the official Docker apt repository using the distro's GPG key. Adds the invoking user to the docker group. No Telegram dependency.
Root required. Group membership takes effect after logout/login or newgrp docker.
Installation Flow
[ curl | bash ] ──► Install prerequisites (ca-certificates, curl)
│
▼
Add Docker GPG key → /etc/apt/keyrings/docker.asc
│
▼
Add apt source → /etc/apt/sources.list.d/docker.list
│
▼
apt update && install docker-ce, docker-ce-cli, containerd.io,
docker-buildx-plugin, docker-compose-plugin
│
▼
usermod -aG docker $USER
Files
| File | Role |
|---|---|
/etc/apt/keyrings/docker.asc |
Docker signing key (chmod a+r)
|
/etc/apt/sources.list.d/docker.list |
Docker apt repository entry |
Packages Installed
| Package | Role |
|---|---|
docker-ce |
Docker daemon |
docker-ce-cli |
docker CLI
|
containerd.io |
Container runtime |
docker-buildx-plugin |
Multi-platform image builds |
docker-compose-plugin |
docker compose subcommand
|
Summary
| Script | Root | /etc/telegram.conf | Mechanism | Interactive | curl install |
|---|---|---|---|---|---|
install-sudo.sh |
Yes (must run as root) | Not used | apt sudo install + usermod -aG sudo |
Yes — may prompt for username | su -c 'curl -s https://coolscript.net/download/shell/install-sudo.sh | bash -s username'
|
install-prompt.sh |
No | Not used | ~/.bashrc PS1 |
No | curl -s https://coolscript.net/download/shell/install-prompt.sh | bash
|
install-fzf.sh |
No (sudo inside) | Not used | apt + ~/.bashrc |
No | curl -s https://coolscript.net/download/shell/install-fzf.sh | bash
|
install-core-tools.sh |
Yes (sudo inside) | Not used | apt bulk install | No | curl -s https://coolscript.net/download/shell/install-core-tools.sh | sudo bash
|
install-docker.sh |
Yes | Not used | Official Docker apt repo + GPG key | No | curl -s https://coolscript.net/download/shell/install-docker.sh | sudo bash
|
install-telegram-ssh-alert.sh |
Yes | Creates if missing | PAM pam_exec optional |
Yes — credential prompt | curl -s https://coolscript.net/download/shell/install-telegram-ssh-alert.sh | sudo bash
|
install-boot-notify.sh |
Yes | Creates if missing | systemd one-shot | Yes — credential prompt | curl -s https://coolscript.net/download/shell/install-boot-notify.sh | sudo bash
|
install-shutdown-notify.sh |
Yes | Must exist (hard abort) | systemd ExecStop |
No | curl -s https://coolscript.net/download/shell/install-shutdown-notify.sh | sudo bash
|
install-clean-shutdown.sh |
Yes | Not used | udev block rule for Raspberry | Yes — overwrite prompt | curl -s https://coolscript.net/download/shell/install-clean-shutdown.sh | sudo bash
|
install-neofetch.sh |
Yes (sudo inside) | Not used | /etc/profile.d global trigger |
No | curl -s https://coolscript.net/download/shell/install-neofetch.sh | sudo bash
|
Recommended Installation Order
install-sudo.sh— required first on Debian images wheresudois not installedinstall-prompt.shinstall-fzf.shinstall-core-tools.sh— standalone, no ordering constraintinstall-docker.sh— standalone, no ordering constraintcreate /etc/telegram.conf— add TELEGRAM_CHAT_ID and TELEGRAM_BOT_TOKENinstall-telegram-ssh-alert.sh— creates/etc/telegram.confinteractivelyinstall-boot-notify.sh— reuses or creates/etc/telegram.confinstall-shutdown-notify.sh— requires/etc/telegram.confto already existinstall-clean-shutdown.sh— standalone, no ordering constraintinstall-neofetch.sh— standalone, no ordering constraint