lib/kitsune/kit/commands/setup_unattended.rb
require "thor" require "net/ssh" require_relative "../defaults" require_relative "../options_builder" module Kitsune module Kit module Commands class SetupUnattended < Thor namespace "setup_unattended" class_option :server_ip, aliases: "-s", required: true, desc: "Server IP address or hostname" class_option :ssh_port, aliases: "-p", desc: "SSH port" class_option :ssh_key_path, aliases: "-k", desc: "Path to your private SSH key" desc "create", "Configure unattended-upgrades on the remote server" def create filled_options = Kitsune::Kit::OptionsBuilder.build( options, required: [:server_ip], defaults: Kitsune::Kit::Defaults.ssh ) with_ssh_connection(filled_options) do |ssh| perform_setup(ssh) end end desc "rollback", "Revert unattended-upgrades configuration on the remote server" def rollback filled_options = Kitsune::Kit::OptionsBuilder.build( options, required: [:server_ip], defaults: Kitsune::Kit::Defaults.ssh ) with_ssh_connection(filled_options) do |ssh| perform_rollback(ssh) end end no_commands do def with_ssh_connection(filled_options) server = filled_options[:server_ip] port = filled_options[:ssh_port] key = File.expand_path(filled_options[:ssh_key_path]) say "🔑 Connecting as deploy@#{server}:#{port}", :green Net::SSH.start(server, "deploy", port: port, keys: [key], non_interactive: true, timeout: 5) do |ssh| yield ssh end end def perform_setup(ssh) output = ssh.exec! <<~EOH set -e sudo mkdir -p /usr/local/backups sudo chown deploy:deploy /usr/local/backups RESOURCE="/etc/apt/apt.conf.d/20auto-upgrades" BACKUP_DIR="/usr/local/backups" SCRIPT_ID="setup_unattended" BACKUP_FILE="${BACKUP_DIR}/${SCRIPT_ID}.before" MARKER_FILE="${BACKUP_DIR}/${SCRIPT_ID}.after" echo "✍🏻 Installing required packages…" if ! dpkg -l | grep -q "^ii\\s*unattended-upgrades"; then sudo apt-get update -y sudo apt-get install -y unattended-upgrades apt-listchanges && echo " - packages installed" else echo " - unattended-upgrades already installed" fi if [ ! -f "$MARKER_FILE" ]; then echo "✍🏻 Backing up existing config…" sudo cp "$RESOURCE" "$BACKUP_FILE" && echo " - backup saved to $BACKUP_FILE" sudo touch "$MARKER_FILE" && echo " - marker created at $MARKER_FILE" else echo " - backup & marker already exist" fi echo "✍🏻 Applying new auto-upgrades config…" sudo tee "$RESOURCE" > /dev/null <<UPGR APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Download-Upgradeable-Packages "1"; APT::Periodic::AutocleanInterval "7"; APT::Periodic::Unattended-Upgrade "1"; UPGR echo " - config applied" echo "✍🏻 Enabling & restarting unattended-upgrades…" sudo systemctl --quiet enable unattended-upgrades.service >/dev/null 2>&1 && echo " - service enabled" sudo systemctl --quiet restart unattended-upgrades.service && echo " - service restarted" EOH say output say "✅ Unattended-upgrades setup completed", :green end def perform_rollback(ssh) output = ssh.exec! <<~EOH set -e sudo mkdir -p /usr/local/backups sudo chown deploy:deploy /usr/local/backups RESOURCE="/etc/apt/apt.conf.d/20auto-upgrades" BACKUP_DIR="/usr/local/backups" SCRIPT_ID="setup_unattended" BACKUP_FILE="${BACKUP_DIR}/${SCRIPT_ID}.before" MARKER_FILE="${BACKUP_DIR}/${SCRIPT_ID}.after" if [ -f "$MARKER_FILE" ]; then echo "🔁 Restoring original auto-upgrades config…" sudo mv "$BACKUP_FILE" "$RESOURCE" && echo " - config restored from $BACKUP_FILE" sudo rm -f "$MARKER_FILE" && echo " - marker $MARKER_FILE removed" else echo " - no marker for $SCRIPT_ID, skipping restore" fi echo "✍🏻 Stopping & disabling unattended-upgrades…" sudo systemctl --quiet stop unattended-upgrades.service apt-daily.timer apt-daily-upgrade.timer && echo " - services stopped" sudo systemctl --quiet disable unattended-upgrades.service && echo " - service disabled" EOH say output say "✅ Unattended-upgrades rollback completed", :green end end end end end end