From 85fbb283c3e868e20ed15128d79e4e8d077b75fd Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Fri, 26 Jul 2024 11:24:56 +0200 Subject: [PATCH] Add uninstall.sh script (#113) --- install.sh | 172 +++++++++++++++++++-------------------------------- uninstall.sh | 108 ++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+), 110 deletions(-) create mode 100755 uninstall.sh diff --git a/install.sh b/install.sh index fd20fde4c..b450739e1 100755 --- a/install.sh +++ b/install.sh @@ -39,58 +39,38 @@ parse_args() { # Function to generate a random admin password and store its hash in the .env file generate_admin_password() { if grep -q "^ADMIN_PASSWORD_HASH=" ".env" && [ "$RESET_PASSWORD" = false ]; then - printf "${CYAN}> ADMIN_PASSWORD_HASH already exists in .env. Use --reset-password to generate a new one.${NC}\n" + printf "${CYAN}> Checking admin password...${NC}\n" + printf "${GREEN}> ADMIN_PASSWORD_HASH already exists in .env. Use --reset-password to generate a new one.${NC}\n" return 0 fi printf "${CYAN}> Generating new admin password...${NC}\n" ADMIN_PASSWORD=$(openssl rand -base64 12) - printf "${BLUE} Building Docker image for password generation:${NC} " + printf "${CYAN}> Building Docker image for password generation...${NC}\n" if [ "$VERBOSE" = true ]; then docker build -t initcli -f src/Utilities/InitializationCLI/Dockerfile . else - ( - # Run docker build and capture its output - docker build -t initcli -f src/Utilities/InitializationCLI/Dockerfile . > install_build_output.log 2>&1 & - BUILD_PID=$! + docker build -t initcli -f src/Utilities/InitializationCLI/Dockerfile . > install_build_output.log 2>&1 + fi + BUILD_EXIT_CODE=$? - # Print dots while the build is running - while kill -0 $BUILD_PID 2>/dev/null; do - printf "." - sleep 1 - done - - # Wait for the build to finish and capture its exit code - wait $BUILD_PID - BUILD_EXIT_CODE=$? - - # If there was an error, display it - if [ $BUILD_EXIT_CODE -ne 0 ]; then - printf "\n${RED} An error occurred while building the Docker image for password generation. Check the output above.${NC}\n" - printf "\n" - cat install_build_output.log - exit $BUILD_EXIT_CODE - fi - ) - - SUBSHELL_EXIT_CODE=$? - if [ $SUBSHELL_EXIT_CODE -ne 0 ]; then - return $SUBSHELL_EXIT_CODE - fi + if [ $BUILD_EXIT_CODE -ne 0 ]; then + printf "${RED}> An error occurred while building the Docker image for password generation. Check install_build_output.log for details.${NC}\n" + exit $BUILD_EXIT_CODE fi - printf "\n" - printf "${BLUE} Running Docker container to generate admin password hash: ${NC}" + printf "${GREEN}> Docker image built successfully.${NC}\n" + + printf "${CYAN}> Running Docker container to generate admin password hash...${NC}\n" # Run the Docker container to generate the password hash ADMIN_PASSWORD_HASH=$(docker run --rm initcli "$ADMIN_PASSWORD" 2> install_run_output.log) RUN_EXIT_CODE=$? if [ $RUN_EXIT_CODE -ne 0 ]; then - printf "${RED} Error occurred while running the Docker container:${NC}\n" - cat install_run_output.log + printf "${RED}> Error occurred while running the Docker container. Check install_run_output.log for details.${NC}\n" return $RUN_EXIT_CODE fi @@ -102,11 +82,9 @@ generate_admin_password() { echo "ADMIN_PASSWORD_HASH=$ADMIN_PASSWORD_HASH" >> .env echo "ADMIN_PASSWORD_GENERATED=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> .env - printf " ok\n" - printf "${CYAN}> New admin password generated and hash stored in .env${NC}\n" + printf "${GREEN}> New admin password generated and hash stored in .env${NC}\n" } - # Function to restart Docker containers restart_docker_containers() { printf "${CYAN}> Restarting Docker containers...${NC}\n" @@ -122,6 +100,7 @@ generate_jwt_key() { # Function to create .env file from .env.example if it doesn't exist create_env_file() { + printf "${CYAN}> Creating .env file...${NC}\n" if [ ! -f "$ENV_FILE" ]; then if [ -f "$ENV_EXAMPLE_FILE" ]; then cp "$ENV_EXAMPLE_FILE" "$ENV_FILE" @@ -131,46 +110,48 @@ create_env_file() { printf "${YELLOW}> .env file created as empty because .env.example was not found.${NC}\n" fi else - printf "${CYAN}> .env file already exists.${NC}\n" + printf "${GREEN}> .env file already exists.${NC}\n" fi } # Function to check and populate the .env file with JWT_KEY populate_jwt_key() { + printf "${CYAN}> Checking JWT_KEY...${NC}\n" if ! grep -q "^JWT_KEY=" "$ENV_FILE" || [ -z "$(grep "^JWT_KEY=" "$ENV_FILE" | cut -d '=' -f2)" ]; then - printf "${YELLOW}JWT_KEY not found or empty in $ENV_FILE. Generating a new JWT key...${NC}\n" JWT_KEY=$(generate_jwt_key) if grep -q "^JWT_KEY=" "$ENV_FILE"; then awk -v key="$JWT_KEY" '/^JWT_KEY=/ {$0="JWT_KEY="key} 1' "$ENV_FILE" > "$ENV_FILE.tmp" && mv "$ENV_FILE.tmp" "$ENV_FILE" else - printf "JWT_KEY=${JWT_KEY}" >> "$ENV_FILE\n" + echo "JWT_KEY=${JWT_KEY}" >> "$ENV_FILE" fi - printf "${GREEN}> JWT_KEY has been added to $ENV_FILE.${NC}\n" + printf "${GREEN}> JWT_KEY has been generated and added to $ENV_FILE.${NC}\n" else - printf "${CYAN}> JWT_KEY already exists and has a value in $ENV_FILE.${NC}\n" + printf "${GREEN}> JWT_KEY already exists and has a value in $ENV_FILE.${NC}\n" fi } # Function to ask the user for SMTP_ALLOWED_DOMAINS set_smtp_allowed_domains() { + printf "${CYAN}> Setting SMTP_ALLOWED_DOMAINS...${NC}\n" if ! grep -q "^SMTP_ALLOWED_DOMAINS=" "$ENV_FILE" || [ -z "$(grep "^SMTP_ALLOWED_DOMAINS=" "$ENV_FILE" | cut -d '=' -f2)" ]; then - printf "${YELLOW}Please enter the domains that should be allowed to send email, separated by commas:${NC}\n" + printf "Please enter the domains that should be allowed to send email, separated by commas: " read -r smtp_allowed_domains if grep -q "^SMTP_ALLOWED_DOMAINS=" "$ENV_FILE"; then awk -v domains="$smtp_allowed_domains" '/^SMTP_ALLOWED_DOMAINS=/ {$0="SMTP_ALLOWED_DOMAINS="domains} 1' "$ENV_FILE" > "$ENV_FILE.tmp" && mv "$ENV_FILE.tmp" "$ENV_FILE" else - printf "SMTP_ALLOWED_DOMAINS=${smtp_allowed_domains}\n" >> "$ENV_FILE" + echo "SMTP_ALLOWED_DOMAINS=${smtp_allowed_domains}" >> "$ENV_FILE" fi printf "${GREEN}> SMTP_ALLOWED_DOMAINS has been set in $ENV_FILE.${NC}\n" else - printf "${CYAN}> SMTP_ALLOWED_DOMAINS already exists and has a value in $ENV_FILE.${NC}\n" + printf "${GREEN}> SMTP_ALLOWED_DOMAINS already exists and has a value in $ENV_FILE.${NC}\n" fi } # Function to ask the user if TLS should be enabled for email set_smtp_tls_enabled() { + printf "${CYAN}> Setting SMTP_TLS_ENABLED...${NC}\n" if ! grep -q "^SMTP_TLS_ENABLED=" "$ENV_FILE" || [ -z "$(grep "^SMTP_TLS_ENABLED=" "$ENV_FILE" | cut -d '=' -f2)" ]; then - printf "${YELLOW}Do you want TLS enabled for email? (yes/no):${NC}\n" + printf "Do you want TLS enabled for email? (yes/no): " read -r tls_enabled tls_enabled=$(echo "$tls_enabled" | tr '[:upper:]' '[:lower:]') if [ "$tls_enabled" = "yes" ] || [ "$tls_enabled" = "y" ]; then @@ -181,24 +162,23 @@ set_smtp_tls_enabled() { if grep -q "^SMTP_TLS_ENABLED=" "$ENV_FILE"; then awk -v tls="$tls_enabled" '/^SMTP_TLS_ENABLED=/ {$0="SMTP_TLS_ENABLED="tls} 1' "$ENV_FILE" > "$ENV_FILE.tmp" && mv "$ENV_FILE.tmp" "$ENV_FILE" else - printf "SMTP_TLS_ENABLED=${tls_enabled}\n" >> "$ENV_FILE" + echo "SMTP_TLS_ENABLED=${tls_enabled}" >> "$ENV_FILE" fi printf "${GREEN}> SMTP_TLS_ENABLED has been set to ${tls_enabled} in $ENV_FILE.${NC}\n" else - printf "${CYAN}> SMTP_TLS_ENABLED already exists and has a value in $ENV_FILE.${NC}\n" + printf "${GREEN}> SMTP_TLS_ENABLED already exists and has a value in $ENV_FILE.${NC}\n" fi } # Function to build and run the Docker Compose stack with muted output unless an error occurs, showing progress indication build_and_run_docker_compose() { - printf "\n" - printf "${CYAN}> Building Docker Compose stack:${NC} " + printf "${CYAN}> Building Docker Compose stack..." if [ "$VERBOSE" = true ]; then docker-compose build else ( # Run docker-compose build and capture its output - docker-compose build 2>&1 > install_compose_build_output.log & + docker-compose build > install_compose_build_output.log 2>&1 & BUILD_PID=$! # Print dots while the build is running @@ -207,63 +187,36 @@ build_and_run_docker_compose() { sleep 1 done + printf "${NC}" + # Wait for the build to finish and capture its exit code wait $BUILD_PID BUILD_EXIT_CODE=$? # If there was an error, display it if [ $BUILD_EXIT_CODE -ne 0 ]; then - printf "\n${RED}An error occurred while building the Docker Compose stack. See the output above.${NC}\n" - printf "\n" - cat install_compose_build_output.log + printf "\n${RED}> An error occurred while building the Docker Compose stack. Check install_compose_build_output.log for details.${NC}\n" exit $BUILD_EXIT_CODE fi ) - - # Capture the exit code of the subshell - SUBSHELL_EXIT_CODE=$? - if [ $SUBSHELL_EXIT_CODE -ne 0 ]; then - return $SUBSHELL_EXIT_CODE - fi fi - printf "\n" - printf "${CYAN}> Starting Docker Compose stack:${NC}\n" + printf "\n${GREEN}> Docker Compose stack built successfully.${NC}\n" + + printf "${CYAN}> Starting Docker Compose stack...${NC}\n" if [ "$VERBOSE" = true ]; then - docker-compose up -d - return $? - else - ( - # Run docker-compose up -d and capture its output - docker-compose up -d & - UP_PID=$! - - # Wait for the process to finish and capture its exit code - wait $UP_PID - UP_EXIT_CODE=$? - - # If there was an error, display it - if [ $UP_EXIT_CODE -ne 0 ]; then - printf "\n${RED}An error occurred while starting the Docker Compose stack. See the output above.${NC}\n" - printf "\n" - cat install_compose_up_output.log - exit $UP_EXIT_CODE - fi - ) - - # Capture the exit code of the subshell - SUBSHELL_EXIT_CODE=$? - if [ $SUBSHELL_EXIT_CODE -ne 0 ]; then - return $SUBSHELL_EXIT_CODE - fi + docker-compose up -d + else + docker-compose up -d > install_compose_up_output.log 2>&1 fi -} + UP_EXIT_CODE=$? -# Function to restart Docker containers -restart_docker_containers() { - printf "${CYAN}> Restarting Docker containers...${NC}\n" - docker-compose up -d --no-deps --force-recreate - printf "${GREEN}> Docker containers restarted successfully.${NC}\n" + if [ $UP_EXIT_CODE -ne 0 ]; then + printf "${RED}> An error occurred while starting the Docker Compose stack. Check install_compose_up_output.log for details.${NC}\n" + exit $UP_EXIT_CODE + fi + + printf "${GREEN}> Docker Compose stack started successfully.${NC}\n" } # Function to print the CLI logo @@ -277,6 +230,7 @@ print_logo() { printf " / ____ \| | | (_| \__ \\ / (_| | |_| | | |_ \n" printf " /_/ \_\_|_|\__,_|___/ \/ \__,_|\__,_|_|\__|\n" printf "\n" + printf " Install Script\n" printf "=========================================================\n" printf "${NC}\n" } @@ -303,40 +257,38 @@ main() { set_smtp_tls_enabled || exit $? generate_admin_password || exit $? printf "\n${YELLOW}+++ Building Docker containers +++${NC}\n" - + printf "\n" build_and_run_docker_compose || exit $? printf "\n" printf "${MAGENTA}=========================================================${NC}\n" printf "\n" - printf "AliasVault is successfully installed!\n" + printf "${GREEN}AliasVault is successfully installed!${NC}\n" printf "\n" - printf "To configure the server, login to the admin panel:\n" + printf "${CYAN}To configure the server, login to the admin panel:${NC}\n" printf "\n" if [ "$ADMIN_PASSWORD" != "" ]; then - printf "${CYAN}Admin Panel: http://localhost:8080/${NC}\n" - printf "${CYAN}Username: admin${NC}\n" - printf "${CYAN}Password: $ADMIN_PASSWORD${NC}\n" + printf "Admin Panel: http://localhost:8080/\n" + printf "Username: admin\n" + printf "Password: $ADMIN_PASSWORD\n" printf "\n" - printf "(!) Caution: Make sure to backup the above credentials in a safe place, they won't be shown again!\n" + printf "${YELLOW}(!) Caution: Make sure to backup the above credentials in a safe place, they won't be shown again!${NC}\n" printf "\n" else - printf "${CYAN}Admin Panel: http://localhost:8080/${NC}\n" - printf "${CYAN}Username: admin${NC}\n" - printf "${CYAN}Password: (Previously set. Run this command with --reset-password to generate a new one.)${NC}\n" - printf "\n" + printf "Admin Panel: http://localhost:8080/\n" + printf "Username: admin\n" + printf "Password: (Previously set. Run this command with --reset-password to generate a new one.)\n" printf "\n" fi - printf "===========================\n" + printf "${CYAN}===========================${NC}\n" printf "\n" - printf "In order to start using AliasVault and create your own vault, log into the client website:\n" + printf "${CYAN}In order to start using AliasVault and create your own vault, log into the client website:${NC}\n" printf "\n" - printf "${CYAN}Client Website: http://localhost:80/${NC}\n" - printf "${CYAN}You can create your own account from there.${NC}\n" + printf "Client Website: http://localhost:80/\n" + printf "You can create your own account from there.\n" printf "\n" + printf "${MAGENTA}=========================================================${NC}\n" fi } # Run the main function main "$@" - - diff --git a/uninstall.sh b/uninstall.sh new file mode 100755 index 000000000..963b978f1 --- /dev/null +++ b/uninstall.sh @@ -0,0 +1,108 @@ +#!/bin/sh + +# Define colors for CLI output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +MAGENTA='\033[0;35m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# Define verbose flag +VERBOSE=false + +# Function to parse command-line arguments +parse_args() { + while [ $# -gt 0 ]; do + case "$1" in + --verbose) + VERBOSE=true + ;; + *) + printf "${RED}Unknown argument: $1${NC}\n" + exit 1 + ;; + esac + shift + done +} + +# Function to print the CLI logo +print_logo() { + printf "${MAGENTA}\n" + printf "=========================================================\n" + printf " _ _ __ __ _ _ \n" + printf " /\ | (_) \ \ / / | | | \n" + printf " / \ | |_ __ _ __\ \ / /_ _ _ _| | |_\n" + printf " / /\ \ | | |/ _ / __\ \/ / _ | | | | | __|\n" + printf " / ____ \| | | (_| \__ \\ / (_| | |_| | | |_ \n" + printf " /_/ \_\_|_|\__,_|___/ \/ \__,_|\__,_|_|\__|\n" + printf "\n" + printf " Uninstall Script\n" + printf "=========================================================\n" + printf "${NC}\n" +} + +# Function to stop and remove Docker containers +stop_and_remove_containers() { + printf "${CYAN}> Stopping and removing Docker containers...${NC}\n" + if [ "$VERBOSE" = true ]; then + docker-compose down -v + else + docker-compose down -v > /dev/null 2>&1 + fi + printf "${GREEN}> Docker containers stopped and removed.${NC}\n" +} + +# Function to remove Docker images +remove_docker_images() { + printf "${CYAN}> Removing Docker images...${NC}\n" + if [ "$VERBOSE" = true ]; then + docker-compose down --rmi all + else + docker-compose down --rmi all > /dev/null 2>&1 + fi + printf "${GREEN}> Docker images removed.${NC}\n" +} + +# Function to prune Docker system +prune_docker_system() { + printf "${CYAN}> Pruning Docker system...${NC}\n" + if [ "$VERBOSE" = true ]; then + docker system prune -af + else + docker system prune -af > /dev/null 2>&1 + fi + printf "${GREEN}> Docker system pruned.${NC}\n" +} + +# Main execution flow +main() { + parse_args "$@" + print_logo + + printf "${YELLOW}+++ Uninstalling AliasVault +++${NC}\n" + printf "\n" + + stop_and_remove_containers + remove_docker_images + prune_docker_system + + printf "\n" + printf "${MAGENTA}=========================================================${NC}\n" + printf "\n" + printf "AliasVault has been successfully uninstalled!\n" + printf "\n" + printf "All Docker containers and images related to AliasVault have been removed.\n" + printf "The current directory, including logs and .env files, has been left intact.\n" + printf "\n" + printf "If you wish to remove the remaining files, you can do so manually.\n" + printf "\n" + printf "Thank you for using AliasVault!\n" + printf "\n" + printf "${MAGENTA}=========================================================${NC}\n" +} + +# Run the main function +main "$@"