diff options
| -rw-r--r-- | create.sh | 34 | ||||
| -rwxr-xr-x | fortress.sh | 31 | ||||
| -rwxr-xr-x | lxd_auto_snap.sh | 21 | ||||
| -rwxr-xr-x | lxdbackup.sh | 43 | ||||
| -rwxr-xr-x | move_containers.sh | 44 | ||||
| -rwxr-xr-x | rebootcheck.sh | 26 | ||||
| -rwxr-xr-x | recid.sh | 3 | ||||
| -rwxr-xr-x | reorder_override.sh | 30 | ||||
| -rwxr-xr-x | reorder_validation.sh | 45 | ||||
| -rwxr-xr-x | reorderips.sh | 53 | ||||
| -rwxr-xr-x | squeakyclean.sh | 36 | ||||
| -rwxr-xr-x | sync_tt_to_alt.sh | 14 | ||||
| -rwxr-xr-x | sync_tt_to_minio.sh | 37 | ||||
| -rwxr-xr-x | testdm.sh | 11 | ||||
| -rwxr-xr-x | ttbanwatch.sh | 79 | ||||
| -rwxr-xr-x | watchman.sh | 40 |
16 files changed, 547 insertions, 0 deletions
diff --git a/create.sh b/create.sh new file mode 100644 index 0000000..eac4147 --- /dev/null +++ b/create.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +echo "π LXD New Container Setup Script" + +read -p "π Enter the new container name: " name +read -p "π Enter static IP to assign (e.g. 10.196.1.70): " ip + +echo "π§ Launching new Ubuntu 22.04 container: $name" +lxc launch ubuntu:22.04 "$name" + +echo "π§ Overriding eth0 device to allow static IP assignment..." +lxc config device override "$name" eth0 + +echo "π§ Assigning static IP: $ip" +lxc config device set "$name" eth0 ipv4.address "$ip" + +echo "π Restarting $name to apply new IP..." +lxc restart "$name" + +echo "π οΈ Validating IP and hostname inside the container..." +actual_ip=$(lxc exec "$name" -- hostname -I | awk '{print $1}') +hostname_inside=$(lxc exec "$name" -- hostname) + +echo "β
Container '$name' has been assigned IP: $actual_ip" +echo "π Container DNS hostname: $hostname_inside" + +ping -c 2 "$ip" > /dev/null 2>&1 +if [[ $? -eq 0 ]]; then + echo "β
Ping to $ip successful!" +else + echo "β Ping to $ip failed!" +fi + +echo "π Container setup complete!" diff --git a/fortress.sh b/fortress.sh new file mode 100755 index 0000000..4df0921 --- /dev/null +++ b/fortress.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# fortress_setup_ubuntu.sh - secure SSH fortress on Ubuntu with UFW + +set -e + +bouncer_ip="38.102.127.173" + +echo "Updating package lists..." +sudo apt update + +echo "Installing UFW if not present..." +sudo apt install -y ufw + +echo "Setting default UFW policies..." +sudo ufw default deny incoming +sudo ufw default allow outgoing + +echo "Allowing SSH only from bouncer ($bouncer_ip)..." +sudo ufw allow from $bouncer_ip to any port 22 proto tcp comment 'Allow SSH from bouncer' + +echo "Allowing inbound HTTP/HTTPS..." +sudo ufw allow 80/tcp comment 'Allow HTTP' +sudo ufw allow 443/tcp comment 'Allow HTTPS' + +echo "Enabling UFW..." +sudo ufw --force enable + +echo "UFW Status:" +sudo ufw status verbose + +echo "SSH fortress is active! Only $bouncer_ip can connect via SSH." diff --git a/lxd_auto_snap.sh b/lxd_auto_snap.sh new file mode 100755 index 0000000..fa87eaa --- /dev/null +++ b/lxd_auto_snap.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +echo "π Starting automatic LXD snapshot for all running containers..." + +# Get a list of running container names +containers=$(lxc list --format csv -c ns | awk -F, '$2 == "RUNNING" {print $1}') + +if [[ -z "$containers" ]]; then + echo "β No running containers found!" + exit 1 +fi + +# Create a snapshot for each container +timestamp=$(date +%Y%m%d-%H%M%S) +for container in $containers; do + snapshot_name="auto-${timestamp}" + echo "π‘ Creating snapshot for $container: $snapshot_name" + lxc snapshot "$container" "$snapshot_name" +done + +echo "β
Snapshot creation complete!" diff --git a/lxdbackup.sh b/lxdbackup.sh new file mode 100755 index 0000000..8865219 --- /dev/null +++ b/lxdbackup.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# backup-lxd.sh - Full LXD backup with offsite rsync + +NOW=$(date +'%F') +BACKUP_DIR="/backups/lxd" +REMOTE_USER="doc" +REMOTE_HOST="thevault.bounceme.net" +REMOTE_PATH="/gigapool/lxdbackups/${NOW}" # Subdir per date + +echo "π¦ Starting LXD backup @ $NOW" +mkdir -p "$BACKUP_DIR" + +# Backup LXD server config +echo "π οΈ Dumping LXD init config..." +lxd init --dump > "${BACKUP_DIR}/lxd.config.${NOW}" + +# Save instance list and version info +echo "π Capturing metadata..." +lxc list > "${BACKUP_DIR}/lxd.instances.list.${NOW}" +snap list lxd > "${BACKUP_DIR}/lxd-version.${NOW}" + +# Export all LXD containers +echo "π¦ Backing up LXD instances..." +for INSTANCE in $(lxc list -c n --format csv); do + echo "β‘οΈ Exporting $INSTANCE..." + lxc export "$INSTANCE" "${BACKUP_DIR}/${INSTANCE}-backup-${NOW}.tar.xz" --optimized-storage \ + && echo "β
Done: $INSTANCE" \ + || echo "β Failed: $INSTANCE" +done + +# Offsite rsync to thevault +echo "π Syncing to ${REMOTE_HOST}:${REMOTE_PATH} ..." +rsync -avh --progress --delete \ + "$BACKUP_DIR/" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/" + +if [[ $? -eq 0 ]]; then + echo "β
Offsite sync completed successfully." +else + echo "β Rsync failed! Check connection or credentials." + exit 1 +fi + +echo "π LXD backup + offsite sync complete." diff --git a/move_containers.sh b/move_containers.sh new file mode 100755 index 0000000..7062177 --- /dev/null +++ b/move_containers.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# === Config === +CONTAINERS=( + archivecontrol + archivelist + ftp + hostingtoot + humptydumpty + teamtalk + akkoma +) + +TARGET_POOL="infernode-pool" + +# === Move loop === +for container in "${CONTAINERS[@]}"; do + echo "=== Processing container: $container ===" + + echo "Stopping $container..." + lxc stop "$container" --timeout=30 + + echo "Waiting for $container to fully shut down..." + while true; do + status=$(lxc info "$container" | grep "Status:" | awk '{print $2}') + if [[ "$status" != "RUNNING" ]]; then + echo "$container is fully stopped." + break + fi + echo "$container still stopping... waiting 3 more seconds." + sleep 3 + done + + echo "Moving $container to pool: $TARGET_POOL" + lxc move "$container" "$container" --storage "$TARGET_POOL" + + echo "Starting $container..." + lxc start "$container" + + echo "=== $container moved and restarted! ===" + echo +done + +echo "=== All containers have been successfully moved and restarted! ===" diff --git a/rebootcheck.sh b/rebootcheck.sh new file mode 100755 index 0000000..62074f5 --- /dev/null +++ b/rebootcheck.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# genesisctl-reboot-check - Lightweight reboot health checker + +LAST_BOOT=$(uptime -s 2>/dev/null) +LAST_BOOT_TS=$(date -d "$LAST_BOOT" +%s) +NOW_TS=$(date +%s) +DAYS_SINCE_BOOT=$(( (NOW_TS - LAST_BOOT_TS) / 86400 )) + +REBOOT_REQUIRED_FILE="/var/run/reboot-required" + +echo "π§ Genesis Reboot Check" +echo "-----------------------" +echo "π Last Boot: $LAST_BOOT" +echo "π Days Since Boot: $DAYS_SINCE_BOOT" + +if [ "$DAYS_SINCE_BOOT" -gt 30 ]; then + echo "β οΈ Overdue: It's been more than 30 days since your last reboot." +else + echo "β
Reboot not overdue (monthly policy)" +fi + +if [ -f "$REBOOT_REQUIRED_FILE" ]; then + echo "β οΈ System indicates a reboot is required (/var/run/reboot-required exists)" +else + echo "β
No reboot required by the system" +fi diff --git a/recid.sh b/recid.sh new file mode 100755 index 0000000..6a7ff6c --- /dev/null +++ b/recid.sh @@ -0,0 +1,3 @@ +curl -X GET "https://api.cloudflare.com/client/v4/zones/c5099d42caa2d9763227267c597cb758/dns_records" \ + -H "Authorization: Bearer lCz1kH6nBZPJL0EWrNI-xEDwfR0oOLpg05fq6M81" \ + -H "Content-Type: application/json" | jq diff --git a/reorder_override.sh b/reorder_override.sh new file mode 100755 index 0000000..35edb2f --- /dev/null +++ b/reorder_override.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +echo "Reassigning container IPs in increments of 10..." + +declare -A CONTAINERS +CONTAINERS=( + [archivecontrol]="10.196.1.10" + [archivelist]="10.196.1.20" + [ftp]="10.196.1.30" + [hostingtoot]="10.196.1.40" + [humptydumpty]="10.196.1.50" + [teamtalk]="10.196.1.60" +) + +for container in "${!CONTAINERS[@]}"; do + new_ip="${CONTAINERS[$container]}" + echo "β‘οΈ Overriding eth0 device for $container..." + lxc config device override "$container" eth0 + echo "π§ Setting $container to IP $new_ip..." + lxc config device set "$container" eth0 ipv4.address "$new_ip" +done + +echo "π Restarting containers to apply new IPs..." +for container in "${!CONTAINERS[@]}"; do + echo "π Restarting $container..." + lxc restart "$container" +done + +echo "β
IP assignment complete! Hereβs the new layout:" +lxc list diff --git a/reorder_validation.sh b/reorder_validation.sh new file mode 100755 index 0000000..29de3f3 --- /dev/null +++ b/reorder_validation.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +echo "π Starting IP validation and connectivity tests..." + +declare -A CONTAINERS +CONTAINERS=( + [archivecontrol]="10.196.1.10" + [archivelist]="10.196.1.20" + [ftp]="10.196.1.30" + [hostingtoot]="10.196.1.40" + [humptydumpty]="10.196.1.50" + [teamtalk]="10.196.1.60" + [akkoma]="10.196.1.70" +) + +for container in "${!CONTAINERS[@]}"; do + expected_ip="${CONTAINERS[$container]}" + echo "π Checking $container..." + + # Get actual IP from inside container + actual_ip=$(lxc exec "$container" -- hostname -I | awk '{print $1}') + + # Compare expected vs actual IP + if [[ "$expected_ip" == "$actual_ip" ]]; then + echo "β
$container IP matches expected: $expected_ip" + else + echo "β $container IP mismatch! Expected: $expected_ip, Found: $actual_ip" + fi + + # Ping test from host + echo "π‘ Pinging $expected_ip..." + ping -c 2 "$expected_ip" > /dev/null 2>&1 + if [[ $? -eq 0 ]]; then + echo "β
Ping to $expected_ip successful" + else + echo "β Ping to $expected_ip failed" + fi + + # DNS hostname inside container + container_hostname=$(lxc exec "$container" -- hostname) + echo "π $container DNS hostname: $container_hostname" + echo "-------------------------------------------" +done + +echo "π Validation and connectivity tests complete!" diff --git a/reorderips.sh b/reorderips.sh new file mode 100755 index 0000000..6567d95 --- /dev/null +++ b/reorderips.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +echo "Reassigning container IPs in increments of 10..." + +# Container name to IP mapping +declare -A CONTAINERS=( + [archivecontrol]="10.196.1.10" + [archivelist]="10.196.1.20" + [ftp]="10.196.1.30" + [hostingtoot]="10.196.1.40" + [humptydumpty]="10.196.1.50" + [teamtalk]="10.196.1.60" + [akkoma]="10.196.1.70" +) + +# Ordered list to process in sequence +ORDER=(archivecontrol archivelist ftp hostingtoot humptydumpty teamtalk akkoma) + +for container in "${ORDER[@]}"; do + new_ip="${CONTAINERS[$container]}" + + # Check current IP assignment + current_ip=$(lxc config device get "$container" eth0 ipv4.address 2>/dev/null) + + if [[ "$current_ip" == "$new_ip" ]]; then + # No change needed + continue + fi + + echo "Updating $container: assigning IP $new_ip (was: ${current_ip:-unset})" + + # Override NIC to allow per-container IP (silently if already done) + lxc config device override "$container" eth0 >/dev/null 2>&1 + + # Clear any existing IP config + lxc config device unset "$container" eth0 ipv4.address >/dev/null 2>&1 + + # Set the new IP + lxc config device set "$container" eth0 ipv4.address "$new_ip" +done + +echo "Restarting updated containers..." +for container in "${ORDER[@]}"; do + new_ip="${CONTAINERS[$container]}" + current_ip=$(lxc config device get "$container" eth0 ipv4.address 2>/dev/null) + if [[ "$current_ip" == "$new_ip" ]]; then + echo "Restarting $container (new IP: $new_ip)" + lxc restart "$container" >/dev/null + fi +done + +echo "IP assignment complete! Hereβs the final layout:" +lxc list diff --git a/squeakyclean.sh b/squeakyclean.sh new file mode 100755 index 0000000..bb1e754 --- /dev/null +++ b/squeakyclean.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +echo "=== LXD Storage Pool Check and Cleanup Helper ===" + +# List all containers with their active storage pool +echo +echo "Container -> Storage Pool:" +for container in $(lxc list --format csv -c n); do + pool=$(lxc config device get "$container" root pool 2>/dev/null) + echo "$container -> ${pool:-default}" +done + +echo +echo "=== Checking for leftover partial volumes in /mnt/infernode_lxd (NFS) ===" +if mountpoint -q /mnt/infernode_lxd; then + leftovers=$(find /mnt/infernode_lxd -mindepth 1 -maxdepth 1) + if [[ -z "$leftovers" ]]; then + echo "No leftover volumes found. Clean as a whistle!" + else + echo "Found leftover items:" + echo "$leftovers" + echo + read -p "Do you want to remove these? (y/n) " confirm + if [[ "$confirm" == "y" ]]; then + sudo rm -rf /mnt/infernode_lxd/* + echo "Leftovers removed!" + else + echo "Leaving leftovers untouched for now." + fi + fi +else + echo "NFS mount not found at /mnt/infernode_lxd. Skipping leftover check." +fi + +echo +echo "=== Done! ===" diff --git a/sync_tt_to_alt.sh b/sync_tt_to_alt.sh new file mode 100755 index 0000000..1d94d4a --- /dev/null +++ b/sync_tt_to_alt.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# === Sync /home/tt from Montreal to Linode === + +# Vars +SOURCE="/home/tt/" +DESTINATION="root@172.238.63.162:/home/tt/" +LOG_FILE="/var/log/tt_sync.log" +DATE=$(date '+%Y-%m-%d %H:%M:%S') + +# Rsync command - preserves perms, ownership, etc. +rsync -az --delete "$SOURCE" "$DESTINATION" >> "$LOG_FILE" 2>&1 + +# Logging +echo "[$DATE] Sync completed" >> "$LOG_FILE" diff --git a/sync_tt_to_minio.sh b/sync_tt_to_minio.sh new file mode 100755 index 0000000..75512ce --- /dev/null +++ b/sync_tt_to_minio.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# === CONFIG === +MINIO_HOST="shredder.sshjunkie.com" # Use IP if DNS doesn't resolve +MINIO_PORT="9000" +ACCESS_KEY="genesisadmin" +SECRET_KEY="MutationXv3!" +BUCKET="teamtalkdata" +SOURCE_DIR="/home/tt" +LOG_FILE="/var/log/tt_sync.log" +MC_BIN="/usr/local/bin/mc" # Change this path if mc is installed elsewhere +TELEGRAM_BOT_TOKEN="YOUR_TOKEN_HERE" +TELEGRAM_CHAT_ID="YOUR_CHAT_ID_HERE" + +# === TIMESTAMP === +TS=$(date '+%Y-%m-%d %H:%M:%S') +echo "[$TS] Starting TeamTalk sync..." >> "$LOG_FILE" + +# === SETUP ALIAS === +$MC_BIN alias set local "http://${MINIO_HOST}:${MINIO_PORT}" "$ACCESS_KEY" "$SECRET_KEY" 2>> "$LOG_FILE" + +# === SYNC === +$MC_BIN mirror "$SOURCE_DIR" "local/${BUCKET}" --overwrite --remove --quiet 2>> "$LOG_FILE" +STATUS=$? + +if [ $STATUS -eq 0 ]; then + echo "[$TS] β
Sync completed successfully." >> "$LOG_FILE" + curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ + -d chat_id="${TELEGRAM_CHAT_ID}" \ + -d text="β
TeamTalk sync to MinIO completed at $TS" +else + echo "[$TS] β Sync failed with exit code $STATUS." >> "$LOG_FILE" + curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ + -d chat_id="${TELEGRAM_CHAT_ID}" \ + -d text="β TeamTalk sync to MinIO failed at $TS (exit code $STATUS)" +fi + diff --git a/testdm.sh b/testdm.sh new file mode 100755 index 0000000..e44be4a --- /dev/null +++ b/testdm.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +MASTODON_URL="https://chatwithus.live" +ACCESS_TOKEN="DsusOr2Gr6UN-sgssHD1XOJr5q9eCbe95fYxUDPM9EQ" + +MESSAGE="π This is a test direct message from TeamTalk security script at $(hostname)!" + +curl -s -X POST "$MASTODON_URL/api/v1/statuses" \ + -H "Authorization: Bearer $ACCESS_TOKEN" \ + -F "status=$MESSAGE" \ + -F "visibility=direct" | jq . diff --git a/ttbanwatch.sh b/ttbanwatch.sh new file mode 100755 index 0000000..7680366 --- /dev/null +++ b/ttbanwatch.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +# === Config === +LOG="/var/log/fail2ban.log" +MASTODON_URL="https://chatwithus.live" +MASTODON_TOKEN="DsusOr2Gr6UN-sgssHD1XOJr5q9eCbe95fYxUDPM9EQ" + +BAN_CACHE="/var/tmp/teamtalk_ban_cache.txt" +UNBAN_CACHE="/var/tmp/teamtalk_unban_cache.txt" +TTL=604800 # 7 days in seconds + +# === Functions === + +send_dm() { + curl -s -X POST "$MASTODON_URL/api/v1/statuses" \ + -H "Authorization: Bearer $MASTODON_TOKEN" \ + -F "status=$1" \ + -F "visibility=direct" > /dev/null +} + +send_log_post() { + curl -s -X POST "$MASTODON_URL/api/v1/statuses" \ + -H "Authorization: Bearer $MASTODON_TOKEN" \ + -F "status=$1" \ + -F "visibility=unlisted" > /dev/null +} + +cleanup_cache() { + local cache_file="$1" + local now=$(date +%s) + local temp_file=$(mktemp) + + while IFS="|" read -r ip timestamp; do + [[ -z "$ip" || -z "$timestamp" ]] && continue + if (( now - timestamp < TTL )); then + echo "$ip|$timestamp" >> "$temp_file" + fi + done < "$cache_file" + + mv "$temp_file" "$cache_file" +} + +log_recent_ips() { + local keyword="$1" # Ban or Unban + grep "$keyword" "$LOG" | grep 'teamtalk' | awk -v now="$(date +%s)" ' + { + cmd = "date +%s -d \"" $1 " " $2 "\"" + cmd | getline timestamp + close(cmd) + if ((now - timestamp) <= 3600) { + print $NF + } + } + ' | sort -u +} + +# === Init Caches === +touch "$BAN_CACHE" +touch "$UNBAN_CACHE" +cleanup_cache "$BAN_CACHE" +cleanup_cache "$UNBAN_CACHE" + +# === Process Bans === +log_recent_ips "Ban" | while read ip; do + if ! grep -q "^$ip|" "$BAN_CACHE"; then + echo "$ip|$(date +%s)" >> "$BAN_CACHE" + send_dm "π« GenesisShield TeamTalk Fail2Ban alert: Banned IP $ip" + send_log_post "π« #GenesisShield TeamTalk Banned IP $ip at $(date -Is)" + fi +done + +# === Process Unbans === +log_recent_ips "Unban" | while read ip; do + if ! grep -q "^$ip|" "$UNBAN_CACHE"; then + echo "$ip|$(date +%s)" >> "$UNBAN_CACHE" + send_dm "β
TeamTalk Fail2Ban alert: IP $ip has been unbanned" + send_log_post "β
#GenesisShield TeamTalk Unbanned IP $ip at $(date -Is)" + fi +done diff --git a/watchman.sh b/watchman.sh new file mode 100755 index 0000000..085fd0d --- /dev/null +++ b/watchman.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# === Your actual setup === +HOST="38.102.127.168" # Montreal's IP to probe +THRESHOLD_LATENCY=150 # in ms +THRESHOLD_LOSS=5 # in % +CF_ZONE_ID="c5099d42caa2d9763227267c597cb758" # Replace with your real Cloudflare zone ID +CF_RECORD_ID="7001484a25f0fe5c323845b6695f7544" # Replace with your real DNS record ID +CF_API_TOKEN="lCz1kH6nBZPJL0EWrNI-xEDwfR0oOLpg05fq6M81" # Cloudflare API token +LINODE_IP="172.238.63.162" # Linode IP +LOG_FILE="/var/log/tt_failover.log" +DATE=$(date '+%Y-%m-%d %H:%M:%S') + +# === Run mtr probe === +mtr -r -c 10 $HOST > /tmp/mtr_output.txt + +# === Extract average latency and packet loss === +# Average latency from ping (use 10 pings) +AVG_LATENCY=$(ping -c 10 $HOST | tail -1| awk '{print $4}' | cut -d '/' -f 2) + +# Packet loss from ping (last line) +LOSS=$(ping -c 10 $HOST | grep -oP '\d+(?=% packet loss)') + +echo "[$DATE] DEBUG: AVG_LATENCY=$AVG_LATENCY, LOSS=$LOSS" >> $LOG_FILE + + +# === Logging === +echo "[$DATE] Latency: $AVG_LATENCY ms, Loss: $LOSS%" >> $LOG_FILE + +# === Decision === +if (( $(echo "$AVG_LATENCY > $THRESHOLD_LATENCY" | bc -l) )) || (( $(echo "$LOSS > $THRESHOLD_LOSS" | bc -l) )); then + echo "[$DATE] π΄ Montreal is glitchy! Flipping to Linode ($LINODE_IP)..." >> $LOG_FILE + curl -X PUT "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records/$CF_RECORD_ID" \ + -H "Authorization: Bearer $CF_API_TOKEN" \ + -H "Content-Type: application/json" \ + --data '{"type":"A","name":"tt.themediahub.org","content":"'"$LINODE_IP"'","ttl":60,"proxied":false}' >> $LOG_FILE 2>&1 + echo "[$DATE] β
Failover to Linode triggered." >> $LOG_FILE +else + echo "[$DATE] β
Montreal healthy. No action taken." >> $LOG_FILE +fi |
