From fba29e51714fcbaeb121334d56ea1e791e990829 Mon Sep 17 00:00:00 2001 From: mates Date: Sat, 1 Aug 2026 22:26:40 +0200 Subject: [PATCH] feat: systemd timery + skripty pro udrzbu serveru Skripty (4): - update.sh: apt update + upgrade + restart kdyz nutny + Telegram - docker-update.sh: docker compose pull + up -d pro vsechny sluzby - docker-zalohy.sh: tar.zst zaloha data/ adresaru na NAS - server-report.sh: denni Telegram report (uptime, RAM, disk, Docker) Systemd (8 - 4x service + 4x timer): - docker-update: kazdou sobotu 18:00 - docker-zalohy: kazde utery 20:00 - server-report: kazdy den 09:30 - update-rpi: kazdy patek 18:00 Konfigurace: - conf/telegram.conf.example: sablona pro Telegram credentials - vsechny skripty ctou z /home//.telegram.conf (chmod 600) Poznamka: - vsechny cesty (/home/mates) a hostname jsou pevne v service souborech - pro jineho uzivatele uprav User=, WorkingDirectory=, ExecStart= - zadne IP adresy, tokeny ani PII v gitu --- .gitignore | 27 ++++ LICENSE | 21 ++++ README.md | 223 ++++++++++++++++++++++++++++++++++ conf/telegram.conf.example | 12 ++ scripts/docker-update.sh | 122 +++++++++++++++++++ scripts/docker-zalohy.sh | 108 ++++++++++++++++ scripts/server-report.sh | 132 ++++++++++++++++++++ scripts/update.sh | 96 +++++++++++++++ systemd/docker-update.service | 13 ++ systemd/docker-update.timer | 9 ++ systemd/docker-zalohy.service | 13 ++ systemd/docker-zalohy.timer | 9 ++ systemd/server-report.service | 13 ++ systemd/server-report.timer | 9 ++ systemd/update-rpi.service | 11 ++ systemd/update-rpi.timer | 9 ++ 16 files changed, 827 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 conf/telegram.conf.example create mode 100644 scripts/docker-update.sh create mode 100644 scripts/docker-zalohy.sh create mode 100644 scripts/server-report.sh create mode 100644 scripts/update.sh create mode 100644 systemd/docker-update.service create mode 100644 systemd/docker-update.timer create mode 100644 systemd/docker-zalohy.service create mode 100644 systemd/docker-zalohy.timer create mode 100644 systemd/server-report.service create mode 100644 systemd/server-report.timer create mode 100644 systemd/update-rpi.service create mode 100644 systemd/update-rpi.timer diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96e50e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# Secrets - nikdy v gitu +.env +*.env +!.env.example +!.env.example.conf + +# Telegram credentials (citlive) +telegram.conf +*.telegram.conf + +# Zálohy a dočasné soubory +*.bak +*.tmp +*.orig +*.log +*.tar.zst +*.tar.gz +*.zip + +# Editor a IDE +.vscode/ +.idea/ +.DS_Store +*.swp + +# Build artefakty +__pycache__/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..17535d5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 mates + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..0b67b15 --- /dev/null +++ b/README.md @@ -0,0 +1,223 @@ +# mates-server-maintenance + +Systemd timery a skripty pro automatickou údržbu serveru. +**Docker update, zálohy, denní report na Telegram, systémový update.** + +> Toto repo je **1:1 kopie** systemd timerů a skriptů, které běží na produkčním serveru. + +--- + +## 📦 Co tu je + +``` +mates-server-maintenance/ +├── README.md # Tento soubor +├── LICENSE # MIT +├── .gitignore +├── scripts/ +│ ├── update.sh # Systémový update + Telegram +│ ├── docker-update.sh # Docker compose pull + up +│ ├── docker-zalohy.sh # Záloha Docker dat +│ └── server-report.sh # Denní Telegram report +├── systemd/ +│ ├── docker-update.{service,timer} +│ ├── docker-zalohy.{service,timer} +│ ├── server-report.{service,timer} +│ └── update-rpi.{service,timer} +└── conf/ + └── telegram.conf.example # Šablona pro Telegram credentials +``` + +--- + +## 🚀 Quickstart + +### 1. Naklonuj + +```bash +git clone http://:3000/mates/mates-server-maintenance.git ~/server-maintenance +``` + +### 2. Vytvoř Telegram konfiguraci + +Získej **BOT_TOKEN** z [@BotFather](https://t.me/BotFather) a **CHAT_ID** z [@userinfobot](https://t.me/userinfobot): + +```bash +mkdir -p ~/.config/telegram +cp ~/server-maintenance/conf/telegram.conf.example ~/.telegram.conf +nano ~/.telegram.conf # doplň reálné hodnoty +chmod 600 ~/.telegram.conf +``` + +### 3. Nainstaluj systemd timery + +```bash +# Pro kazdy timer: nakopiruj service+timer do /etc/systemd/system +sudo cp ~/server-maintenance/systemd/*.{service,timer} /etc/systemd/system/ + +# Aktivuj (napr. docker-update) +sudo systemctl daemon-reload +sudo systemctl enable --now docker-update.timer +sudo systemctl enable --now docker-zalohy.timer +sudo systemctl enable --now server-report.timer +sudo systemctl enable --now update-rpi.timer + +# Over stav +systemctl list-timers --all | grep -E "docker|server-report|update" +``` + +### 4. Ověř + +```bash +# Rucne spust report (melo by prijit Telegram zprava) +sudo systemctl start server-report.service +sudo journalctl -u server-report.service -f + +# Rucne spust Docker update (melo by aktualizovat kontejnery) +sudo systemctl start docker-update.service +sudo journalctl -u docker-update.service -f +``` + +--- + +## ⏰ Plán úloh (timery) + +| Timer | Kdy | Co dělá | +|---|---|---| +| `update-rpi.timer` | **Pátek 18:00** | `apt update && apt upgrade`, restart když nutný | +| `docker-update.timer` | **Sobota 18:00** | `docker compose pull && up -d` pro všechny služby | +| `docker-zalohy.timer` | **Úterý 20:00** | Záloha `data/` adresářů na NAS | +| `server-report.timer` | **Denně 09:30** | Telegram report (uptime, RAM, disk, Docker, teplota) | + +--- + +## 📋 Detail skriptů + +### `update.sh` + +Aktualizuje systém (`apt update && apt upgrade`). + +- **Spustí:** `sudo bash update.sh` nebo přes timer `update-rpi.timer` +- **Restartuje server** pokud `/var/run/reboot-required` existuje (1 minuta grace time) +- **Telegram notifikace:** start, hotovo / chyba, varování před restartem + +### `docker-update.sh` + +Aktualizuje všechny Docker Compose projekty. + +- **Seznam služeb:** edituj `AKTUALIZOVAT` pole v skriptu +- **Log:** `/home/mates/skripty/update-docker-script/docker-update.log` +- **Telegram:** start, souhrn (úspěch/chyby), seznam aktualizovaných + +### `docker-zalohy.sh` + +Zálohuje `data/` adresáře Docker projektů. + +- **Formát:** `tar.zst` (vysoká komprese) +- **Cíl:** `/home/mates/zalohy/docker//` +- **Log:** `/home/mates/zalohy/docker/docker.log` + +### `server-report.sh` + +Denní Telegram report o stavu serveru. + +- **Co reportuje:** uptime, load, RAM, disk, CPU teplota, Docker kontejnery, poslední update/záloha +- **Alert prahy:** disk 80% (warn) / 90% (crit), CPU 70°C / 80°C +- **Kdy:** denně 09:30 + +--- + +## ⚙️ Konfigurace + +### Telegram credentials + +Všechny skripty čtou z `/home//.telegram.conf`: + +```bash +BOT_TOKEN=1234567890:ABCdefGHIjklMNOpqrsTUVwxyz +CHAT_ID=123456789 +``` + +`conf/telegram.conf.example` je šablona. + +### Cesty (v systemd service souborech) + +Pokud máš **jiného uživatele nebo cesty**, uprav `WorkingDirectory` a `ExecStart` v `systemd/*.service`: + +```ini +[Service] +User=tvy-user +WorkingDirectory=/home/tvy-user/skripty/update-docker-script +ExecStart=/home/tvy-user/skripty/update-docker-script/docker-update.sh +``` + +### Seznam služeb k aktualizaci + +V `scripts/docker-update.sh`, pole `AKTUALIZOVAT`: + +```bash +AKTUALIZOVAT=( + audiobookshelf + calibre-web + vaultwarden + # pridej dalsi... +) +``` + +--- + +## 🔐 Bezpečnost + +- ✅ **`/home//.telegram.conf` s `chmod 600`** – nikdy necommitovat reálný token +- ✅ **Service běží jako `User=mates`** – ne root (omezení škod v případě chyby) +- ✅ **`set -euo pipefail`** ve všech skriptech – fail-fast +- ✅ **Logy** – vše se loguje, snadné debugování + +--- + +## 📁 Struktura na serveru + +``` +/home/mates/ +├── .telegram.conf # Telegram credentials (chmod 600) +├── update.log # Log ze systemoveho update +├── docker/ # Docker projekty +├── skripty/ +│ ├── server-report.sh # Tento skript +│ └── update-docker-script/ +│ ├── docker-update.sh # Tento skript +│ └── docker-update.log # Log z Docker update +└── zalohy/ + ├── docker.log # Log ze zaloh + └── docker/ + └── / # Zalohy (tar.zst) + └── -.tar.zst +``` + +--- + +## 🔄 Úprava schedule + +Edituj `*.timer` soubory: + +```ini +[Timer] +# Kazdou nedeli v 02:00 +OnCalendar=Sun *-*-* 02:00:00 +# Kazdych 15 minut +OnCalendar=*:0/15 +# Kazdy patek v 18:00 (puvodni) +OnCalendar=Fri *-*-* 18:00:00 +``` + +Po úpravě: `sudo systemctl daemon-reload`. + +--- + +## 📜 Licence + +MIT – viz [LICENSE](LICENSE) + +--- + +**Poslední update:** 2026-08-01 diff --git a/conf/telegram.conf.example b/conf/telegram.conf.example new file mode 100644 index 0000000..dff6f6c --- /dev/null +++ b/conf/telegram.conf.example @@ -0,0 +1,12 @@ +# Telegram bot konfigurace +# Ziskej z @BotFather na Telegramu: https://t.me/BotFather +# /newbot -> ti da BOT_TOKEN +# Napis botovi, pridej ho do skupiny, ziskej CHAT_ID pres @userinfobot +# +# Soubor umisti na: +# /home//.telegram.conf +# a nastav prava: +# chmod 600 /home//.telegram.conf + +BOT_TOKEN=1234567890:ABCdefGHIjklMNOpqrsTUVwxyz +CHAT_ID=123456789 diff --git a/scripts/docker-update.sh b/scripts/docker-update.sh new file mode 100644 index 0000000..fa29701 --- /dev/null +++ b/scripts/docker-update.sh @@ -0,0 +1,122 @@ +#!/bin/bash +# +# docker-update.sh - aktualizace Docker Compose projektu na tomto serveru +# (docker compose pull + up -d) + Telegram notifikace. +# +# Spust jednou rucne: bash docker-update.sh +# Spust automaticky: systemd timer docker-update.timer (kazdou sobotu 18:00) +# +# Konfigurace: /home/mates/.telegram.conf +# Log: /home/mates/skripty/update-docker-script/docker-update.log +# + +set -euo pipefail + +# === KONFIGURACE === +USER_NAME="mates" +WORK_DIR="/home/$USER_NAME" +ZAKLADNI_SLOZKA="$WORK_DIR/docker" +LOG="$WORK_DIR/skripty/update-docker-script/docker-update.log" +CONFIG_FILE="$WORK_DIR/.telegram.conf" +DATUM=$(date '+%Y-%m-%d %H:%M:%S') +HOST=$(hostname) + +# Seznam sluzeb k aktualizaci (uprav podle potreby) +AKTUALIZOVAT=( + audiobookshelf + calibre-web + glance + homeassistant + jswiki + plex + portainer + rustdesk + speedtest + vaultwarden + nginx +) + +# === TELEGRAM KONFIGURACE === +if [[ -f "$CONFIG_FILE" ]]; then + # shellcheck disable=SC1090 + source "$CONFIG_FILE" +fi +TELEGRAM_BOT_TOKEN="${TELEGRAM_BOT_TOKEN:-}" +TELEGRAM_CHAT_ID="${TELEGRAM_CHAT_ID:-}" + +# === TELEGRAM HELPER === +send_msg() { + local TEXT="$1" + + if [[ -z "$TELEGRAM_BOT_TOKEN" || -z "$TELEGRAM_CHAT_ID" ]]; then + echo "$DATUM ⚠️ Telegram neni nakonfigurovan, preskakuji" >> "$LOG" + return 0 + fi + + curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ + -d chat_id="${TELEGRAM_CHAT_ID}" \ + -d text="$TEXT" \ + -d parse_mode="Markdown" \ + --max-time 10 \ + --retry 3 > /dev/null || echo "$DATUM ⚠️ Telegram chyba" >> "$LOG" +} + +# === HLAVNI LOGIKA === +echo "$DATUM === docker-update.sh spusten ===" >> "$LOG" +send_msg "🔄 *[$HOST]* Spoustim aktualizaci Docker kontejneru..." + +# Vytvor log adresar pokud neexistuje +mkdir -p "$(dirname "$LOG")" + +AKTUALIZOVANO=() +CHYBY=() + +for SLUZBA in "${AKTUALIZOVAT[@]}"; do + SLUZBA_PATH="$ZAKLADNI_SLOZKA/$SLUZBA" + + if [[ ! -d "$SLUZBA_PATH" ]]; then + echo "$DATUM SKIP: $SLUZBA (slozka neexistuje)" >> "$LOG" + continue + fi + + if [[ ! -f "$SLUZBA_PATH/docker-compose.yml" ]]; then + echo "$DATUM SKIP: $SLUZBA (docker-compose.yml chybi)" >> "$LOG" + continue + fi + + echo "$DATUM === Aktualizuji: $SLUZBA ===" >> "$LOG" + + cd "$SLUZBA_PATH" + + # Stahnout nove image + if docker compose pull 2>>"$LOG"; then + # Restart s novym image + if docker compose up -d 2>>"$LOG"; then + AKTUALIZOVANO+=("$SLUZBA") + echo "$DATUM OK: $SLUZBA aktualizovan" >> "$LOG" + else + CHYBY+=("$SLUZBA (up)") + echo "$DATUM CHYBA: $SLUZBA - up -d selhalo" >> "$LOG" + fi + else + CHYBY+=("$SLUZBA (pull)") + echo "$DATUM CHYBA: $SLUZBA - pull selhalo" >> "$LOG" + fi +done + +# === SOUHRN === +POCET_OK=${#AKTUALIZOVANO[@]} +POCET_CHYB=${#CHYBY[@]} + +if [[ $POCET_CHYB -eq 0 ]]; then + send_msg "✅ *[$HOST]* Docker aktualizace dokoncena. +Aktualizovano: $POCET_OK sluzeb +Seznam: ${AKTUALIZOVANO[*]}" +else + send_msg "⚠️ *[$HOST]* Docker aktualizace dokoncena s chybami. +Aktualizovano: $POCET_OK +Chyby: ${CHYBY[*]}" +fi + +echo "$DATUM === docker-update.sh dokoncen ===" >> "$LOG" +exit 0 diff --git a/scripts/docker-zalohy.sh b/scripts/docker-zalohy.sh new file mode 100644 index 0000000..ed8059f --- /dev/null +++ b/scripts/docker-zalohy.sh @@ -0,0 +1,108 @@ +#!/bin/bash +# +# docker-zalohy.sh - zaloha Docker Compose projektu a jejich dat (./data adresaru) +# na NAS (nebo jiny backup disk) + Telegram notifikace. +# +# Spust jednou rucne: bash docker-zalohy.sh +# Spust automaticky: systemd timer docker-zalohy.timer (kazde utery 20:00) +# +# Konfigurace: /home/mates/.telegram.conf +# Log: /home/mates/zalohy/docker/docker.log +# + +set -euo pipefail + +# === KONFIGURACE === +USER_NAME="mates" +WORK_DIR="/home/$USER_NAME" +SOURCE_DIR="$WORK_DIR/docker" +BACKUP_DIR="$WORK_DIR/zalohy/docker" +LOG_FILE="$BACKUP_DIR/docker.log" +CONFIG_FILE="$WORK_DIR/.telegram.conf" + +# Seznam sluzeb k zalohovani (uprav podle potreby) +APP_DIRS=( + audiobookshelf + calibre-web + flatnotes + homeassistant + jswiki + miniflux + nginx + plex + speedtest + vaultwarden + wiki + glance +) + +DATE_DIR=$(date +"%Y%m%d") +TIMESTAMP=$(date +"%H%M%S") +HOST=$(hostname) + +# === TELEGRAM KONFIGURACE === +if [[ -f "$CONFIG_FILE" ]]; then + # shellcheck disable=SC1090 + source "$CONFIG_FILE" +fi +TELEGRAM_BOT_TOKEN="${TELEGRAM_BOT_TOKEN:-}" +TELEGRAM_CHAT_ID="${TELEGRAM_CHAT_ID:-}" + +# === TELEGRAM HELPER === +send_msg() { + local TEXT="$1" + + if [[ -z "$TELEGRAM_BOT_TOKEN" || -z "$TELEGRAM_CHAT_ID" ]]; then + echo "[$(date '+%Y-%m-%d %H:%M:%S')] Telegram neni nakonfigurovan, preskakuji" >> "$LOG_FILE" + return 0 + fi + + curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ + -d chat_id="${TELEGRAM_CHAT_ID}" \ + -d text="$TEXT" \ + -d parse_mode="Markdown" \ + --max-time 10 \ + --retry 3 > /dev/null || echo "[$(date '+%Y-%m-%d %H:%M:%S')] ⚠️ Telegram chyba" >> "$LOG_FILE" +} + +# === HLAVNI LOGIKA === +mkdir -p "$BACKUP_DIR/$DATE_DIR" + +START_TIME=$(date +%s) +ZALOHOVANO=() +CHYBY=() + +for APP in "${APP_DIRS[@]}"; do + APP_PATH="$SOURCE_DIR/$APP" + if [[ ! -d "$APP_PATH" ]]; then + continue + fi + + cd "$APP_PATH" + + # Pokud existuje data/ adresar, zalohuj ho + if [[ -d "./data" ]]; then + BACKUP_FILE="$BACKUP_DIR/$DATE_DIR/${APP}-${TIMESTAMP}.tar.zst" + + if tar --zstd -cf "$BACKUP_FILE" -C "$APP_PATH" data 2>>"$LOG_FILE"; then + ZALOHOVANO+=("$APP ($(du -h "$BACKUP_FILE" | cut -f1))") + else + CHYBY+=("$APP") + fi + fi +done + +END_TIME=$(date +%s) +DURATION=$((END_TIME - START_TIME)) + +if [[ ${#CHYBY[@]} -eq 0 ]]; then + send_msg "✅ *[$HOST]* Docker zalohy dokonceny (${DURATION}s). +Zalohovano: ${#ZALOHOVANO[@]} sluzeb +Adresar: \`$BACKUP_DIR/$DATE_DIR\`" +else + send_msg "⚠️ *[$HOST]* Docker zalohy dokonceny s chybami. +Zalohovano: ${#ZALOHOVANO[@]} +Chyby: ${CHYBY[*]}" +fi + +exit 0 diff --git a/scripts/server-report.sh b/scripts/server-report.sh new file mode 100644 index 0000000..67644ff --- /dev/null +++ b/scripts/server-report.sh @@ -0,0 +1,132 @@ +#!/bin/bash +# +# server-report.sh - denni report stavu serveru na Telegram. +# Obsahuje: uptime, load, RAM, disk, teplota CPU, Docker kontejnery, +# Docker update log, zalohy, sitovy traffic. +# +# Spust jednou rucne: bash server-report.sh +# Spust automaticky: systemd timer server-report.timer (kazdy den 09:30) +# +# Konfigurace: /home/mates/.telegram.conf +# + +set -euo pipefail + +# === KONFIGURACE === +USER_NAME="mates" +WORK_DIR="/home/$USER_NAME" +CONFIG_FILE="$WORK_DIR/.telegram.conf" +DOCKER_ROOT="$WORK_DIR/docker" +DOCKER_UPDATE_LOG="$WORK_DIR/skripty/update-docker-script/docker-update.log" +DOCKER_BACKUP_DIR="$WORK_DIR/zalohy/docker" +HOST=$(hostname) +INTERFACE="eth0" # nastav podle sveho serveru + +# Prahy pro upozorneni +DISK_WARN=80 +DISK_CRIT=90 +TEMP_WARN=70 +TEMP_CRIT=80 + +# === TELEGRAM KONFIGURACE === +if [[ -f "$CONFIG_FILE" ]]; then + # shellcheck disable=SC1090 + source "$CONFIG_FILE" +fi +TELEGRAM_BOT_TOKEN="${TELEGRAM_BOT_TOKEN:-}" +TELEGRAM_CHAT_ID="${TELEGRAM_CHAT_ID:-}" + +send_msg() { + local TEXT="$1" + + if [[ -z "$TELEGRAM_BOT_TOKEN" || -z "$TELEGRAM_CHAT_ID" ]]; then + echo "Telegram neni nakonfigurovan, preskakuji" + return 0 + fi + + curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ + -d chat_id="${TELEGRAM_CHAT_ID}" \ + -d text="$TEXT" \ + -d parse_mode="Markdown" \ + --max-time 10 \ + --retry 3 > /dev/null || echo "⚠️ Telegram chyba" +} + +# === SYSTEMOVE STATISTIKY === +UPTIME=$(uptime -p | sed 's/^up //') +LOAD=$(awk '{print $1" "$2" "$3}' /proc/loadavg) +RAM_USED=$(free -h | awk '/^Mem:/ {print $3}') +RAM_TOTAL=$(free -h | awk '/^Mem:/ {print $2}') +DISK_USED_HUMAN=$(df -h / | awk 'NR==2 {print $3}') +DISK_TOTAL_HUMAN=$(df -h / | awk 'NR==2 {print $2}') +DISK_PERCENT_RAW=$(df -P / | awk 'NR==2 {print $5}' | tr -d '%') + +# CPU teplota (pokud je k dispozici) +TEMP_RAW="" +if [[ -f /sys/class/thermal/thermal_zone0/temp ]]; then + TEMP_RAW=$(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null || echo "") +fi +TEMP_HUMAN="" +if [[ -n "$TEMP_RAW" && "$TEMP_RAW" -gt 0 ]]; then + TEMP_C=$((TEMP_RAW / 1000)) + TEMP_HUMAN="🌡️ CPU: ${TEMP_C}°C\n" +fi + +# Docker kontejnery +CONTAINERS_RUNNING=$(docker ps -q 2>/dev/null | wc -l | tr -d ' ') +CONTAINERS_TOTAL=$(docker ps -aq 2>/dev/null | wc -l | tr -d ' ') +CONTAINERS_STOPPED=$((CONTAINERS_TOTAL - CONTAINERS_RUNNING)) + +# Sitovy traffic (pokud je dostupny) +NETWORK_RX=$(cat /sys/class/net/$INTERFACE/statistics/rx_bytes 2>/dev/null || echo "0") +NETWORK_TX=$(cat /sys/class/net/$INTERFACE/statistics/tx_bytes 2>/dev/null || echo "0") +NETWORK_RX_HUMAN=$(awk "BEGIN {printf \"%.2f GB\", $NETWORK_RX/1073741824}") +NETWORK_TX_HUMAN=$(awk "BEGIN {printf \"%.2f GB\", $NETWORK_TX/1073741824}") + +# Posledni Docker update a zaloha +LAST_UPDATE="zatim neprobehla" +if [[ -f "$DOCKER_UPDATE_LOG" ]]; then + LAST_UPDATE=$(grep -E "=== (docker-update|update.sh) (spusten|dokoncen)" "$DOCKER_UPDATE_LOG" | tail -1 | awk '{print $1, $2}') +fi + +LAST_BACKUP="zatim neprobehla" +if [[ -d "$DOCKER_BACKUP_DIR" ]]; then + LAST_BACKUP=$(ls -t "$DOCKER_BACKUP_DIR"/*/ 2>/dev/null | head -1 | xargs -I {} basename {} 2>/dev/null || echo "neni") +fi + +# === SESTAVENI REPORTU === +ALERTS="" +if [[ $DISK_PERCENT_RAW -ge $DISK_CRIT ]]; then + ALERTS="${ALERTS}🚨 *DISK KRITICKY: ${DISK_PERCENT_RAW}%*\n" +elif [[ $DISK_PERCENT_RAW -ge $DISK_WARN ]]; then + ALERTS="${ALERTS}⚠️ *DISK: ${DISK_PERCENT_RAW}%*\n" +fi + +if [[ -n "$TEMP_RAW" && "$TEMP_RAW" -gt 0 ]]; then + TEMP_C=$((TEMP_RAW / 1000)) + if [[ $TEMP_C -ge $TEMP_CRIT ]]; then + ALERTS="${ALERTS}🚨 *CPU KRITICKY: ${TEMP_C}°C*\n" + elif [[ $TEMP_C -ge $TEMP_WARN ]]; then + ALERTS="${ALERTS}⚠️ *CPU: ${TEMP_C}°C*\n" + fi +fi + +# === ODESLANI === +REPORT="${ALERTS}📊 *[$HOST]* Denni report + +⏱️ Uptime: \`$UPTIME\` +📈 Load: \`$LOAD\` +🧠 RAM: $RAM_USED / $RAM_TOTAL +💾 Disk: $DISK_USED_HUMAN / $DISK_TOTAL_HUMAN (${DISK_PERCENT_RAW}%) +${TEMP_HUMAN}🌐 Sit ($INTERFACE): + RX: $NETWORK_RX_HUMAN | TX: $NETWORK_TX_HUMAN + +🐳 Docker: + Bezi: $CONTAINERS_RUNNING | Celkem: $CONTAINERS_TOTAL + Stopped: $CONTAINERS_STOPPED + +📅 Posledni Docker update: \`$LAST_UPDATE\` +💾 Posledni zaloha: \`$LAST_BACKUP\`" + +send_msg "$REPORT" +exit 0 diff --git a/scripts/update.sh b/scripts/update.sh new file mode 100644 index 0000000..23ce290 --- /dev/null +++ b/scripts/update.sh @@ -0,0 +1,96 @@ +#!/bin/bash +# +# update.sh - aktualizace systemu (apt update + upgrade) + restart pokud nutny +# + Telegram notifikace o vysledku. +# +# Spust jednou rucne: sudo bash update.sh +# Spust automaticky: systemd timer update-rpi.timer (kazdy patek 18:00) +# +# Konfigurace: /home/mates/.telegram.conf (nebo nastav TELEGRAM_BOT_TOKEN a TELEGRAM_CHAT_ID v env) +# + +set -euo pipefail + +# === KONFIGURACE === +CONFIG_FILE="/home/mates/.telegram.conf" +USER_NAME="mates" +WORK_DIR="/home/$USER_NAME" +LOG_FILE="$WORK_DIR/update.log" +HOST=$(hostname) +RESTART_REQUIRED="/var/run/reboot-required" + +# === TELEGRAM KONFIGURACE === +if [[ -f "$CONFIG_FILE" ]]; then + # shellcheck disable=SC1090 + source "$CONFIG_FILE" +fi +TELEGRAM_BOT_TOKEN="${TELEGRAM_BOT_TOKEN:-}" +TELEGRAM_CHAT_ID="${TELEGRAM_CHAT_ID:-}" + +# === TELEGRAM HELPER === +send_msg() { + local TEXT="$1" + + if [[ -z "$TELEGRAM_BOT_TOKEN" || -z "$TELEGRAM_CHAT_ID" ]]; then + echo "[$(date '+%Y-%m-%d %H:%M:%S')] Telegram neni nakonfigurovan, preskakuji notifikaci" >> "$LOG_FILE" + return 0 + fi + + curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ + -d chat_id="${TELEGRAM_CHAT_ID}" \ + -d text="$TEXT" \ + -d parse_mode="Markdown" \ + --max-time 10 \ + --retry 3 > /dev/null || echo "[$(date '+%Y-%m-%d %H:%M:%S')] ⚠️ Telegram chyba" >> "$LOG_FILE" +} + +# === PROMENNE === +START_TIME=$(date +%s) + +# === CHYBA HANDLER === +on_error() { + local exit_code=$? + local end_time=$(date +%s) + local duration=$((end_time - START_TIME)) + echo "[$(date '+%Y-%m-%d %H:%M:%S')] CHYBA: update.sh skončil s chybou (exit code $exit_code)" >> "$LOG_FILE" + send_msg "❌ *[$HOST]* Aktualizace systému selhala (${duration}s). +Zkontroluj log: +\`$LOG_FILE\`" + exit "$exit_code" +} +trap on_error ERR + +# === HLAVNI LOGIKA === +echo "[$(date '+%Y-%m-%d %H:%M:%S')] === update.sh spusten ===" >> "$LOG_FILE" + +# Notifikace o zacatku +send_msg "🔄 *[$HOST]* Spoustim aktualizaci systemu..." + +# Aktualizace baliku +echo "[$(date '+%Y-%m-%d %H:%M:%S')] apt update..." >> "$LOG_FILE" +sudo apt-get update -qq 2>>"$LOG_FILE" + +echo "[$(date '+%Y-%m-%d %H:%M:%S')] apt upgrade..." >> "$LOG_FILE" +sudo apt-get upgrade -y -qq 2>>"$LOG_FILE" + +echo "[$(date '+%Y-%m-%d %H:%M:%S')] apt autoremove..." >> "$LOG_FILE" +sudo apt-get autoremove -y -qq 2>>"$LOG_FILE" + +END_TIME=$(date +%s) +DURATION=$((END_TIME - START_TIME)) + +# Restart? +if [[ -f "$RESTART_REQUIRED" ]]; then + echo "[$(date '+%Y-%m-%d %H:%M:%S')] Restart required" >> "$LOG_FILE" + send_msg "⚠️ *[$HOST]* Aktualizace systemu dokoncena (${DURATION}s). +**Restart serveru je nutny!** Reboot bude proveden za 1 minutu." + + # Naplanovany restart za 1 minutu (at muzes kanclovat) + sudo shutdown -r +1 "Systemovy restart po update" +else + send_msg "✅ *[$HOST]* Aktualizace systemu dokoncena (${DURATION}s). +Restart nutny neni." +fi + +echo "[$(date '+%Y-%m-%d %H:%M:%S')] === update.sh dokoncen (${DURATION}s) ===" >> "$LOG_FILE" +exit 0 diff --git a/systemd/docker-update.service b/systemd/docker-update.service new file mode 100644 index 0000000..bb40911 --- /dev/null +++ b/systemd/docker-update.service @@ -0,0 +1,13 @@ +[Unit] +Description=Aktualizace Docker kontejneru +After=network-online.target docker.service +Wants=network-online.target + +[Service] +Type=oneshot +User=mates +WorkingDirectory=/home/mates/skripty/update-docker-script +ExecStart=/home/mates/skripty/update-docker-script/docker-update.sh + +[Install] +WantedBy=multi-user.target diff --git a/systemd/docker-update.timer b/systemd/docker-update.timer new file mode 100644 index 0000000..1665e6d --- /dev/null +++ b/systemd/docker-update.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Spoustet Docker update kazdou sobotu v 18:00 + +[Timer] +OnCalendar=Sat 18:00 +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/systemd/docker-zalohy.service b/systemd/docker-zalohy.service new file mode 100644 index 0000000..b42fe8c --- /dev/null +++ b/systemd/docker-zalohy.service @@ -0,0 +1,13 @@ +[Unit] +Description=Zaloha Docker aplikaci +After=network-online.target docker.service +Wants=network-online.target + +[Service] +Type=oneshot +User=mates +WorkingDirectory=/home/mates/zalohy +ExecStart=/home/mates/zalohy/docker_zalohy.sh + +[Install] +WantedBy=multi-user.target diff --git a/systemd/docker-zalohy.timer b/systemd/docker-zalohy.timer new file mode 100644 index 0000000..c630328 --- /dev/null +++ b/systemd/docker-zalohy.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Spoustet Docker zalohy kazde utery ve 20:00 + +[Timer] +OnCalendar=Tue 20:00 +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/systemd/server-report.service b/systemd/server-report.service new file mode 100644 index 0000000..a8c0c9f --- /dev/null +++ b/systemd/server-report.service @@ -0,0 +1,13 @@ +[Unit] +Description=Denní report serveru na Telegram +After=network-online.target docker.service +Wants=network-online.target + +[Service] +Type=oneshot +User=mates +WorkingDirectory=/home/mates/skripty +ExecStart=/home/mates/skripty/server-report.sh + +[Install] +WantedBy=multi-user.target diff --git a/systemd/server-report.timer b/systemd/server-report.timer new file mode 100644 index 0000000..df00d33 --- /dev/null +++ b/systemd/server-report.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Spoustet server report kazdy den v 09:30 + +[Timer] +OnCalendar=*-*-* 09:30:00 +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/systemd/update-rpi.service b/systemd/update-rpi.service new file mode 100644 index 0000000..a149117 --- /dev/null +++ b/systemd/update-rpi.service @@ -0,0 +1,11 @@ +[Unit] +Description=Aktualizace systému + Telegram notifikace + +[Service] +Type=oneshot +User=mates +WorkingDirectory=/home/mates +ExecStart=/home/mates/update.sh + +[Install] +WantedBy=multi-user.target diff --git a/systemd/update-rpi.timer b/systemd/update-rpi.timer new file mode 100644 index 0000000..578f1d4 --- /dev/null +++ b/systemd/update-rpi.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Aktualizace každý pátek v 18:00 + +[Timer] +OnCalendar=Fri *-*-* 18:00:00 +Persistent=true + +[Install] +WantedBy=timers.target