132 lines
4.5 KiB
Bash
132 lines
4.5 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Steps to run
|
|
DO_ACCOUNTS_CULL=${DO_ACCOUNTS_CULL:-true}
|
|
DO_MEDIA_REMOVE=${DO_MEDIA_REMOVE:-true}
|
|
DO_STATUSES_REMOVE=${DO_STATUSES_REMOVE:-true}
|
|
DO_CACHE_RECOUNT=${DO_CACHE_RECOUNT:-true}
|
|
# Environment variables for main settings
|
|
TOOTCTL=${TOOTCTL:-/home/mastodon/live/bin/tootctl}
|
|
export DB_POOL=${DB_POOL:-5}
|
|
DRY_RUN=${DRY_RUN:-true}
|
|
# Date difference for expired certificate, default 2w
|
|
TLS_EXPIRED_MAX_SEC=${TLS_EXPIRED_MAX_SEC:-1210000}
|
|
# How many seconds to wait to connect to an instance already in error in the
|
|
# past
|
|
INSTANCE_LAST_CHANCE_TIMEOUT=${INSTANCE_LAST_CHANCE_TIMEOUT:-30}
|
|
# How old media attachments have to be before getting removed
|
|
MEDIA_REMOVE_DAYS=${MEDIA_REMOVE_DAYS:-7}
|
|
CARDS_REMOVE_DAYS=${CARDS_REMOVE_DAYS:-15}
|
|
# How old unreferenced statuses have to be before getting removed
|
|
STATUSES_REMOVE_DAYS=${STATUSES_REMOVE_DAYS:-30}
|
|
# Path to logs files
|
|
CULL_LOG=$(mktemp /tmp/tootpaste_XXX)
|
|
TLS_EXPIRED_LOG=$(mktemp /tmp/tootpaste_XXX)
|
|
OTHER_ERRORS_LOG=$(mktemp /tmp/tootpaste_XXX)
|
|
PREV_ERRORS_LOG=/tmp/tootpaste_prev_errors
|
|
|
|
accounts_cull() {
|
|
|
|
$DRY_RUN && $TOOTCTL accounts cull --dry-run --concurrency "$DB_POOL" > "$CULL_LOG"
|
|
$DRY_RUN || $TOOTCTL accounts cull --concurrency "$DB_POOL" > "$CULL_LOG"
|
|
|
|
# Remove instances that have an expired certificate from more than
|
|
# TLS_EXPIRED_MAX_SEC
|
|
grep 'certificate has expired' "$CULL_LOG" \
|
|
| awk '{print $NF}' \
|
|
| cut -d'/' -f3 \
|
|
| sort -u \
|
|
> "$TLS_EXPIRED_LOG"
|
|
|
|
while read -r instance; do
|
|
TLS_EXPIRED_TS=$(
|
|
date -d "$(
|
|
echo Q \
|
|
| openssl s_client \
|
|
-servername "$instance" \
|
|
-connect "${instance}":443 \
|
|
2>/dev/null \
|
|
| openssl x509 -noout -dates \
|
|
| grep 'notAfter' \
|
|
| cut -d'=' -f2
|
|
)" +%s
|
|
)
|
|
DATE_DIFF=$(($(date +%s) - TLS_EXPIRED_TS))
|
|
if [[ $DATE_DIFF -gt $TLS_EXPIRED_MAX_SEC ]]; then
|
|
echo "${instance} has a certificate expired for more than TLS_EXPIRED_MAX_SEC, purging..."
|
|
$DRY_RUN && $TOOTCTL domains purge --concurrency "$DB_POOL" --dry-run "$instance"
|
|
$DRY_RUN || $TOOTCTL domains purge --concurrency "$DB_POOL" "$instance"
|
|
fi
|
|
done < "$TLS_EXPIRED_LOG"
|
|
|
|
# Log other instances errors, then if they were already in the log, purge
|
|
# them
|
|
grep \
|
|
-e 'certificate verify failed' \
|
|
-e 'timed out' \
|
|
-e 'sslv3 alert handshake failure' \
|
|
-e 'TooManyRedirectsError' \
|
|
"$CULL_LOG" \
|
|
| awk '{print $NF}' \
|
|
| cut -d'/' -f3 \
|
|
| sort -u \
|
|
> "$OTHER_ERRORS_LOG"
|
|
|
|
test -f $PREV_ERRORS_LOG || touch $PREV_ERRORS_LOG
|
|
while read -r instance; do
|
|
if grep -q "$instance" $PREV_ERRORS_LOG; then
|
|
error=false
|
|
echo "${instance} was already in error last time your ran tootpaste, trying access..."
|
|
curl \
|
|
--silent \
|
|
--show-error \
|
|
--max-time "$INSTANCE_LAST_CHANCE_TIMEOUT" \
|
|
https://"${instance}" \
|
|
|| error=true
|
|
if $error; then
|
|
echo "${instance} still cannot be accessed, purging..."
|
|
$DRY_RUN && $TOOTCTL domains purge --concurrency "$DB_POOL" --dry-run "$instance"
|
|
$DRY_RUN || $TOOTCTL domains purge --concurrency "$DB_POOL" "$instance"
|
|
fi
|
|
fi
|
|
done < "$OTHER_ERRORS_LOG"
|
|
cat "$OTHER_ERRORS_LOG" >> $PREV_ERRORS_LOG
|
|
}
|
|
|
|
cache_recount(){
|
|
|
|
$DRY_RUN && echo 'Not running cache recount in dry run.'
|
|
$DRY_RUN || $TOOTCTL cache recount accounts --concurrency "$DB_POOL"
|
|
$DRY_RUN || $TOOTCTL cache recount statuses --concurrency "$DB_POOL"
|
|
}
|
|
|
|
media_remove(){
|
|
|
|
$DRY_RUN && $TOOTCTL media remove --days "$MEDIA_REMOVE_DAYS" --concurrency "$DB_POOL" --dry-run
|
|
$DRY_RUN || $TOOTCTL media remove --days "$MEDIA_REMOVE_DAYS" --concurrency "$DB_POOL"
|
|
|
|
$DRY_RUN && $TOOTCTL media remove-orphans --dry-run
|
|
$DRY_RUN || $TOOTCTL media remove-orphans
|
|
$DRY_RUN && $TOOTCTL preview_cards remove --days "$MEDIA_REMOVE_DAYS" --concurrency "$DB_POOL" --dry-run
|
|
$DRY_RUN || $TOOTCTL preview_cards remove --days "$CARDS_REMOVE_DAYS" --concurrency "$DB_POOL" --link
|
|
}
|
|
|
|
statuses_remove(){
|
|
|
|
$DRY_RUN && echo 'Not removing old statuses in dry-run.'
|
|
$DRY_RUN || $TOOTCTL statuses remove --days "$STATUSES_REMOVE_DAYS"
|
|
}
|
|
|
|
check_command(){
|
|
command -v "$1" > /dev/null
|
|
}
|
|
|
|
for command in $TOOTCTL curl grep awk cut sort; do
|
|
check_command "$command" || (echo "$command not found, exiting..."; exit 1)
|
|
done
|
|
|
|
$DO_ACCOUNTS_CULL && accounts_cull
|
|
$DO_MEDIA_REMOVE && media_remove
|
|
$DO_STATUSES_REMOVE && statuses_remove
|
|
$DO_CACHE_RECOUNT && cache_recount
|