Merge pull request #413 from lanedirt/412-add-update-option-to-install-script

Add update option to install script
This commit is contained in:
Leendert de Borst
2024-11-25 14:41:17 +01:00
committed by GitHub
6 changed files with 377 additions and 118 deletions

View File

@@ -32,14 +32,14 @@ jobs:
- name: Wait for services to be up
run: |
# Wait for a few seconds
sleep 10
- name: Test if localhost:443 (WASM app) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443)
sleep 15
- name: Test if localhost:443 (WASM app) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443)
if [ "$http_code" -ne 200 ]; then
echo "Service did not respond with 200 OK. Check if client app and/or nginx is configured correctly."
exit 1
@@ -47,13 +47,13 @@ jobs:
echo "Service responded with 200 OK"
fi
- name: Test if localhost:443/api (WebApi) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443/api)
- name: Test if localhost:443/api (WebApi) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443/api)
if [ "$http_code" -ne 200 ]; then
echo "Service did not respond with expected 200 OK. Check if WebApi and/or nginx is configured correctly."
exit 1
@@ -61,32 +61,32 @@ jobs:
echo "Service responded with $http_code"
fi
- name: Test if localhost:443/admin (Admin) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443/admin/user/login)
if [ "$http_code" -ne 200 ]; then
echo "Service did not respond with expected 200 OK. Check if admin app and/or nginx is configured correctly."
exit 1
else
echo "Service responded with $http_code"
fi
- name: Test if localhost:443/admin (Admin) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443/admin/user/login)
if [ "$http_code" -ne 200 ]; then
echo "Service did not respond with expected 200 OK. Check if admin app and/or nginx is configured correctly."
exit 1
else
echo "Service responded with $http_code"
fi
- name: Test if localhost:2525 (SmtpService) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
if ! nc -zv localhost 2525 2>&1 | grep -q 'succeeded'; then
echo "SmtpService did not respond on port 2525. Check if the SmtpService service is running."
exit 1
else
echo "SmtpService responded on port 2525"
fi
- name: Test if localhost:2525 (SmtpService) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
if ! nc -zv localhost 2525 2>&1 | grep -q 'succeeded'; then
echo "SmtpService did not respond on port 2525. Check if the SmtpService service is running."
exit 1
else
echo "SmtpService responded on port 2525"
fi
- name: Test install.sh reset-password output
run: |

View File

@@ -29,4 +29,12 @@ gh_edit_link_text: "Edit this page on GitHub."
gh_edit_repository: "https://github.com/lanedirt/AliasVault" # the github URL for your repo
gh_edit_branch: "main" # the branch that your docs is served from
gh_edit_source: docs # the source that your files originate from
gh_edit_view_mode: "tree" # "tree" or "edit" if you want the user to jump into the editor immediately
gh_edit_view_mode: "tree" # "tree" or "edit" if you want the user to jump into the editor immediately
callouts:
warning:
title: Warning
color: red
note:
title: Note
color: purple

View File

@@ -0,0 +1,30 @@
---
layout: default
title: Start/stop
parent: Installation Guide
nav_order: 3
---
# Starting and stopping AliasVault
You can start and stop AliasVault easily by using the install script.
## Stop
To stop AliasVault, run the install script with the `stop` option. This will stop all running AliasVault containers.
```bash
./install.sh stop
```
## Start
To start AliasVault, run the install script with the `start` option. This will start all AliasVault containers.
```bash
./install.sh start
```
## Restart
To restart AliasVault, run the install script with the `restart` option. This will restart all AliasVault containers.
```bash
./install.sh restart
```

View File

@@ -2,17 +2,18 @@
layout: default
title: Uninstall
parent: Installation Guide
nav_order: 3
nav_order: 5
---
# Uninstall
To uninstall AliasVault, run the install script with the `uninstall` option. This will stop and remove the AliasVault containers, remove the Docker images, and delete the .env file.
{: .note }
This will not delete any data stored in the database. If you wish to delete all data, you should manually delete the `database` directory and the other directories created by AliasVault.
### Steps
1. Run the install script with the `uninstall` option
```bash
./install.sh uninstall
```
> **Note:** This will not delete any data stored in the database. If you wish to delete all data, you should manually delete the `database` directory and the other directories created by AliasVault.
```

View File

@@ -0,0 +1,32 @@
---
layout: default
title: Update
parent: Installation Guide
nav_order: 4
---
# Updating AliasVault
To update AliasVault to the latest version, run the install script with the `update` option. This will pull the latest version of AliasVault from GitHub and restart all containers.
You can see the latest available version of AliasVault on [GitHub](https://github.com/lanedirt/AliasVault/releases).
{: .warning }
Before updating, it's recommended to backup your database and other important data. You can do this by making
a copy of the `database` and `certificates` directories.
## Updating to the latest available version
To update to the latest version, run the install script with the `update` option. The script will check for the latest version and prompt you to confirm the update. Follow the prompts to complete the update.
```bash
./install.sh update
```
## Installing a specific version
To install a specific version and skip the automatic version checks, run the install script with the `install` option and specify the version you want to install.
```bash
./install.sh install <version>
# Example:
./install.sh install 0.7.0
```

View File

@@ -37,11 +37,15 @@ show_usage() {
printf "Usage: $0 [COMMAND] [OPTIONS]\n"
printf "\n"
printf "Commands:\n"
printf " install Install AliasVault by pulling pre-built images from GitHub Container Registry (default)\n"
printf " build Build AliasVault from source (takes longer and requires sufficient specs)\n"
printf " reset-password Reset admin password\n"
printf " install Install AliasVault by pulling pre-built images from GitHub Container Registry (recommended)\n"
printf " uninstall Uninstall AliasVault\n"
printf " update Update AliasVault to the latest version\n"
printf " configure-ssl Configure SSL certificates (Let's Encrypt or self-signed)\n"
printf " start Start AliasVault containers\n"
printf " stop Stop AliasVault containers\n"
printf " restart Restart AliasVault containers\n"
printf " reset-password Reset admin password\n"
printf " build Build AliasVault from source (takes longer and requires sufficient specs)\n"
printf "\n"
printf "Options:\n"
@@ -52,38 +56,74 @@ show_usage() {
# Function to parse command line arguments
parse_args() {
COMMAND="" # Remove default command
COMMAND=""
VERBOSE=false
FORCE_YES=false
COMMAND_ARG=""
# Show usage if no arguments provided
if [ $# -eq 0 ]; then
show_usage
exit 0
fi
# First argument is always the command
case $1 in
install|i)
COMMAND="install"
shift
# Check for version argument
if [ $# -gt 0 ] && [[ ! "$1" =~ ^- ]]; then
COMMAND_ARG="$1"
shift
fi
;;
# Other commands remain unchanged
build|b)
COMMAND="build"
shift
;;
uninstall|u)
COMMAND="uninstall"
shift
;;
reset-password|reset-admin-password|rp)
COMMAND="reset-password"
shift
;;
configure-ssl|ssl)
COMMAND="configure-ssl"
shift
;;
start|s)
COMMAND="start"
shift
;;
stop|st)
COMMAND="stop"
shift
;;
restart|r)
COMMAND="restart"
shift
;;
update|up)
COMMAND="update"
shift
;;
--help)
show_usage
exit 0
;;
*)
echo "Unknown option: $1"
show_usage
exit 1
;;
esac
# Parse remaining flags
while [[ $# -gt 0 ]]; do
case $1 in
install|i)
COMMAND="install"
shift
;;
build|b)
COMMAND="build"
shift
;;
uninstall|u)
COMMAND="uninstall"
shift
;;
reset-password|reset-admin-password|rp)
COMMAND="reset-password"
shift
;;
configure-ssl|ssl)
COMMAND="configure-ssl"
shift
;;
--verbose)
VERBOSE=true
shift
@@ -92,10 +132,6 @@ parse_args() {
FORCE_YES=true
shift
;;
--help)
show_usage
exit 0
;;
*)
echo "Unknown option: $1"
show_usage
@@ -118,7 +154,7 @@ main() {
print_logo
case $COMMAND in
"install")
handle_install
handle_install "$COMMAND_ARG"
;;
"build")
handle_build
@@ -136,6 +172,18 @@ main() {
"configure-ssl")
handle_ssl_configuration
;;
"start")
handle_start
;;
"stop")
handle_stop
;;
"restart")
handle_restart
;;
"update")
handle_update
;;
esac
}
@@ -365,6 +413,16 @@ update_env_var() {
printf " ${GREEN}> $key has been set in $ENV_FILE.${NC}\n"
}
# Helper function to delete environment variables
delete_env_var() {
local key=$1
if [ -f "$ENV_FILE" ]; then
sed -i.bak "/^${key}=/d" "$ENV_FILE" && rm -f "$ENV_FILE.bak"
printf " ${GREEN}> $key has been removed from $ENV_FILE.${NC}\n"
fi
}
# Function to print success message
print_success_message() {
printf "\n"
@@ -434,56 +492,38 @@ get_docker_compose_command() {
echo "$base_command"
}
# Function to handle installation
# Function to handle initial installation or reinstallation
handle_install() {
printf "${YELLOW}+++ Installing AliasVault +++${NC}\n"
printf "\n"
local specified_version="$1"
# Initialize workspace which makes sure all required directories and files exist
initialize_workspace
# Initialize environment
create_env_file || { printf "${RED}> Failed to create .env file${NC}\n"; exit 1; }
populate_hostname || { printf "${RED}> Failed to set hostname${NC}\n"; exit 1; }
populate_jwt_key || { printf "${RED}> Failed to set JWT key${NC}\n"; exit 1; }
populate_data_protection_cert_pass || { printf "${RED}> Failed to set certificate password${NC}\n"; exit 1; }
set_private_email_domains || { printf "${RED}> Failed to set email domains${NC}\n"; exit 1; }
set_smtp_tls_enabled || { printf "${RED}> Failed to set SMTP TLS${NC}\n"; exit 1; }
set_support_email || { printf "${RED}> Failed to set support email${NC}\n"; exit 1; }
# Only generate admin password if not already set
if ! grep -q "^ADMIN_PASSWORD_HASH=" "$ENV_FILE" || [ -z "$(grep "^ADMIN_PASSWORD_HASH=" "$ENV_FILE" | cut -d '=' -f2)" ]; then
generate_admin_password || { printf "${RED}> Failed to generate admin password${NC}\n"; exit 1; }
# If version specified, install that version directly
if [ -n "$specified_version" ]; then
handle_install_version "$specified_version"
return
fi
# Pull images from GitHub Container Registry
printf "\n${YELLOW}+++ Pulling Docker images +++${NC}\n"
printf "\n"
# Check for existing version
local current_version=""
if grep -q "^ALIASVAULT_VERSION=" "$ENV_FILE"; then
current_version=$(grep "^ALIASVAULT_VERSION=" "$ENV_FILE" | cut -d '=' -f2)
printf "${CYAN}> Current AliasVault version: ${current_version}${NC}\n"
printf "${YELLOW}> AliasVault is already installed.${NC}\n"
printf "1. To reinstall the current version (${current_version}), continue with this script\n"
printf "2. To check for updates and to install the latest version, use: ./install.sh update\n"
printf "3. To install a specific version, use: ./install.sh install <version>\n"
printf "\n"
images=(
"${GITHUB_CONTAINER_REGISTRY}-reverse-proxy:latest"
"${GITHUB_CONTAINER_REGISTRY}-api:latest"
"${GITHUB_CONTAINER_REGISTRY}-client:latest"
"${GITHUB_CONTAINER_REGISTRY}-admin:latest"
"${GITHUB_CONTAINER_REGISTRY}-smtp:latest"
)
for image in "${images[@]}"; do
printf "${CYAN}> Pulling $image...${NC}\n"
if [ "$VERBOSE" = true ]; then
docker pull $image || { printf "${RED}> Failed to pull image: $image${NC}\n"; exit 1; }
else
docker pull $image > /dev/null 2>&1 || { printf "${RED}> Failed to pull image: $image${NC}\n"; exit 1; }
read -p "Would you like to reinstall the current version? [y/N]: " REPLY
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
printf "${YELLOW}> Installation cancelled.${NC}\n"
exit 0
fi
done
# Start containers
printf "\n${YELLOW}+++ Starting services +++${NC}\n"
printf "\n"
recreate_docker_containers
# Only show success message if we made it here without errors
print_success_message
handle_install_version "$current_version"
else
# First time installation, use latest
handle_install_version "latest"
fi
}
# Function to handle build
@@ -594,6 +634,9 @@ handle_uninstall() {
fi
printf "${GREEN}> Docker containers stopped and removed.${NC}\n"
# Remove version from .env
delete_env_var "ALIASVAULT_VERSION" ""
printf "${CYAN}> Removing Docker images...${NC}\n"
if [ "$VERBOSE" = true ]; then
docker compose -f docker-compose.yml down --rmi all || {
@@ -814,4 +857,149 @@ generate_self_signed_cert() {
printf "${GREEN}> New self-signed certificate has been generated successfully!${NC}\n"
}
# New functions to handle container lifecycle:
handle_start() {
printf "${CYAN}> Starting AliasVault containers...${NC}\n"
$(get_docker_compose_command) up -d
printf "${GREEN}> AliasVault containers started successfully.${NC}\n"
}
handle_stop() {
printf "${CYAN}> Stopping AliasVault containers...${NC}\n"
if ! docker compose ps --quiet 2>/dev/null | grep -q .; then
printf "${YELLOW}> No containers are currently running.${NC}\n"
exit 0
fi
$(get_docker_compose_command) down
printf "${GREEN}> AliasVault containers stopped successfully.${NC}\n"
}
handle_restart() {
printf "${CYAN}> Restarting AliasVault containers...${NC}\n"
$(get_docker_compose_command) down
$(get_docker_compose_command) up -d
printf "${GREEN}> AliasVault containers restarted successfully.${NC}\n"
}
# Function to handle updates
handle_update() {
printf "${YELLOW}+++ Checking for AliasVault updates +++${NC}\n"
printf "\n"
# Check current version
if ! grep -q "^ALIASVAULT_VERSION=" "$ENV_FILE"; then
printf "${YELLOW}> No version information found. Running first-time update check...${NC}\n"
handle_install_version "latest"
return
fi
current_version=$(grep "^ALIASVAULT_VERSION=" "$ENV_FILE" | cut -d '=' -f2)
latest_version=$(curl -s "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
if [ -z "$latest_version" ]; then
printf "${RED}> Failed to check for updates. Please try again later.${NC}\n"
exit 1
fi
printf "${CYAN}> Current version: ${current_version}${NC}\n"
printf "${CYAN}> Latest version: ${latest_version}${NC}\n"
printf "\n"
if [ "$current_version" = "$latest_version" ]; then
printf "${GREEN}> You are already running the latest version of AliasVault!${NC}\n"
exit 0
fi
printf "${YELLOW}> A new version of AliasVault is available!${NC}\n"
printf "\n"
printf "${MAGENTA}Important:${NC}\n"
printf "1. It's recommended to backup your database before updating\n"
printf "2. The update process will restart all containers\n"
printf "\n"
read -p "Would you like to update to the latest version? [y/N]: " REPLY
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
printf "${YELLOW}> Update cancelled.${NC}\n"
exit 0
fi
printf "${CYAN}> Updating AliasVault...${NC}\n"
handle_install_version "$latest_version"
printf "${GREEN}> Update completed successfully!${NC}\n"
}
# Function to perform the actual installation with specific version
handle_install_version() {
local target_version="$1"
# If latest, get actual version number from GitHub API
if [ "$target_version" = "latest" ]; then
local actual_version=$(curl -s "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
if [ -n "$actual_version" ]; then
target_version="$actual_version"
fi
fi
printf "${YELLOW}+++ Installing AliasVault ${target_version} +++${NC}\n"
printf "\n"
# Initialize workspace which makes sure all required directories and files exist
initialize_workspace
# Initialize environment
create_env_file || { printf "${RED}> Failed to create .env file${NC}\n"; exit 1; }
populate_hostname || { printf "${RED}> Failed to set hostname${NC}\n"; exit 1; }
populate_jwt_key || { printf "${RED}> Failed to set JWT key${NC}\n"; exit 1; }
populate_data_protection_cert_pass || { printf "${RED}> Failed to set certificate password${NC}\n"; exit 1; }
set_private_email_domains || { printf "${RED}> Failed to set email domains${NC}\n"; exit 1; }
set_smtp_tls_enabled || { printf "${RED}> Failed to set SMTP TLS${NC}\n"; exit 1; }
set_support_email || { printf "${RED}> Failed to set support email${NC}\n"; exit 1; }
# Only generate admin password if not already set
if ! grep -q "^ADMIN_PASSWORD_HASH=" "$ENV_FILE" || [ -z "$(grep "^ADMIN_PASSWORD_HASH=" "$ENV_FILE" | cut -d '=' -f2)" ]; then
generate_admin_password || { printf "${RED}> Failed to generate admin password${NC}\n"; exit 1; }
fi
# Pull images from GitHub Container Registry
printf "\n${YELLOW}+++ Pulling Docker images +++${NC}\n"
printf "\n"
printf "${CYAN}> Installing version: ${target_version}${NC}\n"
local tag="$target_version"
if [ "$target_version" = "latest" ]; then
tag="latest"
fi
images=(
"${GITHUB_CONTAINER_REGISTRY}-reverse-proxy:${tag}"
"${GITHUB_CONTAINER_REGISTRY}-api:${tag}"
"${GITHUB_CONTAINER_REGISTRY}-client:${tag}"
"${GITHUB_CONTAINER_REGISTRY}-admin:${tag}"
"${GITHUB_CONTAINER_REGISTRY}-smtp:${tag}"
)
for image in "${images[@]}"; do
printf "${CYAN}> Pulling $image...${NC}\n"
if [ "$VERBOSE" = true ]; then
docker pull $image || { printf "${RED}> Failed to pull image: $image${NC}\n"; exit 1; }
else
docker pull $image > /dev/null 2>&1 || { printf "${RED}> Failed to pull image: $image${NC}\n"; exit 1; }
fi
done
# Save version to .env
update_env_var "ALIASVAULT_VERSION" "$target_version"
# Start containers
printf "\n${YELLOW}+++ Starting services +++${NC}\n"
printf "\n"
recreate_docker_containers
# Only show success message if we made it here without errors
print_success_message
}
main "$@"