Skip to content

Instantly share code, notes, and snippets.

@maciekish
Last active February 21, 2026 14:13
Show Gist options
  • Select an option

  • Save maciekish/6fb4665c5c5c9f2c6a8641bacaf6282e to your computer and use it in GitHub Desktop.

Select an option

Save maciekish/6fb4665c5c5c9f2c6a8641bacaf6282e to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Remote run (from target Linux host):
# curl -fsSL https://gist.githubusercontent.com/maciekish/6fb4665c5c5c9f2c6a8641bacaf6282e/raw | bash
# Optional args:
# curl -fsSL https://gist.githubusercontent.com/maciekish/6fb4665c5c5c9f2c6a8641bacaf6282e/raw | bash -s -- --dry-run --yes
# Source gist page:
# https://gist.github.com/maciekish/6fb4665c5c5c9f2c6a8641bacaf6282e
set -Eeuo pipefail
IFS=$'\n\t'
SCRIPT_VERSION="1.0.0"
LOG_PREFIX="[algo-cleanup]"
DRY_RUN=0
ASSUME_YES=0
FORCE=0
KEEP_ALGO_USER=0
KEEP_PACKAGES=0
PURGE_EXTRA_TOOLS=0
SKIP_SSHD_RESET=0
NO_RESTART=0
NO_FIREWALL_FLUSH=0
BACKUP_DIR=""
TIMESTAMP="$(date -u +%Y%m%dT%H%M%SZ)"
CURRENT_LOGIN_USER="${SUDO_USER:-${USER:-}}"
readonly SERVICE_UNITS=(
"wg-quick@wg0.service"
"strongswan-starter.service"
"strongswan.service"
"dnscrypt-proxy.socket"
"dnscrypt-proxy.service"
"netfilter-persistent.service"
"privacy-shutdown-cleanup.service"
)
readonly CRON_ENTRY_NAMES=(
"Adblock hosts update"
"Enhanced privacy log rotation"
"Privacy auto cleanup"
"Privacy auto cleanup weekly"
"Privacy auto cleanup monthly"
)
readonly ALGO_FILE_PATHS=(
"/etc/systemd/network/10-algo-lo100.network"
"/etc/netplan/99-algo-ipv6-egress.yaml"
"/etc/systemd/system/dnscrypt-proxy.service.d/99-algo.conf"
"/etc/systemd/system/dnscrypt-proxy.service.d/90-security-hardening.conf"
"/etc/systemd/system/dnscrypt-proxy.socket.d/10-algo-override.conf"
"/etc/systemd/system/wg-quick@wg0.service.d/90-security-hardening.conf"
"/etc/systemd/system/strongswan-starter.service.d/100-CustomLimitations.conf"
"/etc/systemd/system/strongswan.service.d/100-CustomLimitations.conf"
"/etc/systemd/system/privacy-shutdown-cleanup.service"
"/etc/apparmor.d/usr.bin.dnscrypt-proxy"
"/etc/apparmor.d/local/usr.lib.ipsec.charon"
"/etc/rsyslog.d/45-privacy-minimal.conf"
"/etc/rsyslog.d/46-privacy-ssh-filter.conf"
"/etc/rsyslog.d/47-privacy-auth-filter.conf"
"/etc/rsyslog.d/48-privacy-kernel-filter.conf"
"/etc/rsyslog.d/49-privacy-vpn-filter.conf"
"/etc/logrotate.d/99-privacy-enhanced"
"/etc/logrotate.d/99-auth-privacy"
"/etc/logrotate.d/99-kern-privacy"
"/usr/local/sbin/adblock.sh"
"/usr/local/bin/privacy-auto-cleanup.sh"
"/usr/local/bin/privacy-log-cleanup.sh"
"/usr/local/bin/privacy-monitor.sh"
"/var/log/privacy-cleanup.log"
"/etc/sysctl.d/99-privacy.conf"
"/etc/apt/apt.conf.d/10periodic"
"/etc/apt/apt.conf.d/50unattended-upgrades"
"/etc/apt/apt.conf.d/50-dnscrypt-proxy-unattended-upgrades"
"/etc/iptables/rules.v4"
"/etc/iptables/rules.v6"
"/etc/ipsec.conf"
"/etc/ipsec.secrets"
"/etc/strongswan.conf"
"/etc/strongswan.d/charon.conf"
"/etc/ipsec.d/crls/algo.root.pem"
"/etc/sudoers.d/10-algo-user"
)
readonly ALGO_DIR_PATHS=(
"/etc/wireguard"
"/etc/dnscrypt-proxy"
"/var/cache/dnscrypt-proxy"
"/etc/ipsec.d"
"/etc/strongswan.d"
"/var/lib/strongswan"
"/var/jail"
)
readonly CORE_PACKAGES=(
"dnscrypt-proxy"
"wireguard"
"wireguard-tools"
"strongswan"
"strongswan-starter"
"strongswan-charon"
"strongswan-libcharon"
"strongswan-libcharon-extra-plugins"
"strongswan-pki"
"strongswan-swanctl"
"netfilter-persistent"
"iptables-persistent"
"unattended-upgrades"
)
readonly EXTRA_TOOL_PACKAGES=(
"apparmor-utils"
"cgroup-tools"
"uuid-runtime"
"screen"
"git"
)
usage() {
cat <<'EOF'
Usage: algo-uninstall-cleanup.sh [options]
Comprehensively remove host-side changes made by trailofbits/algo.
Run as root on the target Linux host.
Options:
-n, --dry-run Show what would run without changing the system
-y, --yes Skip interactive confirmation
--force Run even if no Algo markers are detected
--keep-algo-user Keep the cloud-init "algo" login user
--keep-packages Keep installed packages (remove configs/users only)
--purge-extra-tools Also purge extra tools installed by Algo (git/screen/etc)
--skip-sshd-reset Do not reset cloud-init sshd_config to distro defaults
--no-restart Do not restart services at end
--no-firewall-flush Do not flush iptables/ip6tables
--backup-dir <dir> Override backup output dir (default: /var/backups/algo-cleanup-<timestamp>)
-h, --help Show this help
Examples:
sudo ./algo-uninstall-cleanup.sh --dry-run
sudo ./algo-uninstall-cleanup.sh --yes
sudo ./algo-uninstall-cleanup.sh --yes --keep-algo-user --skip-sshd-reset
EOF
}
log() {
printf '%s %s\n' "$LOG_PREFIX" "$*"
}
warn() {
printf '%s WARNING: %s\n' "$LOG_PREFIX" "$*" >&2
}
die() {
printf '%s ERROR: %s\n' "$LOG_PREFIX" "$*" >&2
exit 1
}
print_cmd() {
local rendered=""
printf -v rendered '%q ' "$@"
printf '%s' "${rendered% }"
}
run_cmd() {
if (( DRY_RUN )); then
log "[dry-run] $(print_cmd "$@")"
return 0
fi
"$@"
}
run_ignore_failure() {
if (( DRY_RUN )); then
log "[dry-run] $(print_cmd "$@")"
return 0
fi
"$@" >/dev/null 2>&1 || true
}
parse_args() {
while (( $# > 0 )); do
case "$1" in
-n|--dry-run)
DRY_RUN=1
;;
-y|--yes)
ASSUME_YES=1
;;
--force)
FORCE=1
;;
--keep-algo-user)
KEEP_ALGO_USER=1
;;
--keep-packages)
KEEP_PACKAGES=1
;;
--purge-extra-tools)
PURGE_EXTRA_TOOLS=1
;;
--skip-sshd-reset)
SKIP_SSHD_RESET=1
;;
--no-restart)
NO_RESTART=1
;;
--no-firewall-flush)
NO_FIREWALL_FLUSH=1
;;
--backup-dir)
shift
(( $# > 0 )) || die "--backup-dir requires a value"
BACKUP_DIR="$1"
;;
-h|--help)
usage
exit 0
;;
*)
die "Unknown option: $1 (use --help)"
;;
esac
shift
done
}
require_root_linux() {
[[ "$(uname -s)" == "Linux" ]] || die "This script supports Linux target hosts only."
(( EUID == 0 )) || die "Run as root (sudo)."
}
detect_algo_markers() {
local markers=0
[[ -f /etc/systemd/network/10-algo-lo100.network ]] && (( markers++ ))
[[ -f /etc/wireguard/wg0.conf ]] && (( markers++ ))
[[ -f /etc/rsyslog.d/49-privacy-vpn-filter.conf ]] && (( markers++ ))
[[ -f /etc/systemd/system/privacy-shutdown-cleanup.service ]] && (( markers++ ))
[[ -f /usr/local/sbin/adblock.sh ]] && (( markers++ ))
getent passwd strongswan >/dev/null && (( markers++ ))
getent passwd algo >/dev/null && (( markers++ ))
if [[ -f /etc/ipsec.conf ]] && grep -q 'ikev2-pubkey' /etc/ipsec.conf; then
(( markers++ ))
fi
if [[ -f /etc/ssh/sshd_config ]] && grep -Eq '^[[:space:]]*AllowGroups[[:space:]]+algo([[:space:]]|$)' /etc/ssh/sshd_config; then
(( markers++ ))
fi
if [[ -f /etc/ssh/sshd_config ]] && grep -q 'ANSIBLE MANAGED BLOCK ssh_tunneling_role' /etc/ssh/sshd_config; then
(( markers++ ))
fi
echo "$markers"
}
confirm_action() {
local marker_count="$1"
log "Detected $marker_count Algo marker(s)."
if (( ASSUME_YES )); then
return
fi
cat <<EOF
This script will remove Algo VPN host-side changes, including:
- VPN services/configs (WireGuard, StrongSwan, DNSCrypt)
- Algo-created users/groups (including cloud-init user "algo" unless --keep-algo-user)
- Algo firewall/sysctl/cron/rsyslog/logrotate/privacy artifacts
It can affect SSH access if your current access depends on Algo's sshd_config.
Backup location: ${BACKUP_DIR}
EOF
printf 'Continue? [y/N]: '
local answer
read -r answer
[[ "$answer" =~ ^[Yy]$ ]] || die "Aborted."
}
create_backup() {
if [[ -z "$BACKUP_DIR" ]]; then
BACKUP_DIR="/var/backups/algo-cleanup-${TIMESTAMP}"
fi
if (( DRY_RUN )); then
log "[dry-run] would create backup dir: $BACKUP_DIR"
return
fi
mkdir -p "$BACKUP_DIR"
date -u +"%Y-%m-%dT%H:%M:%SZ" > "${BACKUP_DIR}/created_at_utc.txt"
# Operational snapshots
(crontab -u root -l || true) > "${BACKUP_DIR}/root.crontab.before"
(getent passwd || true) > "${BACKUP_DIR}/passwd.before"
(getent group || true) > "${BACKUP_DIR}/group.before"
(dpkg -l || true) > "${BACKUP_DIR}/dpkg.before"
(sysctl -a 2>/dev/null || true) > "${BACKUP_DIR}/sysctl.before"
(iptables-save 2>/dev/null || true) > "${BACKUP_DIR}/iptables.before.v4"
(ip6tables-save 2>/dev/null || true) > "${BACKUP_DIR}/iptables.before.v6"
local existing_paths=()
local path
for path in \
/etc/ssh/sshd_config \
/etc/pam.d/login \
/etc/pam.d/sshd \
/etc/systemd/resolved.conf \
/etc/systemd/journald.conf \
/etc/sysctl.conf \
/etc/modules \
/etc/modules-load.d \
/etc/logrotate.d/rsyslog \
/etc/logrotate.d/rsyslog.disabled \
/root/.bashrc \
/home/ubuntu/.bashrc \
"${ALGO_FILE_PATHS[@]}" \
"${ALGO_DIR_PATHS[@]}"; do
if [[ -e "$path" || -L "$path" ]]; then
existing_paths+=("$path")
fi
done
if (( ${#existing_paths[@]} > 0 )); then
tar -czf "${BACKUP_DIR}/files.before.tar.gz" --absolute-names "${existing_paths[@]}" >/dev/null 2>&1 || true
fi
log "Backup written to ${BACKUP_DIR}"
}
remove_exact_line() {
local file="$1"
local line="$2"
[[ -f "$file" ]] || return 0
grep -Fqx "$line" "$file" || return 0
if (( DRY_RUN )); then
log "[dry-run] remove exact line from ${file}: ${line}"
return 0
fi
local tmp
tmp="$(mktemp)"
awk -v target="$line" '$0 != target {print}' "$file" > "$tmp"
cat "$tmp" > "$file"
rm -f "$tmp"
}
remove_lines_regex() {
local file="$1"
local regex="$2"
[[ -f "$file" ]] || return 0
if ! grep -Eq "$regex" "$file"; then
return 0
fi
run_cmd sed -i -E "\\#${regex}#d" "$file"
}
remove_block_between_markers() {
local file="$1"
local start_marker="$2"
local end_marker="$3"
[[ -f "$file" ]] || return 0
grep -Fq "$start_marker" "$file" || return 0
if (( DRY_RUN )); then
log "[dry-run] remove block in ${file}: ${start_marker} ... ${end_marker}"
return 0
fi
local tmp
tmp="$(mktemp)"
awk -v start="$start_marker" -v end="$end_marker" '
$0 == start {skip=1; next}
$0 == end {skip=0; next}
!skip {print}
' "$file" > "$tmp"
cat "$tmp" > "$file"
rm -f "$tmp"
}
remove_ansible_cron_entry() {
local entry_name="$1"
command -v crontab >/dev/null 2>&1 || return 0
local tmp_old tmp_new
tmp_old="$(mktemp)"
tmp_new="$(mktemp)"
if ! crontab -u root -l > "$tmp_old" 2>/dev/null; then
rm -f "$tmp_old" "$tmp_new"
return 0
fi
awk -v marker="#Ansible: ${entry_name}" '
$0 == marker {skip=1; next}
skip==1 {skip=0; next}
{print}
' "$tmp_old" > "$tmp_new"
if ! cmp -s "$tmp_old" "$tmp_new"; then
if (( DRY_RUN )); then
log "[dry-run] remove root cron entry: ${entry_name}"
else
crontab -u root "$tmp_new"
fi
fi
rm -f "$tmp_old" "$tmp_new"
}
remove_cron_entries() {
local name
for name in "${CRON_ENTRY_NAMES[@]}"; do
remove_ansible_cron_entry "$name"
done
}
stop_disable_units() {
command -v systemctl >/dev/null 2>&1 || return 0
local unit
for unit in "${SERVICE_UNITS[@]}"; do
run_ignore_failure systemctl disable --now "$unit"
done
}
reset_sshd_if_algo_managed() {
local sshd_cfg="/etc/ssh/sshd_config"
[[ -f "$sshd_cfg" ]] || return 0
remove_block_between_markers \
"$sshd_cfg" \
"# BEGIN ANSIBLE MANAGED BLOCK ssh_tunneling_role" \
"# END ANSIBLE MANAGED BLOCK ssh_tunneling_role"
if (( SKIP_SSHD_RESET )); then
return 0
fi
if ! grep -Eq '^[[:space:]]*AllowGroups[[:space:]]+algo([[:space:]]|$)' "$sshd_cfg"; then
return 0
fi
log "Detected cloud-init Algo sshd_config; resetting to distro default."
if [[ -f /usr/share/openssh/sshd_config ]]; then
run_cmd install -o root -g root -m 0644 /usr/share/openssh/sshd_config "$sshd_cfg"
return 0
fi
if command -v apt-get >/dev/null 2>&1; then
run_cmd env DEBIAN_FRONTEND=noninteractive \
apt-get -y install --reinstall -o Dpkg::Options::=--force-confnew openssh-server
return 0
fi
warn "Could not find /usr/share/openssh/sshd_config or apt-get; removing AllowGroups algo line only."
remove_lines_regex "$sshd_cfg" '^[[:space:]]*AllowGroups[[:space:]]+algo([[:space:]]|$)'
}
restore_pam_motd_entries() {
local file
for file in /etc/pam.d/login /etc/pam.d/sshd; do
[[ -f "$file" ]] || continue
remove_exact_line "$file" "# MOTD DISABLED"
if ! grep -Eq 'pam_motd\.so' "$file"; then
if (( DRY_RUN )); then
log "[dry-run] append pam_motd lines to ${file}"
else
{
echo "session optional pam_motd.so motd=/run/motd.dynamic"
echo "session optional pam_motd.so noupdate"
} >> "$file"
fi
fi
done
}
restore_journald_conf() {
local conf="/etc/systemd/journald.conf"
[[ -f "$conf" ]] || return 0
local backups=()
local backup
while IFS= read -r backup; do
backups+=("$backup")
done < <(ls -1tr /etc/systemd/journald.conf.* 2>/dev/null || true)
if (( ${#backups[@]} > 0 )); then
log "Restoring ${conf} from oldest backup: ${backups[0]}"
run_cmd cp -f -- "${backups[0]}" "$conf"
return 0
fi
remove_lines_regex "$conf" '^[[:space:]]*#?[[:space:]]*(MaxRetentionSec|MaxFileSec|SystemMaxUse|SystemMaxFileSize|ForwardToSyslog|Storage)[[:space:]]*='
}
remove_privacy_bashrc_lines() {
local file
for file in /root/.bashrc /home/ubuntu/.bashrc; do
[[ -f "$file" ]] || continue
remove_exact_line "$file" "# Privacy enhancement: disable bash history"
remove_exact_line "$file" "export HISTFILE=/dev/null"
remove_exact_line "$file" "export HISTSIZE=0"
remove_exact_line "$file" "export HISTFILESIZE=0"
remove_exact_line "$file" "unset HISTFILE"
done
}
remove_generated_bash_logout() {
local file="/etc/bash.bash_logout"
[[ -f "$file" ]] || return 0
if grep -Fq "Generated by Algo VPN privacy role" "$file"; then
run_cmd rm -f -- "$file"
fi
}
remove_af_key_persistence() {
remove_exact_line "/etc/modules" "af_key"
local modules_file
shopt -s nullglob
for modules_file in /etc/modules-load.d/*.conf; do
remove_exact_line "$modules_file" "af_key"
# Remove empty config files left behind
if [[ -f "$modules_file" ]] && [[ ! -s "$modules_file" ]]; then
run_cmd rm -f -- "$modules_file"
fi
done
shopt -u nullglob
}
remove_sysctl_keys() {
local sysctl_file="/etc/sysctl.conf"
if [[ -f "$sysctl_file" ]]; then
local key escaped
for key in \
"net.ipv4.ip_forward" \
"net.ipv4.conf.all.forwarding" \
"net.ipv4.conf.all.route_localnet" \
"net.ipv6.conf.all.forwarding" \
"kernel.printk" \
"kernel.dmesg_restrict"; do
escaped="${key//./\\.}"
remove_lines_regex "$sysctl_file" "^[[:space:]]*${escaped}[[:space:]]*="
done
fi
# Runtime rollback where safe
run_ignore_failure sysctl -w net.ipv4.ip_forward=0
run_ignore_failure sysctl -w net.ipv4.conf.all.forwarding=0
run_ignore_failure sysctl -w net.ipv4.conf.all.route_localnet=0
run_ignore_failure sysctl -w net.ipv6.conf.all.forwarding=0
run_ignore_failure sysctl -w kernel.dmesg_restrict=0
}
remove_algo_paths() {
local path
for path in "${ALGO_FILE_PATHS[@]}"; do
if [[ -e "$path" || -L "$path" ]]; then
run_cmd rm -rf -- "$path"
fi
done
for path in "${ALGO_DIR_PATHS[@]}"; do
if [[ -e "$path" || -L "$path" ]]; then
run_cmd rm -rf -- "$path"
fi
done
}
restore_logrotate_default_if_needed() {
if [[ -f /etc/logrotate.d/rsyslog.disabled && ! -e /etc/logrotate.d/rsyslog ]]; then
run_cmd mv /etc/logrotate.d/rsyslog.disabled /etc/logrotate.d/rsyslog
fi
}
delete_user_if_present() {
local username="$1"
getent passwd "$username" >/dev/null || return 0
if [[ "$CURRENT_LOGIN_USER" == "$username" ]]; then
warn "Skipping removal of active login user '${username}'."
return 0
fi
run_ignore_failure pkill -KILL -u "$username"
run_ignore_failure userdel -r "$username"
}
remove_algo_users_and_groups() {
local jail_users=()
local user
while IFS=: read -r user _ _ _ _ home _; do
if [[ "$home" == /var/jail/* ]]; then
jail_users+=("$user")
fi
done < /etc/passwd
for user in "${jail_users[@]}"; do
delete_user_if_present "$user"
done
delete_user_if_present "strongswan"
if (( ! KEEP_ALGO_USER )); then
delete_user_if_present "algo"
else
log "Keeping 'algo' user as requested."
fi
if getent group algo >/dev/null; then
local gid secondary_members
gid="$(getent group algo | cut -d: -f3)"
secondary_members="$(getent group algo | cut -d: -f4)"
if awk -F: -v g="$gid" '$4 == g {found=1} END{exit found ? 0 : 1}' /etc/passwd; then
warn "Keeping group 'algo' because it is still a primary group for existing user(s)."
elif [[ -n "$secondary_members" ]]; then
warn "Keeping group 'algo' because it still has member(s): ${secondary_members}"
else
run_ignore_failure groupdel algo
fi
fi
}
purge_algo_packages() {
if (( KEEP_PACKAGES )); then
log "Keeping packages as requested (--keep-packages)."
return 0
fi
command -v apt-get >/dev/null 2>&1 || {
warn "apt-get not found; skipping package purge."
return 0
}
local candidates=("${CORE_PACKAGES[@]}")
if (( PURGE_EXTRA_TOOLS )); then
candidates+=("${EXTRA_TOOL_PACKAGES[@]}")
fi
local installed=()
local pkg
for pkg in "${candidates[@]}"; do
if dpkg-query -W -f='${Status}' "$pkg" 2>/dev/null | grep -q '^install ok installed$'; then
installed+=("$pkg")
fi
done
if (( ${#installed[@]} == 0 )); then
log "No candidate Algo packages currently installed."
return 0
fi
log "Purging packages: ${installed[*]}"
run_cmd env DEBIAN_FRONTEND=noninteractive apt-get -y purge "${installed[@]}"
run_cmd env DEBIAN_FRONTEND=noninteractive apt-get -y autoremove --purge
}
flush_firewall_rules() {
if (( NO_FIREWALL_FLUSH )); then
log "Skipping firewall flush (--no-firewall-flush)."
return 0
fi
local tool table
for tool in iptables ip6tables; do
command -v "$tool" >/dev/null 2>&1 || continue
run_ignore_failure "$tool" -P INPUT ACCEPT
run_ignore_failure "$tool" -P FORWARD ACCEPT
run_ignore_failure "$tool" -P OUTPUT ACCEPT
for table in filter nat mangle raw security; do
run_ignore_failure "$tool" -t "$table" -F
run_ignore_failure "$tool" -t "$table" -X
done
done
run_ignore_failure ip xfrm state flush
run_ignore_failure ip xfrm policy flush
}
reset_iptables_alternatives() {
command -v update-alternatives >/dev/null 2>&1 || return 0
run_ignore_failure update-alternatives --auto iptables
run_ignore_failure update-alternatives --auto ip6tables
}
reload_runtime() {
remove_lines_regex /etc/systemd/resolved.conf '^[[:space:]]*FallbackDNS[[:space:]]*='
run_ignore_failure modprobe -r af_key
run_ignore_failure sysctl --system
if command -v netplan >/dev/null 2>&1; then
run_ignore_failure netplan apply
fi
if command -v systemctl >/dev/null 2>&1; then
run_ignore_failure systemctl daemon-reload
if (( ! NO_RESTART )); then
run_ignore_failure systemctl restart systemd-networkd
run_ignore_failure systemctl restart systemd-resolved
run_ignore_failure systemctl restart rsyslog
run_ignore_failure systemctl restart systemd-journald
run_ignore_failure systemctl restart ssh
run_ignore_failure systemctl restart sshd
fi
fi
}
cleanup_empty_dropin_dirs() {
local dir
for dir in \
/etc/systemd/system/dnscrypt-proxy.service.d \
/etc/systemd/system/dnscrypt-proxy.socket.d \
/etc/systemd/system/wg-quick@wg0.service.d \
/etc/systemd/system/strongswan-starter.service.d \
/etc/systemd/system/strongswan.service.d; do
if [[ -d "$dir" ]]; then
run_ignore_failure rmdir "$dir"
fi
done
}
main() {
parse_args "$@"
require_root_linux
if [[ -z "$BACKUP_DIR" ]]; then
BACKUP_DIR="/var/backups/algo-cleanup-${TIMESTAMP}"
fi
local marker_count
marker_count="$(detect_algo_markers)"
if (( marker_count == 0 && ! FORCE )); then
die "No Algo markers found. Re-run with --force if you still want cleanup."
fi
confirm_action "$marker_count"
create_backup
stop_disable_units
remove_cron_entries
reset_sshd_if_algo_managed
restore_pam_motd_entries
remove_privacy_bashrc_lines
remove_generated_bash_logout
restore_journald_conf
remove_af_key_persistence
remove_sysctl_keys
remove_algo_paths
restore_logrotate_default_if_needed
remove_algo_users_and_groups
purge_algo_packages
flush_firewall_rules
reset_iptables_alternatives
cleanup_empty_dropin_dirs
reload_runtime
log "Cleanup complete."
log "Backup directory: ${BACKUP_DIR}"
log "Review SSH/cloud firewall rules before disconnecting if sshd settings changed."
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment