diff --git a/check-dependencies b/check-dependencies deleted file mode 100755 index 068a934..0000000 --- a/check-dependencies +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# Version: 0.0.3 -# Copyright (c) 2007 - 2026: -# Darren 'Tadgy' Austin -# Licensed under the terms of the GNU General Public License version 3. -# -# This is a quick^Wslow dirty hack to check binaries and libraries for missing -# dependancies using ldd. Only those files with missing dependancies (along -# with the missing library information itself) will be written to stderr. -# Redirecting stderr to a file is advised, since this can produce a large -# volume of output on a system with many missing libraries. - -echo "This will take a little while..." - -{ find -P "${1:-/}" -regextype posix-extended \ - \( -regex "^/(boot|data|dev|etc|home|lost\+found|media|mnt|proc|root|run|srv|sys|tmp|var)" -a -prune \) -o \ - \( -regex "^/lib(64)?/ld-.*" -a -prune \) -o \ - \( -regex "^/lib/(dhcpcd|firmware|modprobe\.d|modules)" -a -prune \) -o \ - \( -regex "^/(opt|usr|usr/local)/(doc|etc|include|info|man|share|src)" -a -prune \) -o \ - \( -regex "^/usr/lib(64)?/(firefox|java|jdk|jre|seamonkey|thunderbird)-.*" -a -prune \) -o \ - \( -regex "^/usr/lib(64)?/(locale|qt/plugins/.*.debug)" -a -prune \) -o \ - -type f -print0 | xargs -0 -r file -N -0 | grep -E -a ".*ELF.*(executable|shared object).*dynamically" | cut -d $'\0' -f1 | sort | \ - xargs -r ldd 2>/dev/null | grep -E "(^/|not found)" | grep -E -B 1 "^[[:space:]]" | grep -E -v "^--"; } >&2 diff --git a/dehydrated-wrapper b/dehydrated-wrapper index 673e89f..e27f453 100755 --- a/dehydrated-wrapper +++ b/dehydrated-wrapper @@ -1,5 +1,5 @@ #!/bin/bash -# Delay the run for 15 hours (from midnight, when the cron job triggers) and then run at a random time within 3 hours after that. +#Delay the run for 15 hours (from midnight) and then run at a random time within 3 hours after that. sleep $(( 54000 + (RANDOM % 10800) )) /opt/gitrepos/dehydrated.git/dehydrated -c >/dev/null diff --git a/do-backup b/do-backup new file mode 100755 index 0000000..d0c8816 --- /dev/null +++ b/do-backup @@ -0,0 +1,148 @@ +#!/bin/bash +# Perform backup tasks in a generic way. + +# Base configuration. +RSYNC_OPTIONS=( '-a' '-H' '-A' '--timeout=300' '--partial' '--partial-dir=.rsync-tmp' '--delete-delay' '--delay-updates' ) +RSYNC_OPTIONS_VERBOSE=( '--verbose' '--stats' '--human-readable' ) +RSYNC_LOG="/tmp/${0##*/}-$$-$RANDOM.log" +LOCK_FILE="/tmp/${0##*/}-$$-$RANDOM.lock" + +# Sanity checks. +(( $# != 1 )) || [[ -z "$1" ]] || [[ "$1" =~ ^(-h|-help|--help)$ ]] && { + printf "%s: %s <%s>\\n" "Usage" "$0" "backup definition" >&2 + exit 1 +} + +# Remove temporary files upon exit. +trap 'rm -f "$RSYNC_LOG"; rm -f "$LOCK_FILE"' EXIT + +# Get backup definition specific configuration. +case "$1" in + 'gv0') + BACKUP_MOUNTPOINT="/localdata" + BACKUP_DESTDIR="$BACKUP_MOUNTPOINT/backups/gv0" + RSYNC_SOURCE="/storage/gv0/" # The / on the end is required. + RSYNC_FILTER=() + ;; + 'mirrors') + BACKUP_MOUNTPOINT="/localdata" + BACKUP_DESTDIR="$BACKUP_MOUNTPOINT/backups/mirrors" + RSYNC_SOURCE="slackware.uk::mirrors/" # The / on the end is required. + RSYNC_FILTER=( \ + '--include=/absolute/***' \ + '--include=/csb/***' \ + '--include=/cumulative/***' \ + '--include=/freeslack/***' \ + '--include=/gfs/***' \ + '--include=/microlinux/***' \ + '--include=/msb/***' \ + '--include=/sarpi/***' \ + '--include=/slackonly/***' \ + '--include=/slackvirt/***' \ + '--include=/slackware/' \ + '--include=/slackware/slackware-pre-1.0-beta/***' \ + '--include=/slackware/slackware-1.01/***' \ + '--include=/slackwarearm/***' \ + '--include=/slacky/***' \ + '--include=/slaxbmc/***' \ + '--include=/slint/***' \ + '--include=/sls/***' \ + '--include=/studioware/***' \ + '--exclude=*' ) + RSYNC_OPTIONS+=( '--contimeout=30' ) + ;; + 'userdir') + BACKUP_MOUNTPOINT="/data/home" + BACKUP_DESTDIR="$BACKUP_MOUNTPOINT/tadgy/UserDirs/${HOSTNAME%%.*}-$USER" + RSYNC_SOURCE="/home/$USER/" # The / on the end is required. + RSYNC_FILTER=( \ + '--exclude=/.cache/mozilla/firefox/*/cache2/***' \ + '--exclude=/.gnupg/private-keys-v1.d/*.key' \ + '--exclude=/.gnupg/openpgp-revocs.d/*.rev' \ + '--exclude=/.irssi/config' \ + '--exclude=/.ssh/id_ed25519' \ + '--exclude=/.ssh/id_rsa' ) + ERRORS_SOURCE="userdir: ${HOSTNAME%%.*}-$USER" + ;; + *) + printf "%s: %s: %s\\n" "${0##*/}" "$1" "unknown backup definition" >&2 + exit 1 + ;; +esac + +# Only allow one copy of the script to run at any time. +# shellcheck disable=SC2154 +if [[ "$FLOCK" != "$0" ]]; then + # shellcheck disable=SC2093 + exec env FLOCK="$0" flock -E 10 -e -n "$0" "$0" "$@" + ERR="$?" + if (( ERR == 10 )); then + # File is locked, exit now. + exit 0 + elif (( ERR > 0 )); then + printf "%s: %s\\n" "${0##*/}" "flock execution error" >&2 + exit 1 + fi +fi + +# Source the mail configuration. +source /etc/mail.conf "backups" 2>/dev/null || { + printf "%s: %s\\n" "${0##*/}" "Failed to source /etc/mail.conf" >&2 + exit 1 +} + +# Make sure BACKUP_MOUNTPOINT is a mountpoint. +# Note: The / on the end if required for automount mountpoints. +mountpoint "$BACKUP_MOUNTPOINT/" >/dev/null 2>&1 || { + [[ -x /opt/bin/pushover-client ]] && /opt/bin/pushover-client "backups" -p -1 -m "Backup failure: ${ERRORS_SOURCE:-$RSYNC_SOURCE}" + if [[ -n "${EMAIL_TO[*]}" ]]; then + mailx "${MAILX_ARGS[@]}" -S "from=$EMAIL_FROM" -s "Backup failure: ${ERRORS_SOURCE:-$RSYNC_SOURCE}" "${EMAIL_TO[@]}" <<-EOF 2>/dev/null || \ + printf "%s: %s\\n" "${0##*/}" "mailx command failed" >&2 + '$BACKUP_MOUNTPOINT' is not a mountpoint. + EOF + exit 1 + else + printf "%s: %s\\n" "${0##*/}" "no recipient configured for mail delivery" >&2 + exit 1 + fi +} + +# Create the BACKUP_DESTDIR if required. +[[ ! -e "$BACKUP_DESTDIR" ]] && { + mkdir -p "$BACKUP_DESTDIR" || { + [[ -x /opt/bin/pushover-client ]] && /opt/bin/pushover-client "backups" -p -1 -m "Backup failure: ${ERRORS_SOURCE:-$RSYNC_SOURCE}" + if [[ -n "${EMAIL_TO[*]}" ]]; then + mailx "${MAILX_ARGS[@]}" -S "from=$EMAIL_FROM" -s "Backup failure: ${ERRORS_SOURCE:-$RSYNC_SOURCE}" "${EMAIL_TO[@]}" <<-EOF 2>/dev/null || \ + printf "%s: %s\\n" "${0##*/}" "mailx command failed" >&2 + Failed to mkdir '$BACKUP_DESTDIR'. + EOF + exit 1 + else + printf "%s: %s\\n" "${0##*/}" "no recipient configured for mail delivery" >&2 + exit 1 + fi + } +} + +# Do the backup. +ionice -c Idle nice -n 19 rsync "${RSYNC_OPTIONS[@]}" "${RSYNC_OPTIONS_VERBOSE[@]}" "${RSYNC_FILTER[@]}" "$RSYNC_SOURCE" "$BACKUP_DESTDIR" >"$RSYNC_LOG" 2>&1 +ERR="$?" + +# Send a notification and mail a log if there were errors. +(( ERR != 0 )) && (( ERR != 10 )) && (( ERR != 24 )) && { + [[ -x /opt/bin/pushover-client ]] && /opt/bin/pushover-client "backups" -p -1 -m "Backup failure: ${ERRORS_SOURCE:-$RSYNC_SOURCE}" + if [[ -n "${EMAIL_TO[*]}" ]]; then + mailx "${MAILX_ARGS[@]}" -S "from=$EMAIL_FROM" -s "Backup failure: ${ERRORS_SOURCE:-$RSYNC_SOURCE}" "${EMAIL_TO[@]}" <<-EOF 2>/dev/null || \ + printf "%s: %s\\n" "${0##*/}" "mailx command failed" >&2 + Exit code: $ERR + Output: + $(< "$RSYNC_LOG") + EOF + exit 1 + else + printf "%s: %s\\n" "${0##*/}" "no recipient configured for mail delivery" >&2 + exit 1 + fi +} + +exit 0 diff --git a/dovecot-service-checksuspended b/dovecot-service-checksuspended new file mode 100755 index 0000000..da11b7e --- /dev/null +++ b/dovecot-service-checksuspended @@ -0,0 +1,18 @@ +#!/bin/bash +# A Dovecot service script to check whether a domain or user has been suspended from being able to use mail. + +VIRTUAL_DIR="/etc/virtual" +U="${USER%%@*}" +D="${USER#*@}" + +[[ -e "$VIRTUAL_DIR/$D/suspended" ]] && { + printf "* %s\\r\\n" "NO [ALERT] Domain suspended" + exit 0 +} + +[[ -e "$VIRTUAL_DIR/$D/$U/suspended" ]] && { + printf "* %s\\r\\n" "NO [ALERT] User suspended" + exit 0 +} + +exec "$@" diff --git a/rsyncd-notify-upload b/notify-rsync-upload similarity index 100% rename from rsyncd-notify-upload rename to notify-rsync-upload diff --git a/tlog-f95c691-devuan.tar.xz b/tlog-f95c691-devuan.tar.xz new file mode 100644 index 0000000..3913c80 Binary files /dev/null and b/tlog-f95c691-devuan.tar.xz differ diff --git a/tlog-f95c691-slackware.tar.xz b/tlog-f95c691-slackware.tar.xz new file mode 100644 index 0000000..1530dc4 Binary files /dev/null and b/tlog-f95c691-slackware.tar.xz differ diff --git a/tlog-session-list b/tlog-session-list new file mode 100755 index 0000000..60bdf98 --- /dev/null +++ b/tlog-session-list @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 + +import sys +import json +import datetime +import argparse + +def format_timestamp(ts): + return datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') + +def main(): + parser = argparse.ArgumentParser(description="List Tlog session metadata") + parser.add_argument("file", help="Path to the tlog session JSON file") + parser.add_argument("--user", help="Filter by username") + args = parser.parse_args() + + sessions = {} + + with open(args.file, 'r') as f: + for line in f: + try: + record = json.loads(line) + rec_id = record.get('rec') + user = record.get('user', 'unknown') + + if not rec_id: + continue + + if args.user and user != args.user: + continue + + if rec_id not in sessions: + timestamp = record.get('time', 0) + sessions[rec_id] = { + 'time': timestamp, + 'formatted_time': format_timestamp(timestamp), + 'rec': rec_id, + 'host': record.get('host', 'unknown'), + 'user': user + } + except json.JSONDecodeError: + continue # skip bad lines + + sorted_sessions = sorted(sessions.values(), key=lambda s: s['time'], reverse=True) + + print(f"{'Time':<20} | {'Session ID':<50} | {'Hostname':<25} | {'User'}") + print('-' * 120) + for sess in sorted_sessions: + print(f"{sess['formatted_time']:<20} | {sess['rec']:<50} | {sess['host']:<25} | {sess['user']}") + +if __name__ == "__main__": + main() diff --git a/tlog.README b/tlog.README new file mode 100644 index 0000000..2d2a022 --- /dev/null +++ b/tlog.README @@ -0,0 +1,5 @@ +The tlog tar archive contains a statically linked version of tlog, installed +into /opt (/etc/tlog as sysconfdir). + +It should be untarred in / to install tlog onto the system. +A symlink from tlog-rec-session should be placed in /usr/bin for sssd.