diff --git a/README.md b/README.md index c2fefe8..263fe18 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,14 @@ A collection of battle-tested scripts and utilities for system administrators, D --- -### 📂 Navigation Table +## 📂 Navigation Table This toolbox contains a `mix` of `built-in scripts` and `links to my standalone specialized projects` for easier navigation. | OS | Stack | Utility Name | Description | Status | | :--- | :--- | :--- | :--- | :--- | -| ![Windows](https://img.shields.io/badge/Windows-0078D6?style=flat-square&logo=windows&logoColor=white) | ![Batch](https://img.shields.io/badge/-Batch-4D4D4D?style=flat-square) | [AnyDesk Reset](./tools/windows/apps-reset/anydesk-id-reseter.bat) | Terminate [AnyDesk](https://anydesk.com/en) & clear config files (`ID reset`) | ✅ Stable
🧰 Built-in  | -| ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat-square&logo=linux&logoColor=black) | ![Bash](https://img.shields.io/badge/-Bash-4EAA25?style=flat-square) | [Juniper Network Toggle](./tools/linux/juniper-ctrl/juniper-net-toggle/juniper-net-toggle.sh) | Remote toggle for [Juniper](https://www.juniper.net/) interfaces & static routes | ✅ Stable
🧰 Built-in  | -| ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat-square&logo=linux&logoColor=black) | ![Bash](https://img.shields.io/badge/-Bash-4EAA25?style=flat-square) | [Directory Comparator](./tools/linux/compare-dirs/compare-dirs.sh) | Recursive file comparison between two directories with detailed diff logging | ✅ Stable
🧰 Built-in  | +| ![Windows](https://img.shields.io/badge/Windows-0078D6?style=flat-square&logo=windows&logoColor=white) | ![Batch](https://img.shields.io/badge/-Batch-4D4D4D?style=flat-square) | [AnyDesk Reset](./tools/windows/apps-reset) | Terminate [AnyDesk](https://anydesk.com/en) & clear config files (`ID reset`) | ✅ Stable
🧰 Built-in  | +| ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat-square&logo=linux&logoColor=black) | ![Bash](https://img.shields.io/badge/-Bash-4EAA25?style=flat-square) | [Docker Network Manager](./tools/linux/docker-ce/network-manager) | Auto-IPAM & static bridge naming for `Docker` bridge networks | ✅ Stable
🧰 Built-in  | +| ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat-square&logo=linux&logoColor=black) | ![Bash](https://img.shields.io/badge/-Bash-4EAA25?style=flat-square) | [Juniper Network Toggle](./tools/linux/juniper-ctrl/juniper-net-toggle) | Remote toggle for [Juniper](https://www.juniper.net/) interfaces & static routes | ✅ Stable
🧰 Built-in  | +| ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat-square&logo=linux&logoColor=black) | ![Bash](https://img.shields.io/badge/-Bash-4EAA25?style=flat-square) | [Directory Comparator](./tools/linux/compare-dirs) | Recursive file comparison between two directories with detailed diff logging | ✅ Stable
🧰 Built-in  | | ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat-square&logo=linux&logoColor=black) | ![Bash](https://img.shields.io/badge/-Bash-4EAA25?style=flat-square) | [PSQL NFS Backup](https://github.com/andsyrovatko/s4k-psql-db-backuper) | Automation for [PostgreSQL](https://www.postgresql.org/) dumps with [NFS](https://en.wikipedia.org/wiki/Network_File_System) & [Telegram](https://telegram.org/) | ✅ Stable
📦 Standalone  | | ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat-square&logo=linux&logoColor=black) | ![Bash](https://img.shields.io/badge/-Bash-4EAA25?style=flat-square) | [PVE Rsync Backup Pro](https://github.com/andsyrovatko/s4k-pve-rsync-backup) | Surgical [Proxmox VE](https://www.proxmox.com/) VM backups with log-parsed paths & auto-cleanup | ✅ Stable
📦 Standalone  | | ![Linux](https://img.shields.io/badge/Linux-FCC624?style=flat-square&logo=linux&logoColor=black) | ![Bash](https://img.shields.io/badge/-Bash-4EAA25?style=flat-square) | [Whois Infrastructure Automator (for ISPs)](https://github.com/andsyrovatko/s4k-billing-whois-automator) | Automation for Whois DB update by billing system | ✅ Stable
📦 Standalone  | @@ -21,6 +22,15 @@ This toolbox contains a `mix` of `built-in scripts` and `links to my standalone --- +## ⭐ Featured Tools + +### 🐳 Docker Network Manager +A surgical tool for managing Docker infrastructure. It eliminates the "random bridge names" problem by forcing static names at the OS level, making it perfect for custom firewall rules and network monitoring. +- **Auto-IPAM**: Scans and assigns free subnets. +- **Native Naming**: Direct mapping between Docker names and Linux interfaces. + +--- + ### ⚠️ Disclaimer > **Use at your own risk!** These scripts are designed for administrative tasks and may perform destructive actions (like killing processes or deleting config files). The author is not responsible for any data loss or system instability. Always test in a sandbox environment first. diff --git a/tools/linux/docker-ce/network-manager/README.md b/tools/linux/docker-ce/network-manager/README.md new file mode 100644 index 0000000..5613599 --- /dev/null +++ b/tools/linux/docker-ce/network-manager/README.md @@ -0,0 +1,91 @@ +# 🐳 Docker Network Manager + +A lightweight, production-ready Bash utility to manage external Docker bridge networks with automatic IPAM (IP Address Management). It ensures your network configurations are persistent, documented, and free from subnet overlaps. + +--- + +## 🚀 Key Features +* **Smart Subnet Allocation:** Automatically finds the next available /24 block within your specified range (e.g., `172.30.x.x`). +* **Infrastructure as Code (Lite):** Keep your network names in a simple text file; the script handles the rest. +* **Safe Operations:** + * Interactive confirmation for bulk deletions. + * ShellCheck-validated code (Strict Mode: `set -euo pipefail`). + * Non-interactive mode support (via `FORCE=true`). +* **Status Dashboard:** Instant overview of which tracked networks are `ONLINE` or `OFFLINE`. + +## 🛠 Installation & Setup +1. **Clone the repo** (or add the code to your admin toolbox). +2. Create the config file: +```bash +cp docker-network-manager.conf.example docker-network-manager.conf +#OR +cat < docker-network-manager.conf +NET_FILE="./dnm-networks.txt" +LOG_FILE="./dnm-networks.log" +BASE_NET="172.30" +START_OCTET=0 +END_OCTET=255 +EOF +``` +3. **Make script executable:** +```bash +chmod +x docker-network-manager.sh +``` + +## 📖 Usage Examples +1. **Check current status** + ```bash + ./docker-network-manager.sh info + ``` + Example:\ + ![Dashboard Preview](assets/info-screen.png) +2. **Provision networks** + * **From file:** Add network names to dnm-networks.txt and run: + ```bash + ./docker-network-manager.sh create + ``` + * **Single network:** + ```bash + ./docker-network-manager.sh create br-project-alpha + ``` +3. **Decommission networks** + * **Remove and cleanup:** + ```bash + ./docker-network-manager.sh delete br-project-alpha + ``` + * **Purge all (from file):*** + ```bash + ./docker-network-manager.sh delete + ``` + +### ⚠️ IMPORTANT +> **Interface Name Limit**: Linux has a **15-character** limit for network interface names. Ensure your Docker network names stay within this limit to maintain consistent bridge naming. + +## 🧩 Native OS Integration +Unlike standard Docker networks that create cryptic interface names (e.g., br-837d9f...), this manager assigns the actual network name to the Linux bridge interface. + +This allows you to: +* Monitor traffic per-network using standard tools (tcpdump -i br-test1). +* Create persistent firewall rules (IPTables/NFTables) targeting specific bridges. +* Easily identify networks in ip addr or ifconfig output.\ +Example:\ +![Dashboard Preview](assets/ip-a-test.png) + +## 📊 Summary Table of Commands +| Command | Short | Argument | Description | +| :--- | :--- | :--- | :--- | +| `create` | `c` | [name] | Provisions network(s) and updates config file. | +| `delete` | `d` | [name] | Removes network(s) from Docker and config file. | +| `info` | `i` | - | Displays dashboard with IP ranges and statuses. | + +## ⚙️ Configuration Variables +| Variable | Default | Description | +| :--- | :--- | :--- | +| `BASE_NET` | `172.30` | The first two octets of your managed pool. | +| `START_OCTET` | `0` | Starting range for the 3rd octet. | +| `END_OCTET` | `255` | Ending range for the 3rd octet. | +| `NET_FILE` | `./dnm-networks.txt` | File where network names are stored. | +--- + +### ⚖️ License +MIT [LICENSE](https://github.com/andsyrovatko/s4k-admin-toolbox/blob/main/LICENSE). Free to use and modify. diff --git a/tools/linux/docker-ce/network-manager/assets/info-screen.png b/tools/linux/docker-ce/network-manager/assets/info-screen.png new file mode 100644 index 0000000..cd3bd59 Binary files /dev/null and b/tools/linux/docker-ce/network-manager/assets/info-screen.png differ diff --git a/tools/linux/docker-ce/network-manager/assets/ip-a-test.png b/tools/linux/docker-ce/network-manager/assets/ip-a-test.png new file mode 100644 index 0000000..5399b4a Binary files /dev/null and b/tools/linux/docker-ce/network-manager/assets/ip-a-test.png differ diff --git a/tools/linux/docker-ce/network-manager/dnm-networks.txt b/tools/linux/docker-ce/network-manager/dnm-networks.txt new file mode 100644 index 0000000..698ce7a --- /dev/null +++ b/tools/linux/docker-ce/network-manager/dnm-networks.txt @@ -0,0 +1,5 @@ +# br-test1 +#br-test2 +br-test3 +br-longname_not_allowed-test4 +br-test5 diff --git a/tools/linux/docker-ce/network-manager/docker-network-manager.conf.example b/tools/linux/docker-ce/network-manager/docker-network-manager.conf.example new file mode 100644 index 0000000..07f67bc --- /dev/null +++ b/tools/linux/docker-ce/network-manager/docker-network-manager.conf.example @@ -0,0 +1,6 @@ +# MAIN VARIABLES +NET_FILE="./dnm-networks.txt" +LOG_FILE="./dnm-networks.log" +BASE_NET="172.30" +START_OCTET=0 +END_OCTET=255 diff --git a/tools/linux/docker-ce/network-manager/docker-network-manager.sh b/tools/linux/docker-ce/network-manager/docker-network-manager.sh new file mode 100755 index 0000000..c5e394d --- /dev/null +++ b/tools/linux/docker-ce/network-manager/docker-network-manager.sh @@ -0,0 +1,213 @@ +#!/usr/bin/env bash +# ============================================================================= +# Script Name : docker-network-manager.sh +# Description : Manage Docker external networks with automatic subnet allocation and tracking. +# Usage: : ./docker-network-manager.sh [ARGUMENTS] +# Commands: +# create [NAME] - Create a specific network by name or all networks from file if NO NAME provided. +# delete [NAME] - Delete a specific network by name or all networks from file if NO NAME provided. +# info - Show current status and configuration. +# For details - see README.md +# Author : syr4ok (Andrii Syrovatko) +# Version : 1.1.0 +# ============================================================================= + +# --- STRICT MODE --- +set -euo pipefail + +# Configuration Loader +CONFIG_FILE="$(dirname "$0")/docker-network-manager.conf" +if [[ -f "$CONFIG_FILE" ]]; then + # shellcheck source=/dev/null + source "$CONFIG_FILE" +else + echo "[Error]: Configuration file not found. Create ip_manager.conf from example." + exit 1 +fi + +touch "$NET_FILE" + +log() { + local level="$1"; shift + printf '%s [%s] %s\n' "$(date -Is)" "$level" "$*" | tee -a "$LOG_FILE" +} + +confirm_action() { + [[ "${FORCE:-false}" == "true" ]] && return 0 + + read -rp "Are you sure you want to delete ALL networks from $NET_FILE? (y/N): " response + case "$response" in + [yY][eE][sS]|[yY]) return 0 ;; + *) log INFO "Operation cancelled by user"; exit 0 ;; + esac +} + +# Network check +network_exists() { + docker network ls --format '{{.Name}}' | grep -Fxq "$1" +} + +used_subnets() { + local escaped_base="${BASE_NET//./\\.}" + + # Get all subnets from existing Docker networks and filter those that match our base pattern + docker network ls -q | xargs -r docker network inspect 2>/dev/null \ + | grep -oP '"Subnet":\s*"\K'"${escaped_base}"'\.[0-9]+\.0/24' || echo "" +} + +next_free_subnet() { + local used="$1" + for i in $(seq "$START_OCTET" "$END_OCTET"); do + local subnet="${BASE_NET}.${i}.0/24" + if ! grep -q "$subnet" <<<"$used"; then + echo "$subnet" + return + fi + done + log ERROR "no free /24 subnet found in ${BASE_NET}.x.x" + exit 1 +} + +name_length_check() { + local name="$1" + if [[ ${#name} -gt 15 ]]; then + log WARN "Network name '$name' is too long for a Linux bridge (max 15 chars). It might be truncated." + return 1 + fi + return 0 +} + +provision_single() { + local name="$1" + if ! name_length_check "$name"; then + return 1 + fi + if network_exists "$name"; then + log INFO "network already exists name=$name" + return + fi + + local used + local subnet + used="$(used_subnets)" + subnet="$(next_free_subnet "$used")" + local gw="${subnet%0/24}1" + + log INFO "creating network name=$name subnet=$subnet gateway=$gw" + docker network create --driver bridge --subnet "$subnet" --gateway "$gw" \ + --opt com.docker.network.bridge.name="$name" "$name" >/dev/null + + if ! grep -Fxq "$name" "$NET_FILE"; then + echo "$name" >> "$NET_FILE" + log INFO "network name=$name added to $NET_FILE" + sed -i '/^$/d' "$NET_FILE" + fi +} + +provision_from_file() { + [[ ! -s "$NET_FILE" ]] && { log WARN "NET_FILE is empty"; return; } + log INFO "starting mass provisioning from $NET_FILE" + while read -u 3 -r line; do + [[ -z "$line" || "$line" =~ ^# ]] && continue + provision_single "$line" || true + done 3< "$NET_FILE" +} + +delete_network() { + local name="$1" + if network_exists "$name"; then + log INFO "deleting network name=$name" + docker network rm "$name" >/dev/null + log INFO "network name=$name deleted from docker" + else + log WARN "network not found in docker name=$name — cleanup config anyway" + fi + + # Remove from NET_FILE if exists + if grep -Fxq "$name" "$NET_FILE"; then + sed -i "/^$name$/d" "$NET_FILE" + log INFO "network name=$name removed from $NET_FILE" + else + log INFO "network name=$name not found in $NET_FILE, no cleanup needed" + fi +} + +delete_all_from_file() { + log INFO "deleting all networks listed in $NET_FILE" + while read -u 3 -r line; do + [[ -z "$line" || "$line" =~ ^# ]] && continue + delete_network "$line" + done 3< "$NET_FILE" +} + +show_info() { + local tracked_count + tracked_count=$(grep -cE '^\s*[^#]' "$NET_FILE" || true) + + echo "--- Docker Network Manager v1.1.0 ---" + echo "Configured Base : ${BASE_NET}.0.0/16 (Range: .${START_OCTET}.x to .${END_OCTET}.x)" + echo "Config File : $(basename "$NET_FILE")" + echo "Log File : $(basename "$LOG_FILE")" + echo "Tracked Networks: $tracked_count" + + echo -e "\n[Current Status]" + if [[ "$tracked_count" -gt 0 ]]; then + printf "%-20s %-15s %-10s\n" "NETWORK NAME" "IP RANGE" "STATUS" + echo "--------------------------------------------------------" + while read -u 3 -r line; do + [[ -z "$line" || "$line" =~ ^# ]] && continue + + local status="OFFLINE" + local subnet="N/A" + + if network_exists "$line"; then + status="ONLINE" + subnet=$(docker network inspect "$line" --format '{{(index .IPAM.Config 0).Subnet}}' 2>/dev/null || echo "error") + fi + printf "%-20s %-15s %-10s\n" "$line" "$subnet" "$status" + done 3< "$NET_FILE" + else + echo "No networks tracked in $NET_FILE" + fi + + echo -e "\n[Usage]" + echo " $0 create (c) [name] - Create single network and add to file" + echo " $0 create (c) - Create all networks from file" + echo " $0 delete (d) [name] - Remove network and clean file" + echo " $0 delete (d) - Remove all networks from file" +} + +case "${1:-info}" in + [Cc][Rr][Ee][Aa][Tt][Ee]|[Cc]) + if [[ ${2:-} ]]; then + provision_single "$2" + else + provision_from_file + fi + ;; + [Dd][Ee][Ll][Ee][Tt][Ee]|[Dd]) + if [[ ${2:-} ]]; then + delete_network "$2" + else + count=$( (grep -vE '^\s*(#|$)' "$NET_FILE" || true) | wc -l | xargs) + + if (( count == 0 )); then + log INFO "Nothing to delete. $NET_FILE is empty or contains only comments." + exit 0 + fi + + confirm_action + delete_all_from_file + fi + ;; + [Ii][Nn][Ff][Oo]|[Ii]) + show_info + ;; + *) + log ERROR "Unknown command: $1" + show_info + exit 1 + ;; +esac + +exit 0