octojoom/src/octojoom

5392 lines
203 KiB
Bash
Executable File

#!/bin/bash
# The most recent program version.
_VERSION="3.4.6"
_V="3.4"
# The program full name
PROGRAM_NAME="Octojoom"
# Set Server Hostname
SERVER_HOSTNAME="$(hostname)"
# Set the back title
BACK_TITLE=" Octoleo | ${USER}@${SERVER_HOSTNAME}"
# make sure whiptail is installed
command -v whiptail >/dev/null 2>&1 || {
echo >&2 "ERROR: ${PROGRAM_NAME} v${_VERSION} script require whiptail."
exit 1
}
# make sure curl is installed
command -v curl >/dev/null 2>&1 || {
echo >&2 "ERROR: ${PROGRAM_NAME} v${_VERSION} script require curl."
exit 1
}
# make sure awk is installed
command -v awk >/dev/null 2>&1 || {
echo >&2 "ERROR: ${PROGRAM_NAME} v${_VERSION} script require awk."
exit 1
}
# Check if Docker is installed.
if ! command -v docker &>/dev/null; then
# If Docker is not installed, ask the user if they want to install it.
if whiptail --yesno "Docker is not installed. Do you want to install it now?" \
--backtitle "${BACK_TITLE}" 10 60; then
# If the user chooses Yes, install Docker.
echo "Installing Docker..."
# Add Docker GPG key and repository to sources.list.
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Update package index and install Docker.
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io -y
# Add the current user to the docker group.
sudo groupadd docker
sudo usermod -aG docker "$USER"
# Enable and start the Docker service.
sudo systemctl enable docker.service
sudo systemctl start docker.service
echo "Docker is installed."
else
# If the user chooses No, exit the script with an error message.
echo >&2 "ERROR: ${PROGRAM_NAME} v${_VERSION} script require docker."
exit 1
fi
fi
# Check if Docker Compose is installed.
if ! command -v docker-compose &>/dev/null; then
# If Docker Compose is not installed, ask the user if they want to install it.
if whiptail --yesno "Docker Compose is not installed. Do you want to install it now?" \
--backtitle "${BACK_TITLE}" 10 60; then
# If the user chooses Yes, install Docker Compose.
echo "Installing Docker Compose..."
# Download the latest Docker Compose binary.
COMPOSE_VERSION=$(curl --silent https://api.github.com/repos/docker/compose/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
sudo curl -SL "https://github.com/docker/compose/releases/download/$COMPOSE_VERSION/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# Make the Docker Compose binary executable.
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
echo "Docker Compose is installed."
else
# If the user chooses No, exit the script with an error message.
echo >&2 "ERROR: ${PROGRAM_NAME} v${_VERSION} script require docker-compose."
exit 1
fi
fi
# just clear the screen
clear
#####################################################################################################################VDM
######################################## The main method
function main() {
# we check if we have a type and a task
# we use the __TRuST__ convention AS "PUBLIC METHODS" to avoid wrong calls, and hide other functions
if [ ${#VDM_CONTAINER_TYPE} -ge 1 ] && [ ${#VDM_TASK} -ge 1 ] && isFunc "${VDM_CONTAINER_TYPE}__TRuST__${VDM_TASK}"; then
"${VDM_CONTAINER_TYPE}__TRuST__${VDM_TASK}"
else
mainMenu
fi
}
#####################################################################################################################VDM
######################################## SETUP TRAEFIK
function traefik__TRuST__setup() {
# load this container type globals
# shellcheck disable=SC1090
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && source "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
# check if we have secure switch set
setSecureState
# setup letsencrypt stuff
if $VDM_SECURE; then
VDM_REMOVE_SECURE=''
VDM_HTTP_SCHEME="https"
# get the email if not set
while [ ${#VDM_SECURE_EMAIL} -le 1 ]; do
# get the value
VDM_SECURE_EMAIL=$(getInput 'Enter email for the Letsencrypt setup.' '' 'Enter Valid Email')
# keep asking
[ ${#VDM_SECURE_EMAIL} -ge 1 ] || {
showError "You must enter an email for the Letsencrypt setup."
}
done
# make sure the directory exist
mkdir -p "${VDM_PROJECT_PATH}/traefik"
# we must create this, else docker creates a folder
echo "{}" > "${VDM_PROJECT_PATH}/traefik/acme.json"
# make sure the permission are good
sudo chmod 600 "${VDM_PROJECT_PATH}/traefik/acme.json"
# and is owned by root
sudo chown -R root:root "${VDM_PROJECT_PATH}/traefik"
else
VDM_REMOVE_SECURE="#"
VDM_HTTP_SCHEME="http"
fi
# set the main domain if not set
setMainDomain
##########################
### export all we need
# global
export VDM_CONTAINER_TYPE
export VDM_REPO_PATH
export VDM_PROJECT_PATH
# container
export VDM_REMOVE_SECURE
export VDM_HTTP_SCHEME
export VDM_SECURE_EMAIL
## create the directory if it does not yet already exist
# shellcheck disable=SC2174
mkdir -p -m 700 "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}"
## place this docker composer file in its place
traefikContainer >"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml"
## set permissions
chmod 600 "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml"
# saved the file
showNotice "Saved ${VDM_CONTAINER_TYPE}:docker-compose.yml file.\nSetup of this container is complete!"
# ask if we should continue to enable
if (whiptail --yesno "Would you also like to enable this ${VDM_CONTAINER_TYPE^} container" --defaultno \
--title "Enable Container" --backtitle "${BACK_TITLE}" 8 112); then
enableContainer "${VDM_CONTAINER_TYPE}"
fi
##########################
### unset all no longer needed
# container
unset VDM_REMOVE_SECURE
unset VDM_HTTP_SCHEME
unset VDM_SECURE_EMAIL
# return a success
return 0
}
# return the Traefik Container setup yml
function traefikContainer() {
# we build the yml file
cat <<EOF
version: "3.3"
services:
traefik:
container_name: traefik
image: "traefik:latest"
command:
${VDM_REMOVE_SECURE} - --entrypoints.web.address=:80
${VDM_REMOVE_SECURE} - --entrypoints.websecure.address=:443
# - --api.dashboard=true
# - --api.insecure=true
- --providers.docker
${VDM_REMOVE_SECURE} - --log.level=INFO
${VDM_REMOVE_SECURE} - --certificatesresolvers.vdmresolver.acme.httpchallenge=true
${VDM_REMOVE_SECURE} - --certificatesresolvers.vdmresolver.acme.keytype=RSA4096
${VDM_REMOVE_SECURE} - --certificatesresolvers.vdmresolver.acme.email=${VDM_SECURE_EMAIL:-user@demo.com}
${VDM_REMOVE_SECURE} - --certificatesresolvers.vdmresolver.acme.storage=/acme.json
${VDM_REMOVE_SECURE} - --certificatesresolvers.vdmresolver.acme.httpchallenge.entrypoint=web
${VDM_REMOVE_SECURE} - --providers.file.directory=/conf
${VDM_REMOVE_SECURE} - --providers.file.watch=true
restart: unless-stopped
ports:
- "80:80"
- "443:443"
# - "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
${VDM_REMOVE_SECURE} - "\${VDM_PROJECT_PATH}/traefik/conf:/conf"
${VDM_REMOVE_SECURE} - "\${VDM_PROJECT_PATH}/traefik/acme.json:/acme.json"
${VDM_REMOVE_SECURE} - "\${VDM_PROJECT_PATH}/traefik/errors:/errors"
${VDM_REMOVE_SECURE} labels:
# settings for all containers
${VDM_REMOVE_SECURE} - "traefik.http.routers.http-catchall.rule=hostregexp(\`{host:.+}\`)"
${VDM_REMOVE_SECURE} - "traefik.http.routers.http-catchall.entrypoints=web"
${VDM_REMOVE_SECURE} - "traefik.http.routers.http-catchall.middlewares=redirect-to-me"
${VDM_REMOVE_SECURE} - "traefik.http.middlewares.redirect-to-me.redirectscheme.scheme=${VDM_HTTP_SCHEME}"
networks:
- traefik
networks:
traefik:
name: ${VDM_TRAEFIK_GATEWAY:-traefik_webgateway}
EOF
}
#####################################################################################################################VDM
######################################## SETUP PORTAINER
function portainer__TRuST__setup() {
# load this container type globals
# shellcheck disable=SC1090
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && source "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
# check if we have secure switch set
setSecureState
# setup letsencrypt stuff
VDM_PORT_SECURE_LABELS=''
if $VDM_SECURE; then
VDM_REMOVE_SECURE=''
VDM_ENTRY_POINT="websecure"
setSecureCloudflareState
if $VDM_SECURE_CLOUDFLARE; then
VDM_PORT_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.portainer.entrypoints=web\"")
else
VDM_PORT_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.portainer.entrypoints=${VDM_ENTRY_POINT}\"")
VDM_PORT_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.portainer.tls.certresolver=vdmresolver\"")
fi
else
VDM_REMOVE_SECURE="#"
VDM_ENTRY_POINT="web"
fi
# set the domain
setDomain
# get the sub domain if not set
setSubDomain 'port' '' 'joomla'
##########################
### export all we need
# global
export VDM_CONTAINER_TYPE
export VDM_REPO_PATH
export VDM_PROJECT_PATH
# container
export VDM_REMOVE_SECURE
export VDM_ENTRY_POINT
export VDM_PORT_SECURE_LABELS
# set host file if needed
updateHostFile
## create the directory if it does not yet already exist
# shellcheck disable=SC2174
mkdir -p -m 700 "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}"
## place this docker composer file in its place
portainerContainer >"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml"
## set permissions
chmod 600 "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml"
# saved the file
showNotice "Saved ${VDM_CONTAINER_TYPE}:docker-compose.yml file.\nSetup of this container is complete!"
# ask if we should continue to enable
if (whiptail --yesno "Would you also like to enable this ${VDM_CONTAINER_TYPE^} container" \
--defaultno --title "Enable Container" --backtitle "${BACK_TITLE}" 8 112); then
enableContainer "${VDM_CONTAINER_TYPE}"
fi
##########################
### unset all no longer needed
# container
unset VDM_SUBDOMAIN
unset VDM_REMOVE_SECURE
unset VDM_ENTRY_POINT
unset VDM_PORT_SECURE_LABELS
# return a success
return 0
}
# return the Portainer Container setup yml
function portainerContainer() {
# we build the yml file
cat <<EOF
version: "3.3"
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
command: -H unix:///var/run/docker.sock
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
labels:
# Frontend
- "traefik.enable=true"
- "traefik.http.routers.portainer.rule=Host(\`${VDM_SUBDOMAIN}.${VDM_DOMAIN}\`)"${VDM_PORT_SECURE_LABELS}
- "traefik.http.routers.portainer.service=portainer"
- "traefik.http.services.portainer.loadbalancer.server.port=9000"
# Edge
# - "traefik.http.routers.portaineredge.rule=Host(\`${VDM_SUBDOMAIN}edge.${VDM_DOMAIN}\`)"
# - "traefik.http.routers.portaineredge.entrypoints=${VDM_ENTRY_POINT}"
# - "traefik.http.routers.portaineredge.tls.certresolver=vdmresolver"
# - "traefik.http.routers.portaineredge.service=portaineredge"
# - "traefik.http.services.portaineredge.loadbalancer.server.port=8000"
networks:
- traefik
volumes:
portainer_data:
networks:
traefik:
external: true
name: ${VDM_TRAEFIK_GATEWAY:-traefik_webgateway}
EOF
}
#####################################################################################################################VDM
######################################## SETUP JOOMLA
function joomla__TRuST__setup() {
# load this container type globals
# shellcheck disable=SC1090
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && source "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
# we need to pull these values from the env if set
local vdm_key_db
local vdm_env_db
local vdm_key_user
local vdm_env_user
local vdm_key_pass
local vdm_env_pass
local vdm_key_root
local vdm_env_root
# get the Joomla image source
setImageSource
# get the key if not set
setUniqueKey
# get the env key if not set
setEnvironmentKey
# set the domain
setDomain
# get the sub domain if not set TODO get dynamic joomla domain name
setSubDomain "${VDM_KEY,,}" "joomla"
# check if we have secure switch set
setSecureState
# setup letsencrypt stuff
VDM_JOOMLA_SECURE_LABELS=''
VDM_PHPMYADMIN_SECURE_LABELS=''
if $VDM_SECURE; then
VDM_REMOVE_SECURE=''
VDM_ENTRY_POINT="websecure"
VDM_HTTP_SCHEME="https://"
setSecureCloudflareState
# add joomla labels
if $VDM_SECURE_CLOUDFLARE; then
VDM_JOOMLA_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.joomla${VDM_KEY}.entrypoints=web\"")
else
VDM_JOOMLA_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.joomla${VDM_KEY}.entrypoints=${VDM_ENTRY_POINT}\"")
VDM_JOOMLA_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.joomla${VDM_KEY}.tls.certresolver=vdmresolver\"")
fi
VDM_JOOMLA_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.joomla${VDM_KEY}.service=joomla${VDM_KEY}\"")
VDM_JOOMLA_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.services.joomla${VDM_KEY}.loadbalancer.server.port=80\"")
# add phpmyadmin labels
if $VDM_SECURE_CLOUDFLARE; then
VDM_PHPMYADMIN_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.phpmyadmin${VDM_KEY}.entrypoints=web\"")
else
VDM_PHPMYADMIN_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.phpmyadmin${VDM_KEY}.entrypoints=${VDM_ENTRY_POINT}\"")
VDM_PHPMYADMIN_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.phpmyadmin${VDM_KEY}.tls.certresolver=vdmresolver\"")
fi
VDM_PHPMYADMIN_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.phpmyadmin${VDM_KEY}.service=phpmyadmin${VDM_KEY}\"")
VDM_PHPMYADMIN_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.services.phpmyadmin${VDM_KEY}.loadbalancer.server.port=80\"")
else
VDM_REMOVE_SECURE="#"
VDM_ENTRY_POINT="web"
VDM_HTTP_SCHEME="http://"
fi
# set the details
vdm_key_db="VDM_${VDM_ENV_KEY^^}_DB"
vdm_env_db="${!vdm_key_db}"
vdm_key_user="VDM_${VDM_ENV_KEY^^}_DB_USER"
vdm_env_user="${!vdm_key_user}"
vdm_key_pass="VDM_${VDM_ENV_KEY^^}_DB_PASS"
vdm_env_pass="${!vdm_key_pass}"
vdm_key_root="VDM_${VDM_ENV_KEY^^}_DB_ROOT"
vdm_env_root="${!vdm_key_root}"
# now we check if its has been set
vdm_database_name="${vdm_database_name:-$vdm_env_db}"
vdm_database_user="${vdm_database_user:-$vdm_env_user}"
vdm_database_pass="${vdm_database_pass:-$vdm_env_pass}"
vdm_database_rootpass="${vdm_database_rootpass:-$vdm_env_root}"
# check if env is already set
# shellcheck disable=SC2015
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && grep -q "VDM_${VDM_ENV_KEY^^}_DB=" "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" || {
# add a space or create the file
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && echo '' >>"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
# get the database name needed
while [ ${#vdm_database_name} -le 1 ]; do
# get the value
vdm_database_name=$(getInput "Enter Database Name\n[Text with no spaces that is only underscore and alphabetical]" \
"vdm_io" 'Enter Database Name')
# keep asking if empty or does exist
[ ${#vdm_database_name} -ge 1 ] || {
showError "You must enter a database name!"
}
done
# get the database user name needed
while [ ${#vdm_database_user} -le 1 ]; do
# get the value
vdm_database_user=$(getInput "Enter Database Username\n[Text with no spaces that is only underscore and alphabetical]" \
"vdm_user" 'Enter Database Username')
# keep asking if empty or does exist
[ ${#vdm_database_user} -ge 1 ] || {
showError "You must enter a database username!"
}
done
# get the database user password needed
while [ ${#vdm_database_pass} -le 1 ]; do
# get the value
vdm_database_pass=$(getPassword "Enter Database User Password" \
"$(getRandomPass 20)" 'Enter Database User Password')
# keep asking if empty or does exist
[ ${#vdm_database_pass} -ge 1 ] || {
showError "You must enter a database user password!"
}
done
# get the database root password
while [ ${#vdm_database_rootpass} -le 1 ]; do
# get the value
vdm_database_rootpass=$(getPassword "Enter Database Root Password" \
"$(getRandomPass 40)" 'Enter Database Root Password')
# keep asking if empty or does exist
[ ${#vdm_database_rootpass} -ge 1 ] || {
showError "You must enter a database root password!"
}
done
}
# set persistence
VDM_JOOMLA_VOLUMES_MOUNT=$(getYMLine3 "- \"\${VDM_PROJECT_PATH}/${VDM_KEY}/joomla:/var/www/html\"")
VDM_DB_VOLUMES_MOUNT=$(getYMLine3 "- \"\${VDM_PROJECT_PATH}/${VDM_KEY}/db:/var/lib/mysql\"")
VDM_EXTRA_CONTAINER_STUFF=''
VDM_EXTRA_JOOMLA_ENV=''
VDM_VOLUMES='volumes:'
reset_volume=true
# only if in expert mode
if isExpert && ! setPersistence 'Joomla website files and folders'; then
VDM_JOOMLA_VOLUMES_MOUNT=$(getYMLine3 "- ${VDM_KEY,,}_web:/var/www/html")
VDM_VOLUMES+=$(getYMLine1 "${VDM_KEY,,}_web:")
reset_volume=false
fi
# only if in expert mode
if isExpert && ! setPersistence 'Joomla database'; then
VDM_DB_VOLUMES_MOUNT=$(getYMLine3 "- ${VDM_KEY,,}_db:/var/lib/mysql")
VDM_VOLUMES+=$(getYMLine1 "${VDM_KEY,,}_db:")
reset_volume=false
fi
# check if we have to reset the volume value
$reset_volume && VDM_VOLUMES=''
# add the projects path
setContainerEnvVariable "VDM_PROJECT_PATH=\"${VDM_PROJECT_PATH}\""
# ask if we should add mailcatcher
if (whiptail --yesno "Would you also like to enable mailcatcher for these ${VDM_CONTAINER_TYPE^} containers" \
--defaultno --title "Enable Mailcatcher" --backtitle "${BACK_TITLE}" 8 112); then
VDM_EXTRA_CONTAINER_STUFF=$(getYMLine1 "mailcatcher${VDM_KEY}:")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine2 "image: schickling/mailcatcher")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine2 "container_name: mailcatcher${VDM_KEY}")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine2 "restart: unless-stopped")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine2 "networks:")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- traefik")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine2 "labels:")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "# mailcatcher")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- \"traefik.enable=true\"")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- \"traefik.http.routers.mailcatcher${VDM_KEY}.rule=Host(\`${VDM_SUBDOMAIN}mail.${VDM_DOMAIN}\`)\"")
if $VDM_SECURE; then
if $VDM_SECURE_CLOUDFLARE; then
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- \"traefik.http.routers.mailcatcher${VDM_KEY}.entrypoints=web\"")
else
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- \"traefik.http.routers.mailcatcher${VDM_KEY}.entrypoints=${VDM_ENTRY_POINT}\"")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- \"traefik.http.routers.mailcatcher${VDM_KEY}.tls.certresolver=vdmresolver\"")
fi
fi
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- \"traefik.http.routers.mailcatcher${VDM_KEY}.service=mailcatcher${VDM_KEY}\"")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- \"traefik.http.services.mailcatcher${VDM_KEY}.loadbalancer.server.port=1080\"")
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_SMTP_HOST=mailcatcher${VDM_KEY}")
fi
# only if in expert mode set the container user detail id needed
if isExpert; then
# if this is our octoleo images we can also set the user ID and user-group ID
setContainerUser "$(id -u)"
# check that we got the details
if [ -n "${VDM_PUID}" ] && [ -n "${VDM_PGID}" ]; then
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_PUID=\"#${VDM_PUID}\""
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_PGID=\"#${VDM_PGID}\""
fi
fi
# add this value if not set variable
[ ${#vdm_database_name} -ge 1 ] && setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_DB=\"${vdm_database_name}\""
# add this value if not set variable
[ ${#vdm_database_user} -ge 1 ] && setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_DB_USER=\"${vdm_database_user}\""
# add this value if not set variable
[ ${#vdm_database_pass} -ge 1 ] && setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_DB_PASS=\"${vdm_database_pass}\""
# add this value if not set variable
[ ${#vdm_database_rootpass} -ge 1 ] && setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_DB_ROOT=\"${vdm_database_rootpass}\""
# we only do autodeploy for Joomla 4.3 and above
if isVersionAbove "$VDM_JV" "4.3"; then
# setup the website auto deploy details
setJoomlaWebsiteDetails
if [[ -n "${VDM_J_EMAIL}" ]]; then
# add extra Joomla envs
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_JOOMLA_DB_TYPE=\"mysqli\""
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_JOOMLA_DB_PREFIX=\"${VDM_KEY}_\""
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_JOOMLA_SITE_NAME=\"${VDM_J_SITE_NAME}\""
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_USERNAME=\"${VDM_J_USERNAME}\""
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_USER=\"${VDM_J_USER}\""
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_EMAIL=\"${VDM_J_EMAIL}\""
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_PASSWORD=\"${VDM_J_PASSWORD}\""
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_DB_TYPE=\${VDM_${VDM_ENV_KEY^^}_JOOMLA_DB_TYPE}")
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_DB_PREFIX=\${VDM_${VDM_ENV_KEY^^}_JOOMLA_DB_PREFIX}")
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_SITE_NAME=\${VDM_${VDM_ENV_KEY^^}_JOOMLA_SITE_NAME}")
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_ADMIN_USERNAME=\${VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_USERNAME}")
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_ADMIN_USER=\${VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_USER}")
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_ADMIN_EMAIL=\${VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_EMAIL}")
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_ADMIN_PASSWORD=\${VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_PASSWORD}")
fi
fi
# add PHP settings
VDM_PHP_PROJECT_PATH="${VDM_KEY}"
export VDM_PHP_PROJECT_PATH
if isExpert && setPHPSettings; then
VDM_JOOMLA_VOLUMES_MOUNT+=$(getYMLine3 "- \"\${VDM_PROJECT_PATH}/${VDM_PHP_PROJECT_PATH}/php.ini:/var/www/html/php.ini\"")
fi
# customize docker-entrypoint.sh
VDM_ENTRY_PROJECT_PATH="${VDM_KEY}"
export VDM_ENTRY_PROJECT_PATH
if isExpert && setDockerEntrypoint; then
VDM_JOOMLA_VOLUMES_MOUNT+=$(getYMLine3 "- \"\${VDM_PROJECT_PATH}/${VDM_ENTRY_PROJECT_PATH}/entrypoint.sh:/entrypoint.sh\"")
fi
##########################
### export all we need
# global
export VDM_CONTAINER_TYPE
export VDM_REPO_PATH
export VDM_PROJECT_PATH
# container
export VDM_REMOVE_SECURE
export VDM_ENTRY_POINT
export VDM_HTTP_SCHEME
export VDM_PERSISTENCE
export VDM_NOT_PERSISTENCE
export VDM_VOLUMES
export VDM_JOOMLA_VOLUMES_MOUNT
export VDM_DB_VOLUMES_MOUNT
export VDM_EXTRA_CONTAINER_STUFF
export VDM_JOOMLA_SECURE_LABELS
export VDM_PHPMYADMIN_SECURE_LABELS
export VDM_EXTRA_JOOMLA_ENV
# container lower
export vdm_database_name
export vdm_database_user
export vdm_database_pass
export vdm_database_rootpass
# set host file if needed
updateHostFile
# also set the database domain
updateHostFile "${VDM_SUBDOMAIN}db"
# create the directory if it does not yet already exist
# shellcheck disable=SC2174
mkdir -p -m 700 "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_SUBDOMAIN}.${VDM_DOMAIN}"
# place this docker composer file in its place
joomlaContainer >"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_SUBDOMAIN}.${VDM_DOMAIN}/docker-compose.yml"
# set permissions
chmod 600 "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_SUBDOMAIN}.${VDM_DOMAIN}/docker-compose.yml"
# saved the file
showNotice "Saved ${VDM_CONTAINER_TYPE}:docker-compose.yml file.\nSetup of this container is complete!"
# ask if we should continue to enable
if (whiptail --yesno "Would you also like to enable this ${VDM_CONTAINER_TYPE^} container" \
--defaultno --title "Enable Container" --backtitle "${BACK_TITLE}" 8 112); then
# we set the container details
export VDM_CONTAINER="${VDM_SUBDOMAIN}.${VDM_DOMAIN}"
# then we enable it
enableContainer "${VDM_CONTAINER_TYPE}"
fi
# display the configurations
showJoomlaConfigDetails
##########################
### unset all no longer needed
# container
unset VDM_SUBDOMAIN
unset VDM_J_REPO
unset VDM_ENTRY_REPO
unset VDM_JV
unset VDM_KEY
unset VDM_ENV_KEY
unset VDM_REMOVE_SECURE
unset VDM_ENTRY_POINT
unset VDM_HTTP_SCHEME
unset VDM_PERSISTENCE
unset VDM_NOT_PERSISTENCE
unset VDM_VOLUMES
unset VDM_JOOMLA_VOLUMES_MOUNT
unset VDM_DB_VOLUMES_MOUNT
unset VDM_PHP_PROJECT_PATH
unset VDM_ENTRY_PROJECT_PATH
unset VDM_EXTRA_CONTAINER_STUFF
unset VDM_JOOMLA_SECURE_LABELS
unset VDM_PHPMYADMIN_SECURE_LABELS
unset VDM_EXTRA_JOOMLA_ENV
unset VDM_J_SITE_NAME
unset VDM_J_USERNAME
unset VDM_J_USER
unset VDM_J_EMAIL
unset VDM_J_PASSWORD
# container lower
unset vdm_database_name
unset vdm_database_user
unset vdm_database_pass
unset vdm_database_rootpass
# return a success
return 0
}
# return the Joomla Container setup yml
function joomlaContainer() {
# set the USER if set
vdm_container_user=''
if [ -n "${VDM_PUID}" ] && [ -n "${VDM_PGID}" ]; then
vdm_container_user="
- APACHE_RUN_USER=\${VDM_${VDM_ENV_KEY^^}_PUID}
- APACHE_RUN_GROUP=\${VDM_${VDM_ENV_KEY^^}_PGID}"
fi
# we build the yml file
cat <<EOF
version: '2'
services:
mariadb${VDM_KEY}:
image: mariadb:latest
container_name: mariadb${VDM_KEY}
restart: unless-stopped
environment:
- MARIADB_DATABASE=\${VDM_${VDM_ENV_KEY^^}_DB}
- MARIADB_USER=\${VDM_${VDM_ENV_KEY^^}_DB_USER}
- MARIADB_PASSWORD=\${VDM_${VDM_ENV_KEY^^}_DB_PASS}
- MARIADB_ROOT_PASSWORD=\${VDM_${VDM_ENV_KEY^^}_DB_ROOT}
volumes:${VDM_DB_VOLUMES_MOUNT}
networks:
- traefik
joomla${VDM_KEY}:
image: ${VDM_J_REPO}:${VDM_JV}
container_name: joomla${VDM_KEY}
restart: unless-stopped
environment:${vdm_container_user}
- JOOMLA_DB_HOST=mariadb${VDM_KEY}:3306
- JOOMLA_DB_NAME=\${VDM_${VDM_ENV_KEY^^}_DB}
- JOOMLA_DB_USER=\${VDM_${VDM_ENV_KEY^^}_DB_USER}
- JOOMLA_DB_PASSWORD=\${VDM_${VDM_ENV_KEY^^}_DB_PASS}${VDM_EXTRA_JOOMLA_ENV}
depends_on:
- mariadb${VDM_KEY}
volumes:${VDM_JOOMLA_VOLUMES_MOUNT}
networks:
- traefik
labels:
# joomla
- "traefik.enable=true"
- "traefik.http.routers.joomla${VDM_KEY}.rule=Host(\`${VDM_SUBDOMAIN}.${VDM_DOMAIN}\`)"${VDM_JOOMLA_SECURE_LABELS}
phpmyadmin${VDM_KEY}:
image: phpmyadmin/phpmyadmin
container_name: phpmyadmin${VDM_KEY}
restart: unless-stopped
environment:
PMA_HOST: mariadb${VDM_KEY}
PMA_PORT: 3306
UPLOAD_LIMIT: 300M
depends_on:
- mariadb${VDM_KEY}
networks:
- traefik
labels:
# phpmyadmin
- "traefik.enable=true"
- "traefik.http.routers.phpmyadmin${VDM_KEY}.rule=Host(\`${VDM_SUBDOMAIN}db.${VDM_DOMAIN}\`)"${VDM_PHPMYADMIN_SECURE_LABELS}${VDM_EXTRA_CONTAINER_STUFF}
networks:
traefik:
external: true
name: ${VDM_TRAEFIK_GATEWAY:-traefik_webgateway}
${VDM_VOLUMES}
EOF
}
#####################################################################################################################VDM
######################################## BULK SETUP JOOMLA
function joomla__TRuST__bulk() {
# load this container type globals
# shellcheck disable=SC1090
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && source "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
# we need to pull these values from the env if set
local vdm_key
local vdm_subdomain
local vdm_database_name
local vdm_bulk_database_name
local vdm_database_user
local vdm_bulk_database_user
local vdm_database_pass
local vdm_bulk_database_user
local vdm_database_rootpass
# get the Joomla image source
setImageSource
# set the domain
setDomain
# get the sub domain if not set TODO get dynamic joomla domain name
setSubDomain "subdomain" "joomla"
vdm_subdomain="${VDM_SUBDOMAIN}"
# check if we have secure switch set
setSecureState
# setup letsencrypt stuff
if $VDM_SECURE; then
VDM_REMOVE_SECURE=''
VDM_ENTRY_POINT="websecure"
VDM_HTTP_SCHEME="https://"
setSecureCloudflareState
else
VDM_REMOVE_SECURE="#"
VDM_ENTRY_POINT="web"
VDM_HTTP_SCHEME="http://"
fi
# get the database name needed
while [ ${#vdm_bulk_database_name} -le 1 ]; do
# get the value
vdm_bulk_database_name=$(getInput "Enter Database Name\n[Text with no spaces that is only underscore and alphabetical]" \
"vdm_io" 'Enter Database Name')
# keep asking if empty or does exist
[ ${#vdm_bulk_database_name} -ge 1 ] || {
showError "You must enter a database name!"
}
done
# get the database user name needed
while [ ${#vdm_bulk_database_user} -le 1 ]; do
# get the value
vdm_bulk_database_user=$(getInput "Enter Database Username\n[Text with no spaces that is only underscore and alphabetical]" \
"vdm_user" 'Enter Database Username')
# keep asking if empty or does exist
[ ${#vdm_bulk_database_user} -ge 1 ] || {
showError "You must enter a database username!"
}
done
# get the database user password needed
while [ ${#vdm_bulk_database_pass} -le 1 ]; do
# get the value
vdm_bulk_database_pass=$(getPassword "Enter Database User Password" \
"$(getRandomPass 20)" 'Enter Database User Password')
# keep asking if empty or does exist
[ ${#vdm_bulk_database_pass} -ge 1 ] || {
showError "You must enter a database user password!"
}
done
# only if in expert mode set the container user detail id needed
if isExpert; then
# if this is our octoleo images we can also set the user ID and user-group ID
setContainerUser "$(id -u)"
fi
# add PHP settings
set_php_settings=false
VDM_PHP_PROJECT_PATH="bulk"
export VDM_PHP_PROJECT_PATH
if isExpert && setPHPSettings; then
set_php_settings=true
fi
# customize docker-entrypoint.sh
set_docker_entry_point=false
VDM_ENTRY_PROJECT_PATH="bulk"
export VDM_ENTRY_PROJECT_PATH
if isExpert && setDockerEntrypoint; then
set_docker_entry_point=true
fi
# set persistence
persistence_volume=false
persistence_db=false
# only if in expert mode
if isExpert && setPersistence 'Joomla website files and folders'; then
persistence_volume=true
fi
# only if in expert mode
if isExpert && setPersistence 'Joomla database'; then
persistence_db=true
fi
# ask if we should add mailcatcher
enable_mailcatcher=false
if (whiptail --yesno "Would you also like to enable mailcatcher for these ${VDM_CONTAINER_TYPE^} containers" \
--defaultno --title "Enable Mailcatcher" --backtitle "${BACK_TITLE}" 8 112); then
enable_mailcatcher=true
fi
# we only do autodeploy for Joomla 4.3 and above
enable_autodeploy=false
if isVersionAbove "$VDM_JV" "4.3"; then
# get website setup details
setJoomlaWebsiteDetails
if [[ -n "${VDM_J_EMAIL}" ]]; then
enable_autodeploy=true
fi
fi
# add the projects path
setContainerEnvVariable "VDM_PROJECT_PATH=\"${VDM_PROJECT_PATH}\""
##########################
### export all we need
# global
export VDM_CONTAINER_TYPE
export VDM_REPO_PATH
export VDM_PROJECT_PATH
# container
export VDM_REMOVE_SECURE
export VDM_ENTRY_POINT
export VDM_HTTP_SCHEME
export VDM_PERSISTENCE
export VDM_NOT_PERSISTENCE
# get the number of containers
setNumberContainers
# ask if we should continue to enable
enable_containers=false
if (whiptail --yesno "Would you also like to enable all these ${VDM_CONTAINER_TYPE^} containers" \
--defaultno --title "Enable Containers" --backtitle "${BACK_TITLE}" 8 112); then
enable_containers=true
fi
# loop the number of containers
for (( i=1; i<=VDM_NUMBER_CONTAINERS; i++ ))
do
vdm_key=$(getRandomName 5)
VDM_KEY="${vdm_key,,}"
VDM_ENV_KEY="${vdm_key^^}"
VDM_SUBDOMAIN="${vdm_subdomain}${i}"
vdm_database_name="${vdm_bulk_database_name}${i}"
vdm_database_user="${vdm_bulk_database_user}${i}"
vdm_database_pass="${vdm_bulk_database_pass}${i}"
vdm_database_rootpass=$(getRandomPass 30)
# reset some globals
VDM_EXTRA_CONTAINER_STUFF=''
VDM_EXTRA_JOOMLA_ENV=''
# check that we got the details
if [ -n "${VDM_PUID}" ] && [ -n "${VDM_PGID}" ]; then
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_PUID=\"#${VDM_PUID}\""
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_PGID=\"#${VDM_PGID}\""
fi
# add this value if not set variable
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_DB=\"${vdm_database_name}\""
# add this value if not set variable
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_DB_USER=\"${vdm_database_user}\""
# add this value if not set variable
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_DB_PASS=\"${vdm_database_pass}\""
# add this value if not set variable
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_DB_ROOT=\"${vdm_database_rootpass}\""
# we only do autodeploy for Joomla 4.3 and above
if $enable_autodeploy; then
# add extra Joomla envs
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_JOOMLA_DB_TYPE=\"mysqli\""
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_JOOMLA_DB_PREFIX=\"${VDM_KEY}_\""
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_JOOMLA_SITE_NAME=\"${VDM_J_SITE_NAME} ${i}\""
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_USERNAME=\"${VDM_J_USERNAME}\""
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_USER=\"${VDM_J_USER}\""
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_EMAIL=\"${VDM_J_EMAIL}\""
setContainerEnvVariable "VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_PASSWORD=\"${VDM_J_PASSWORD}\""
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_DB_TYPE=\${VDM_${VDM_ENV_KEY^^}_JOOMLA_DB_TYPE}")
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_DB_PREFIX=\${VDM_${VDM_ENV_KEY^^}_JOOMLA_DB_PREFIX}")
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_SITE_NAME=\${VDM_${VDM_ENV_KEY^^}_JOOMLA_SITE_NAME}")
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_ADMIN_USERNAME=\${VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_USERNAME}")
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_ADMIN_USER=\${VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_USER}")
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_ADMIN_EMAIL=\${VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_EMAIL}")
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_ADMIN_PASSWORD=\${VDM_${VDM_ENV_KEY^^}_JOOMLA_ADMIN_PASSWORD}")
fi
# set persistence
reset_volume=true
VDM_JOOMLA_VOLUMES_MOUNT=$(getYMLine3 "- \"\${VDM_PROJECT_PATH}/${VDM_KEY}/joomla:/var/www/html\"")
VDM_DB_VOLUMES_MOUNT=$(getYMLine3 "- \"\${VDM_PROJECT_PATH}/${VDM_KEY}/db:/var/lib/mysql\"")
VDM_VOLUMES='volumes:'
if ! $persistence_volume; then
VDM_JOOMLA_VOLUMES_MOUNT=$(getYMLine3 "- ${VDM_KEY,,}_web:/var/www/html")
VDM_VOLUMES+=$(getYMLine1 "${VDM_KEY,,}_web:")
reset_volume=false
fi
if ! $persistence_db; then
VDM_DB_VOLUMES_MOUNT=$(getYMLine3 "- ${VDM_KEY,,}_db:/var/lib/mysql")
VDM_VOLUMES+=$(getYMLine1 "${VDM_KEY,,}_db:")
reset_volume=false
fi
# add PHP settings
if $set_php_settings; then
VDM_JOOMLA_VOLUMES_MOUNT+=$(getYMLine3 "- \"\${VDM_PROJECT_PATH}/${VDM_PHP_PROJECT_PATH}/php.ini:/var/www/html/php.ini\"")
fi
# customize docker-entrypoint.sh
if $set_docker_entry_point; then
VDM_JOOMLA_VOLUMES_MOUNT+=$(getYMLine3 "- \"\${VDM_PROJECT_PATH}/${VDM_ENTRY_PROJECT_PATH}/entrypoint.sh:/entrypoint.sh\"")
fi
# check if we have to reset the volume value
$reset_volume && VDM_VOLUMES=''
# add the mailcatcher if needed
if $enable_mailcatcher; then
VDM_EXTRA_CONTAINER_STUFF=$(getYMLine1 "mailcatcher${VDM_KEY}:")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine2 "image: schickling/mailcatcher")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine2 "container_name: mailcatcher${VDM_KEY}")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine2 "restart: unless-stopped")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine2 "networks:")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- traefik")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine2 "labels:")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "# mailcatcher")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- \"traefik.enable=true\"")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- \"traefik.http.routers.mailcatcher${VDM_KEY}.rule=Host(\`${VDM_SUBDOMAIN}mail.${VDM_DOMAIN}\`)\"")
if $VDM_SECURE; then
if $VDM_SECURE_CLOUDFLARE; then
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- \"traefik.http.routers.mailcatcher${VDM_KEY}.entrypoints=web\"")
else
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- \"traefik.http.routers.mailcatcher${VDM_KEY}.entrypoints=${VDM_ENTRY_POINT}\"")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- \"traefik.http.routers.mailcatcher${VDM_KEY}.tls.certresolver=vdmresolver\"")
fi
fi
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- \"traefik.http.routers.mailcatcher${VDM_KEY}.service=mailcatcher${VDM_KEY}\"")
VDM_EXTRA_CONTAINER_STUFF+=$(getYMLine3 "- \"traefik.http.services.mailcatcher${VDM_KEY}.loadbalancer.server.port=1080\"")
VDM_EXTRA_JOOMLA_ENV+=$(getYMLine3 "- JOOMLA_SMTP_HOST=mailcatcher${VDM_KEY}")
fi
# setup letsencrypt stuff
VDM_JOOMLA_SECURE_LABELS=''
VDM_PHPMYADMIN_SECURE_LABELS=''
if $VDM_SECURE; then
# add joomla labels
if $VDM_SECURE_CLOUDFLARE; then
VDM_JOOMLA_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.joomla${VDM_KEY}.entrypoints=web\"")
else
VDM_JOOMLA_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.joomla${VDM_KEY}.entrypoints=${VDM_ENTRY_POINT}\"")
VDM_JOOMLA_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.joomla${VDM_KEY}.tls.certresolver=vdmresolver\"")
fi
VDM_JOOMLA_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.joomla${VDM_KEY}.service=joomla${VDM_KEY}\"")
VDM_JOOMLA_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.services.joomla${VDM_KEY}.loadbalancer.server.port=80\"")
# add phpmyadmin labels
if $VDM_SECURE_CLOUDFLARE; then
VDM_PHPMYADMIN_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.phpmyadmin${VDM_KEY}.entrypoints=web\"")
else
VDM_PHPMYADMIN_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.phpmyadmin${VDM_KEY}.entrypoints=${VDM_ENTRY_POINT}\"")
VDM_PHPMYADMIN_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.phpmyadmin${VDM_KEY}.tls.certresolver=vdmresolver\"")
fi
VDM_PHPMYADMIN_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.routers.phpmyadmin${VDM_KEY}.service=phpmyadmin${VDM_KEY}\"")
VDM_PHPMYADMIN_SECURE_LABELS+=$(getYMLine3 "- \"traefik.http.services.phpmyadmin${VDM_KEY}.loadbalancer.server.port=80\"")
fi
# global
export VDM_KEY
export VDM_ENV_KEY
export VDM_SUBDOMAIN
# container
export VDM_VOLUMES
export VDM_JOOMLA_VOLUMES_MOUNT
export VDM_DB_VOLUMES_MOUNT
export VDM_EXTRA_CONTAINER_STUFF
export VDM_JOOMLA_SECURE_LABELS
export VDM_PHPMYADMIN_SECURE_LABELS
export VDM_EXTRA_JOOMLA_ENV
# container lower
export vdm_database_name
export vdm_database_user
export vdm_database_pass
export vdm_database_rootpass
# create the directory if it does not yet already exist
# shellcheck disable=SC2174
mkdir -p -m 700 "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_SUBDOMAIN}.${VDM_DOMAIN}"
# place this docker composer file in its place
joomlaContainer >"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_SUBDOMAIN}.${VDM_DOMAIN}/docker-compose.yml"
# set permissions
chmod 600 "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_SUBDOMAIN}.${VDM_DOMAIN}/docker-compose.yml"
# enable the container
if $enable_containers; then
# we set the container details
export VDM_CONTAINER="${VDM_SUBDOMAIN}.${VDM_DOMAIN}"
# then we enable it
enableContainer "${VDM_CONTAINER_TYPE}"
fi
done
##########################
### unset all no longer needed
# container
unset VDM_SUBDOMAIN
unset VDM_J_REPO
unset VDM_ENTRY_REPO
unset VDM_JV
unset VDM_KEY
unset VDM_ENV_KEY
unset VDM_REMOVE_SECURE
unset VDM_ENTRY_POINT
unset VDM_HTTP_SCHEME
unset VDM_PERSISTENCE
unset VDM_NOT_PERSISTENCE
unset VDM_VOLUMES
unset VDM_JOOMLA_VOLUMES_MOUNT
unset VDM_DB_VOLUMES_MOUNT
unset VDM_NUMBER_CONTAINERS
unset VDM_PHP_PROJECT_PATH
unset VDM_ENTRY_PROJECT_PATH
unset VDM_EXTRA_CONTAINER_STUFF
unset VDM_JOOMLA_SECURE_LABELS
unset VDM_PHPMYADMIN_SECURE_LABELS
unset VDM_J_SITE_NAME
unset VDM_J_USERNAME
unset VDM_J_USER
unset VDM_J_EMAIL
unset VDM_J_PASSWORD
# container lower
unset vdm_database_name
unset vdm_database_user
unset vdm_database_pass
unset vdm_database_rootpass
# return a success
return 0
}
#####################################################################################################################VDM
######################################## SETUP OPENSSH
function openssh__TRuST__setup() {
# load this container type globals
# shellcheck disable=SC1090
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && source "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
# get the ssh port if not set
while [ ${#VDM_PORT} -le 1 ]; do
# get the value
VDM_PORT=$(getInput 'Enter ssh port to use\n[do not use 22]' '' 'Enter Port')
# keep asking
[ ${#VDM_PORT} -ge 1 ] || {
showError "You must enter a ssh port for the container"
}
done
# set the main domain if not set
setMainDomain
# get the username if not set
while [ ${#VDM_USER_NAME} -le 1 ] || [ -d "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_USER_NAME}.${VDM_DOMAIN}" ]; do
# get the value
VDM_USER_NAME=$(getInput 'Enter username of the container\n[Text with no spaces that is only alphabetical]' 'ubuntu' 'Enter Username')
# keep asking if empty or does exist
if [ ${#VDM_USER_NAME} -ge 1 ] && [ -d "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_USER_NAME}.${VDM_DOMAIN}" ]; then
showError "The username:${VDM_USER_NAME} is already used. Select another"
elif [ ${#VDM_USER_NAME} -le 1 ]; then
showError "You must enter a username for the container"
fi
done
# be sure to set the container USER ID
setContainerUser 33
# get the key if not set
setUniqueKey "Enter key used for container naming."
# get the env key if not set
setEnvironmentKey
# we check if it was set
[ ${#VDM_PUBLIC_KEY_GLOBAL_DIR} -le 1 ] && VDM_PUBLIC_KEY_GLOBAL_DIR="${VDM_PUBLIC_KEY_DIR:-}"
# get the global directory of the ssh public keys if not set
while [ ${#VDM_PUBLIC_KEY_GLOBAL_DIR} -le 1 ] || [ ! -d "${VDM_PUBLIC_KEY_GLOBAL_DIR}" ]; do
# creat the path if it exist
if [ ${#VDM_PUBLIC_KEY_GLOBAL_DIR} -ge 1 ] &&
(whiptail --yesno "Can we create the ${VDM_PUBLIC_KEY_GLOBAL_DIR} ssh folder" \
--title "Create the Path" --backtitle "${BACK_TITLE}" 8 112); then
mkdir -p "${VDM_PUBLIC_KEY_GLOBAL_DIR}"
else
# get the value
VDM_PUBLIC_KEY_GLOBAL_DIR=$(getInput "Enter the ssh path where we can select the ssh key folders from." \
"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.ssh" 'Enter SSH Path')
# keep asking if empty or does exist
if [ ${#VDM_PUBLIC_KEY_GLOBAL_DIR} -ge 1 ] && [ ! -d "${VDM_PUBLIC_KEY_GLOBAL_DIR}" ] &&
(whiptail --yesno "Can we create the ${VDM_PUBLIC_KEY_GLOBAL_DIR} ssh folder" \
--title "Create the Path" --backtitle "${BACK_TITLE}" 8 112); then
# shellcheck disable=SC2174
mkdir -p -m 700 "${VDM_PUBLIC_KEY_GLOBAL_DIR}"
elif [ ${#VDM_PUBLIC_KEY_GLOBAL_DIR} -le 1 ]; then
showError "You must set a ssh path where we can select the ssh key folders from."
fi
fi
done
# set the global key env string for the ssh keys
VDM_ENV_PUBLIC_KEY_U_DIR="VDM_${VDM_ENV_KEY^^}_PUBLIC_KEY_DIR"
VDM_PUBLIC_KEY_U_DIR=${!VDM_ENV_PUBLIC_KEY_U_DIR}
# get the directory of this containers public keys if not set
while [ ${#VDM_PUBLIC_KEY_U_DIR} -le 1 ] || [ ! -d "${VDM_PUBLIC_KEY_U_DIR}" ]; do
# creat the path if it exist
if [ ${#VDM_PUBLIC_KEY_U_DIR} -ge 1 ] &&
(whiptail --yesno "Can we create this (${VDM_PUBLIC_KEY_U_DIR}) containers' ssh public keys folder" \
--title "Create the Path" --backtitle "${BACK_TITLE}" 8 112); then
# shellcheck disable=SC2174
mkdir -p -m 700 "${VDM_PUBLIC_KEY_U_DIR}"
else
# get the value
VDM_PUBLIC_KEY_U_DIR=$(getSelectedDirectory "Select the containers' ssh public keys folder." \
"${VDM_PUBLIC_KEY_GLOBAL_DIR}" "${VDM_KEY,,}" 'Select Folder')
# keep asking if empty or does exist
if [ ${#VDM_PUBLIC_KEY_U_DIR} -ge 1 ]; then
# add the parent dir back
VDM_PUBLIC_KEY_U_DIR="${VDM_PUBLIC_KEY_GLOBAL_DIR}/${VDM_PUBLIC_KEY_U_DIR}"
# check if this directory exist
if [ ! -d "${VDM_PUBLIC_KEY_U_DIR}" ] &&
(whiptail --yesno "Can we create this (${VDM_PUBLIC_KEY_U_DIR}) containers' ssh public keys folder" \
--title "Create the Path" --backtitle "${BACK_TITLE}" 8 112); then
# shellcheck disable=SC2174
mkdir -p -m 700 "${VDM_PUBLIC_KEY_U_DIR}"
# TODO add option to add keys?
fi
else
showError "You must set a containers' ssh public keys folder."
fi
fi
done
# we must get the project path
VDM_ENV_PROJECT_DIR="VDM_${VDM_ENV_KEY^^}_PROJECT_DIR"
VDM_PROJECT_U_DIR=${!VDM_ENV_PROJECT_DIR}
# get the directory of the ssh public keys if not set
while [ ${#VDM_PROJECT_U_DIR} -le 1 ] || [ ! -d "${VDM_PROJECT_U_DIR}" ]; do
# creat the path if it exist
if [ ${#VDM_PROJECT_U_DIR} -ge 1 ] &&
(whiptail --yesno "Can we create the ${VDM_PROJECT_U_DIR} parent mounting directory" \
--title "Create the Path" --backtitle "${BACK_TITLE}" 8 112); then
mkdir -p "${VDM_PROJECT_U_DIR}"
else
# get the value
VDM_PROJECT_U_DIR=$(getInput "Enter the parent path where we can select the folders to mount to this container." \
"${VDM_PROJECT_PATH}" 'Enter Path')
# keep asking if empty or does exist
if [ ${#VDM_PROJECT_U_DIR} -ge 1 ] && [ ! -d "${VDM_PROJECT_U_DIR}" ] &&
(whiptail --yesno "Can we create the ${VDM_PROJECT_U_DIR} parent mounting directory" \
--title "Create the Path" --backtitle "${BACK_TITLE}" 8 112); then
# shellcheck disable=SC2174
mkdir -p -m 700 "${VDM_PROJECT_U_DIR}"
elif [ ${#VDM_PROJECT_U_DIR} -le 1 ]; then
showError "You must set a parent mounting directory path where we can select the folders to mount to this container."
fi
fi
done
# now load the mounting volumes
while [ ${#VDM_MOUNT_DIRS} -le 1 ]; do
# get the value
VDM_MOUNT_DIRS=$(getSelectedDirectories "Select the directories to mount to this container." \
"${VDM_PROJECT_U_DIR}" 'Select Folders')
# keep asking if empty or does exist
if [ ${#VDM_MOUNT_DIRS} -le 1 ]; then
showError "You must set the directories to mount to this container."
fi
done
# convert the string to an array
IFS=' ' read -r -a vdm_mount_dirs_array <<<"${VDM_MOUNT_DIRS[@]}"
# build the mount projects
VDM_VOLUMES_MOUNT=$(getYMLine3 "- \${${VDM_ENV_PUBLIC_KEY_U_DIR}}:/config/ssh_public_keys")
# loop over the directories to build the
for mDir in "${vdm_mount_dirs_array[@]}"; do
# set the full path
mDir="${mDir//\"/}"
# when we mount a joomla volume we may not want to mount the database
mFull="${VDM_PROJECT_U_DIR}/${mDir}/joomla"
# add to mount projects
if [ -d "${mFull}" ] && (whiptail --yesno "Should we ONLY mount the (joomla website files) ${mDir}/joomla directory" \
--title "Mount Joomla" --backtitle "${BACK_TITLE}" 8 112); then
VDM_VOLUMES_MOUNT+=$(getYMLine3 "- \${VDM_${VDM_ENV_KEY^^}_PROJECT_DIR}/${mDir}/joomla:/app/${mDir}")
else
VDM_VOLUMES_MOUNT+=$(getYMLine3 "- \${VDM_${VDM_ENV_KEY^^}_PROJECT_DIR}/${mDir}:/app/${mDir}")
fi
done
# add this value if not set variable
setContainerEnvVariable "${VDM_ENV_PROJECT_DIR}=\"${VDM_PROJECT_U_DIR}\""
# add this value if not set variable
setContainerEnvVariable "VDM_PUBLIC_KEY_GLOBAL_DIR=\"${VDM_PUBLIC_KEY_GLOBAL_DIR}\""
# add this value if not set variable
setContainerEnvVariable "${VDM_ENV_PUBLIC_KEY_U_DIR}=\"${VDM_PUBLIC_KEY_U_DIR}\""
##########################
### export all we need
# global
export VDM_CONTAINER_TYPE
export VDM_REPO_PATH
export VDM_PROJECT_PATH
# container
export VDM_PORT
export VDM_USER_NAME
export VDM_PUBLIC_KEY_GLOBAL_DIR
export VDM_PUBLIC_KEY_U_DIR
export VDM_VOLUMES_MOUNT
export VDM_PROJECT_U_DIR
# create the directory if it does not yet already exist
# shellcheck disable=SC2174
mkdir -p -m 700 "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_USER_NAME}.${VDM_DOMAIN}"
# place this docker composer file in its place
opensshContainer >"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_USER_NAME}.${VDM_DOMAIN}/docker-compose.yml"
# set permissions
chmod 600 "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_USER_NAME}.${VDM_DOMAIN}/docker-compose.yml"
# saved the file
showNotice "Saved ${VDM_CONTAINER_TYPE}:docker-compose.yml file.\nSetup of this container is complete!"
# ask if we should continue to enable
if (whiptail --yesno "Would you also like to enable this ${VDM_CONTAINER_TYPE^} container" \
--defaultno --title "Enable Container" --backtitle "${BACK_TITLE}" 8 112); then
# we set the container details
export VDM_CONTAINER="${VDM_USER_NAME}.${VDM_DOMAIN}"
# then we enable it
enableContainer "${VDM_CONTAINER_TYPE}"
fi
##########################
### unset all no longer needed
# container
unset VDM_PORT
unset VDM_USER_NAME
unset VDM_KEY
unset VDM_ENV_KEY
unset VDM_PUBLIC_KEY_GLOBAL_DIR
unset VDM_PUBLIC_KEY_U_DIR
unset VDM_VOLUMES_MOUNT
unset VDM_PROJECT_U_DIR
# return a success
return 0
}
# return the Openssh Container setup yml
function opensshContainer() {
# we build the yml file
cat <<EOF
version: "2.1"
services:
openssh-server-${VDM_KEY}:
image: lscr.io/linuxserver/openssh-server
container_name: openssh-server-${VDM_KEY}
restart: unless-stopped
hostname: ${VDM_DOMAIN:-vdm.dev}
environment:
- PUID=${VDM_PUID}
- PGID=${VDM_PGID}
- TZ=${VDM_TZ:-Africa/Windhoek}
- PUBLIC_KEY_DIR=/config/ssh_public_keys
- SUDO_ACCESS=${VDM_SUDO_ACCESS:-false}
- USER_NAME=${VDM_USER_NAME:-ubuntu}
volumes:${VDM_VOLUMES_MOUNT}
ports:
- ${VDM_PORT}:2222
networks:
- openssh
networks:
openssh:
name: ${VDM_OPENSSH_GATEWAY:-openssh_gateway}
EOF
}
#####################################################################################################################VDM
######################################## EDIT JOOMLA
function joomla__TRuST__edit() {
# check if this type have available containers
if ! hasDirectories "${VDM_CONTAINER_TYPE}/available/"; then
showError "The path ${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/ does not exist or is empty, first run a ${VDM_CONTAINER_TYPE^} setup."
else
# set some local variables
local vdm_edit_me
local container
# list containers... and allow selection to edit
container=$(getSelectedDirectory "Select a container to manually edit the docker-composer.yml file.\n[Only continue if you know what your doing!]" \
"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/" '' "Edit ${VDM_CONTAINER_TYPE^} Container")
# check that we have something, else return to main menu
if [ ${#container} -ge 1 ]; then
# add the parent dir back
vdm_edit_me="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${container}/docker-compose.yml"
# check if this docker-composer.yml exist
if [ -f "${vdm_edit_me}" ]; then
# give little heads-up
showNotice "${USER^}, to save the changes you've made or to just close the file again press:\n\n[ctrl+x] with nano on ubuntu." 13
# lets open the file with nano for now
"${EDITOR:-nano}" "${vdm_edit_me}"
# if this container is enabled ask if it should be redeployed
if [ -d "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}" ] &&
(whiptail --yesno "Would you like to re-deploy the (${container}) container that you opened to edit?" \
--title "Re-Deploy Container" --backtitle "${BACK_TITLE}" 8 112); then
# we set the container details
export VDM_CONTAINER="${container}"
# then we enable it
enableContainer "${VDM_CONTAINER_TYPE}"
fi
fi
fi
fi
}
#####################################################################################################################VDM
######################################## EDIT OPENSSH
function openssh__TRuST__edit() {
# check if this type have available containers
if ! hasDirectories "${VDM_CONTAINER_TYPE}/available/"; then
showError "The path ${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/ does not exist or is empty, first run a ${VDM_CONTAINER_TYPE^} setup."
else
# set some local variables
local vdm_edit_me
local container
# list containers... and allow selection to edit
container=$(getSelectedDirectory "Select a container to manually edit the docker-composer.yml file.\n[Only continue if you know what your doing!]" \
"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/" '' "Edit ${VDM_CONTAINER_TYPE^} Container")
# check that we have something, else return to main menu
if [ ${#container} -ge 1 ]; then
# add the parent dir back
vdm_edit_me="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${container}/docker-compose.yml"
# check if this docker-composer.yml exist
if [ -f "${vdm_edit_me}" ]; then
# give little heads-up
showNotice "${USER^}, to save the changes you've made or to just close the file again press:\n\n[ctrl+x] with nano on ubuntu." 13
# lets open the file with nano for now
"${EDITOR:-nano}" "${vdm_edit_me}"
# if this container is enabled ask if it should be redeployed
if [ -d "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}" ] &&
(whiptail --yesno "Would you like to re-deploy the (${container}) container that you opened to edit?" \
--title "Re-Deploy Container" --backtitle "${BACK_TITLE}" 8 112); then
# we set the container details
export VDM_CONTAINER="${container}"
# then we enable it
enableContainer "${VDM_CONTAINER_TYPE}"
fi
fi
fi
fi
}
#####################################################################################################################VDM
######################################## EDIT TRAEFIK
function traefik__TRuST__edit() {
# check if traefik has been setup
if [ ! -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" ]; then
showError "There is no ${VDM_CONTAINER_TYPE^} container to edit."
else
# give little warning for less command ready people
if (whiptail --yesno "Only continue if you know what your doing!\n\n\
${USER^}, to save the changes you've made or to just close the file again press:\n\n\
[ctrl+x] with nano on ubuntu." --title "Continue to edit ${VDM_CONTAINER_TYPE^} config." \
--backtitle "${BACK_TITLE}" 15 112); then
# lets open the file with nano for now
"${EDITOR:-nano}" "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml"
# if this container is enabled ask if it should be redeployed
if (whiptail --yesno "Would you like to deploy or re-deploy the ${VDM_CONTAINER_TYPE^} container that you opened to edit?" \
--title "Deploy or Re-Deploy Container" --backtitle "${BACK_TITLE}" 8 112); then
# then we enable it
enableContainer "${VDM_CONTAINER_TYPE}"
fi
fi
fi
}
#####################################################################################################################VDM
######################################## EDIT PORTAINER
function portainer__TRuST__edit() {
# check if portainer has been setup
if [ ! -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" ]; then
showError "There is no ${VDM_CONTAINER_TYPE^} container to edit."
else
# give little warning for less command ready people
if (whiptail --yesno "Only continue if you know what your doing!\n\n\
${USER^}, to save the changes you've made or to just close the file again press:\n\n\
[ctrl+x] with nano on ubuntu." --title "Continue to edit ${VDM_CONTAINER_TYPE^} config." \
--backtitle "${BACK_TITLE}" 15 112); then
# lets open the file with nano for now
"${EDITOR:-nano}" "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml"
# if this container is enabled ask if it should be redeployed
if (whiptail --yesno "Would you like to deploy or re-deploy the ${VDM_CONTAINER_TYPE^} container that you opened to edit?" \
--title "Deploy or Re-Deploy Container" --backtitle "${BACK_TITLE}" 8 112); then
# then we enable it
enableContainer "${VDM_CONTAINER_TYPE}"
fi
fi
fi
}
#####################################################################################################################VDM
######################################## ENABLE JOOMLA
function joomla__TRuST__enable() {
# some local values
local evn_file
# check if this type have available containers
if ! hasDirectories "${VDM_CONTAINER_TYPE}/available/"; then
showError "The path ${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/ does not exist or is empty, first run a ${VDM_CONTAINER_TYPE^} setup."
elif [ ! -d "${VDM_PROJECT_PATH}" ]; then
# this should never happen, but in case
showError "The path ${VDM_PROJECT_PATH} does not exist, so we can't mount the persistent volumes. This error should never show, \
please open an issue and report octojoom-error-1234 with the steps of how you got here?"
elif [ ${#VDM_CONTAINER} -ge 1 ]; then
# this means we have a single already selected container to enable if it exists
if [ -d "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_CONTAINER}" ]; then
# create the folder as needed
mkdir -p "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/"
# create the soft link
[ -e "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}" ] || {
ln -s "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_CONTAINER}" "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}"
}
# check if image has its own env file also
evn_file=''
# shellcheck disable=SC2015
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}/.env" ] && evn_file="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}/.env" || {
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && evn_file="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
}
# make sure the docker image is started
# shellcheck disable=SC2015
[ ${#evn_file} -ge 1 ] && docker-compose --env-file "${evn_file}" --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}/docker-compose.yml" up -d || {
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}/docker-compose.yml" up -d
}
else
showError "The (${VDM_CONTAINER}) container does not exist."
fi
# always unset after
VDM_CONTAINER=''
unset VDM_CONTAINER
else
# set some local variables
local vdm_enable_me
local container
# create the folder as needed
mkdir -p "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/"
# get containers to enable
vdm_enable_me=$(getSelectedDirectories "Select container/s to enable." \
"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/" "Enable ${VDM_CONTAINER_TYPE^} Containers")
# check that we have something, else return to main menu
if [ ${#vdm_enable_me} -ge 1 ]; then
# convert the string to and array
IFS=' ' read -r -a vdm_enable_me_array <<<"${vdm_enable_me[@]}"
# loop over the directories to build the
for containered in "${vdm_enable_me_array[@]}"; do
# remove the " from the string
container="${containered//\"/}"
# create the soft link
[ -e "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}" ] || {
ln -s "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${container}" "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}"
}
# check if image has its own env file also
evn_file=''
# shellcheck disable=SC2015
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}/.env" ] && evn_file="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}/.env" || {
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && evn_file="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
}
# make sure the docker image is started
# shellcheck disable=SC2015
[ ${#evn_file} -ge 1 ] && docker-compose --env-file "${evn_file}" --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}/docker-compose.yml" up -d || {
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}/docker-compose.yml" up -d
}
done
fi
fi
}
#####################################################################################################################VDM
######################################## ENABLE OPENSSH
function openssh__TRuST__enable() {
# check if this type have available containers
if ! hasDirectories "${VDM_CONTAINER_TYPE}/available/"; then
showError "The path ${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/ does not exist, first run a ${VDM_CONTAINER_TYPE} setup."
elif [ ${#VDM_CONTAINER} -ge 1 ]; then
# this means we have a single already selected container to enable if it exists
if [ -d "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_CONTAINER}" ]; then
# create the folder as needed
mkdir -p "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/"
# create the soft lin
[ -e "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}" ] || {
ln -s "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${VDM_CONTAINER}" "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}"
}
# check if image has its own env file also
evn_file=''
# shellcheck disable=SC2015
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}/.env" ] && evn_file="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}/.env" || {
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && evn_file="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
}
# make sure the docker image is started
# shellcheck disable=SC2015
[ ${#evn_file} -ge 1 ] && docker-compose --env-file "${evn_file}" --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}/docker-compose.yml" up -d || {
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}/docker-compose.yml" up -d
}
else
showError "The (${VDM_CONTAINER}) container does not exist."
fi
# always unset after
VDM_CONTAINER=''
unset VDM_CONTAINER
else
# set some local variables
local vdm_enable_me
local container
local evn_file
# create the folder as needed
mkdir -p "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/"
# get containers to enable
vdm_enable_me=$(getSelectedDirectories "Select container/s to enable." \
"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/" "Enable ${VDM_CONTAINER_TYPE^} Containers")
# check that we have something, else return to main menu
if [ ${#vdm_enable_me} -ge 1 ]; then
# convert the string to and array
IFS=' ' read -r -a vdm_enable_me_array <<<"${vdm_enable_me[@]}"
# loop over the directories to build the
for containered in "${vdm_enable_me_array[@]}"; do
# remove the " from the string
container="${containered//\"/}"
# create the soft link
[ -e "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}" ] || {
ln -s "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${container}" "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}"
}
# check if image has its own env file also
evn_file=''
# shellcheck disable=SC2015
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}/.env" ] && evn_file="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}/.env" || {
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && evn_file="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
}
# make sure the docker image is started
# shellcheck disable=SC2015
[ ${#evn_file} -ge 1 ] && docker-compose --env-file "${evn_file}" --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}/docker-compose.yml" up -d || {
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}/docker-compose.yml" up -d
}
done
fi
fi
}
#####################################################################################################################VDM
######################################## ENABLE TRAEFIK
function traefik__TRuST__enable() {
# check if traefik has been setup
if [ ! -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" ]; then
showError "There is no ${VDM_CONTAINER_TYPE^} container to enable, first run the ${VDM_CONTAINER_TYPE^} setup."
else
# set some local variables
local evn_file
# make sure to take down Apache
downApache
# check if image has its own env file also
evn_file=''
# shellcheck disable=SC2015
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && evn_file="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" || {
[ -f "${VDM_SRC_PATH}/.env" ] && evn_file="${VDM_SRC_PATH}/.env"
}
# make sure the docker image is started
# shellcheck disable=SC2015
[ ${#evn_file} -ge 1 ] && docker-compose --env-file "${evn_file}" --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" up -d || {
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" up -d
}
fi
}
#####################################################################################################################VDM
######################################## ENABLE PORTAINER
function portainer__TRuST__enable() {
# check if traefik has been setup
if [ ! -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" ]; then
showError "There is no ${VDM_CONTAINER_TYPE^} container to enable, first run the ${VDM_CONTAINER_TYPE^} setup."
else
# set some local variables
local evn_file
# check if image has its own env file also
evn_file=''
# shellcheck disable=SC2015
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && evn_file="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" || {
[ -f "${VDM_SRC_PATH}/.env" ] && evn_file="${VDM_SRC_PATH}/.env"
}
# make sure the docker image is started
# shellcheck disable=SC2015
[ ${#evn_file} -ge 1 ] && docker-compose --env-file "${evn_file}" --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" up -d || {
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" up -d
}
fi
}
#####################################################################################################################VDM
######################################## DISABLE JOOMLA
function joomla__TRuST__disable() {
# check if this type has enabled containers
if ! hasDirectories "${VDM_CONTAINER_TYPE}/enabled/"; then
showError "There are no ${VDM_CONTAINER_TYPE^} containers to disable."
elif [ ${#VDM_CONTAINER} -ge 1 ]; then
# this means we have a single already selected container to enable if it exists
if [ -d "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}" ]; then
# make sure the docker image is stopped
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}/docker-compose.yml" down --remove-orphans
# then remove soft link
rm -rf "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}"
else
showError "The (${VDM_CONTAINER}) container is not enabled."
fi
# always unset after
VDM_CONTAINER=''
unset VDM_CONTAINER
else
# set some local variables
local vdm_disable_me
local container
# get containers to enable
vdm_disable_me=$(getSelectedDirectories "Select container/s to disable." \
"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/" "Disable ${VDM_CONTAINER_TYPE^} Containers")
# check that we have something, else return to main menu
if [ ${#vdm_disable_me} -ge 1 ]; then
# convert the string to and array
IFS=' ' read -r -a vdm_disable_me_array <<<"${vdm_disable_me[@]}"
# loop over the directories to build the
for containered in "${vdm_disable_me_array[@]}"; do
# remove the " from the string
container="${containered//\"/}"
# make sure the docker image is stopped
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}/docker-compose.yml" down --remove-orphans
# then remove soft link
rm -rf "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}"
done
fi
fi
}
#####################################################################################################################VDM
######################################## DISABLE OPENSSH
function openssh__TRuST__disable() {
# check if this type has enabled containers
if ! hasDirectories "${VDM_CONTAINER_TYPE}/enabled/"; then
showError "There are no ${VDM_CONTAINER_TYPE^} containers to disable."
elif [ ${#VDM_CONTAINER} -ge 1 ]; then
# this means we have a single already selected container to enable if it exists
if [ -d "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}" ]; then
# make sure the docker image is stopped
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}/docker-compose.yml" down --remove-orphans
# then remove soft link
rm -rf "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${VDM_CONTAINER}"
else
showError "The (${VDM_CONTAINER}) container is not enabled."
fi
# always unset after
VDM_CONTAINER=''
unset VDM_CONTAINER
else
# set some local variables
local vdm_disable_me
local container
# get containers to enable
vdm_disable_me=$(getSelectedDirectories "Select container/s to disable." \
"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/" "Disable ${VDM_CONTAINER_TYPE^} Containers")
# check that we have something, else return to main menu
if [ ${#vdm_disable_me} -ge 1 ]; then
# convert the string to and array
IFS=' ' read -r -a vdm_disable_me_array <<<"${vdm_disable_me[@]}"
# loop over the directories to build the
for containered in "${vdm_disable_me_array[@]}"; do
# remove the " from the string
container="${containered//\"/}"
# make sure the docker image is stopped
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}/docker-compose.yml" down --remove-orphans
# then remove soft link
rm -rf "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}"
done
fi
fi
}
#####################################################################################################################VDM
######################################## DISABLE TRAEFIK
function traefik__TRuST__disable() {
# check if traefik has been setup
if [ ! -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" ]; then
showError "There is no ${VDM_CONTAINER_TYPE^} container to disable."
else
# make sure the docker image is stopped
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" down
fi
}
#####################################################################################################################VDM
######################################## DISABLE PORTAINER
function portainer__TRuST__disable() {
# check if portainer has been setup
if [ ! -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" ]; then
showError "There is no ${VDM_CONTAINER_TYPE^} container to disable."
else
# make sure the docker image is stopped
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" down
fi
}
#####################################################################################################################VDM
######################################## UP JOOMLA
function joomla__TRuST__up() {
# check if this type has enabled containers
if ! hasDirectories "${VDM_CONTAINER_TYPE}/enabled/"; then
showError "There are no ${VDM_CONTAINER_TYPE^} containers enabled, first enable some containers.\n\
(UP and DOWN targets only enabled containers)"
else
# set some local variables
local evn_file
local vdm_container
# get all zip files
for yml in "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/"*/*.yml; do
# get the vdm_container value
vdm_container="${yml%/docker-compose.yml}"
# check if image has its own env file also
evn_file=''
# check if image has its own env file also
# shellcheck disable=SC2015
[ -f "${vdm_container}/.env" ] && evn_file="${vdm_container}/.env" || {
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && evn_file="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
}
# make sure the docker image is started
# shellcheck disable=SC2015
[ ${#evn_file} -ge 1 ] && docker-compose --env-file "${evn_file}" --file "${yml}" up -d || {
docker-compose --file "${yml}" up -d
}
done
fi
}
#####################################################################################################################VDM
######################################## UP OPENSSH
function openssh__TRuST__up() {
# check if this type has enabled containers
if ! hasDirectories "${VDM_CONTAINER_TYPE}/enabled/"; then
showError "There are no ${VDM_CONTAINER_TYPE^} containers enabled, first enable some containers.\n\
(UP and DOWN targets only enabled containers)"
else
# set some local variables
local evn_file
local vdm_container
# get all zip files
for yml in "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/"*/*.yml; do
# get the vdm_container value
vdm_container="${yml%/docker-compose.yml}"
# check if image has its own env file also
evn_file=''
# check if image has its own env file also
# shellcheck disable=SC2015
[ -f "${vdm_container}/.env" ] && evn_file="${vdm_container}/.env" || {
[ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && evn_file="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
}
# make sure the docker image is started
# shellcheck disable=SC2015
[ ${#evn_file} -ge 1 ] && docker-compose --env-file "${evn_file}" --file "${yml}" up -d || {
docker-compose --file "${yml}" up -d
}
done
fi
}
#####################################################################################################################VDM
######################################## DOWN JOOMLA
function joomla__TRuST__down() {
# check if this type has enabled containers
if ! hasDirectories "${VDM_CONTAINER_TYPE}/enabled/"; then
showError "There are no ${VDM_CONTAINER_TYPE^} containers to take down.\n\
(UP and DOWN targets only enabled containers)"
elif (whiptail --yesno "Are you absolutely sure you want to take down all the ${VDM_CONTAINER_TYPE^} containers?" \
--title "Take Down Containers" --backtitle "${BACK_TITLE}" 8 112); then
# get all zip files
for yml in "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/"*/*.yml; do
docker-compose --file "${yml}" down
done
fi
}
#####################################################################################################################VDM
######################################## DOWN OPENSSH
function openssh__TRuST__down() {
# check if this type has enabled containers
if ! hasDirectories "${VDM_CONTAINER_TYPE}/enabled/"; then
showError "There are no ${VDM_CONTAINER_TYPE^} containers to take down."
elif (whiptail --yesno "Are you absolutely sure you want to take down all the ${VDM_CONTAINER_TYPE^} containers?" \
--title "Take Down Containers" --backtitle "${BACK_TITLE}" 8 112); then
# get all zip files
for yml in "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/"*/*.yml; do
docker-compose --file "${yml}" down
done
fi
}
#####################################################################################################################VDM
######################################## DELETE JOOMLA
function joomla__TRuST__delete() {
# check if this type has enabled containers
if ! hasDirectories "${VDM_CONTAINER_TYPE}/available/"; then
showError "There are no ${VDM_CONTAINER_TYPE^} containers available."
else
# set some local variables
local vdm_delete_me
local container
# saved the file
showNotice "Only delete containers of which you have made absolutely sure it's no longer needed! Better to just disable them if all you want is to just take them down."
# get containers to enable
vdm_delete_me=$(getSelectedDirectories "Select container/s to delete." \
"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/" "Delete ${VDM_CONTAINER_TYPE^} Container/s")
# check that we have something, else return to main menu
if [ ${#vdm_delete_me} -ge 1 ]; then
# convert the string to and array
IFS=' ' read -r -a vdm_delete_me_array <<<"${vdm_delete_me[@]}"
# loop over the directories to build the
for containered in "${vdm_delete_me_array[@]}"; do
# remove the " from the string
container="${containered//\"/}"
# check if the container is still enabled
if [ -d "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}" ]; then
# make sure the docker image is stopped
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}/docker-compose.yml" down
# then remove soft link
rm -rf "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}"
fi
# before deleting the config we ask to make sure
if (whiptail --yesno "Would you like to delete the (${container}) container's folder that holds the docker-compose.yml file?" \
--title "Delete Docker Compose Yaml" --backtitle "${BACK_TITLE}" 8 112); then
# then remove docker-compose.yml file
rm -rf "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${container}"
fi
done
fi
# ask if there are volumes to delete
if hasDirectories '' "${VDM_PROJECT_PATH}" &&
(whiptail --yesno "Would you like to delete persistent volumes found in (${VDM_PROJECT_PATH})?" \
--title "Continue To Delete Persistent Volumes" --backtitle "${BACK_TITLE}" 12 112); then
# trigger the volumes removal script
deletePersistentVolumes
fi
fi
}
#####################################################################################################################VDM
######################################## DELETE OPENSSH
function openssh__TRuST__delete() {
# check if this type has enabled containers
if ! hasDirectories "${VDM_CONTAINER_TYPE}/available/"; then
showError "There are no ${VDM_CONTAINER_TYPE^} containers available."
else
# set some local variables
local vdm_delete_me
local container
# saved the file
showNotice "Only delete containers of which you have made absolutely sure it's no longer needed! Better to just disable them if all you want is to just take them down."
# get containers to enable
vdm_delete_me=$(getSelectedDirectories "Select container/s to delete." \
"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/" "Delete ${VDM_CONTAINER_TYPE^} Container/s")
# check that we have something, else return to main menu
if [ ${#vdm_delete_me} -ge 1 ]; then
# convert the string to and array
IFS=' ' read -r -a vdm_delete_me_array <<<"${vdm_delete_me[@]}"
# loop over the directories to build the
for containered in "${vdm_delete_me_array[@]}"; do
# remove the " from the string
container="${containered//\"/}"
# check if the container is still enabled
if [ -d "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}" ]; then
# make sure the docker image is stopped
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}/docker-compose.yml" down
# then remove soft link
rm -fr "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/enabled/${container}"
fi
# before deleting the config we ask to make sure
if (whiptail --yesno "Would you like to delete the (${container}) container's folder that holds the docker-compose.yml file?" \
--title "Delete Docker Compose Yaml" --backtitle "${BACK_TITLE}" 8 112); then
# then remove docker-compose.yml file
rm -fr "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${container}"
fi
done
fi
fi
}
#####################################################################################################################VDM
######################################## DELETE TRAEFIK
function traefik__TRuST__delete() {
# check if traefik has been setup
if [ ! -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" ]; then
showError "There is no ${VDM_CONTAINER_TYPE^} container to delete."
else
# make sure the docker image is stopped
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" down
# before deleting the config we ask to make sure
if (whiptail --yesno "Would you like to delete the ${VDM_CONTAINER_TYPE^} container's docker-compose.yml file?" \
--title "Delete Docker Compose Yaml" --backtitle "${BACK_TITLE}" 8 112); then
# then remove docker-compose.yml file
rm -fr "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml"
fi
fi
}
#####################################################################################################################VDM
######################################## DELETE PORTAINER
function portainer__TRuST__delete() {
# check if portainer has been setup
if [ ! -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" ]; then
showError "There is no ${VDM_CONTAINER_TYPE^} container to delete."
else
# make sure the docker image is stopped
docker-compose --file "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml" down
# before deleting the config we ask to make sure
if (whiptail --yesno "Would you like to delete the ${VDM_CONTAINER_TYPE^} container's docker-compose.yml file?" \
--title "Delete Docker Compose Yaml" --backtitle "${BACK_TITLE}" 8 112); then
# then remove docker-compose.yml file
rm -fr "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/docker-compose.yml"
fi
fi
}
#####################################################################################################################VDM
######################################## Migrate Joomla
function joomla__TRuST__migrate() {
# check if this type have available containers
if ! hasDirectories "${VDM_CONTAINER_TYPE}/available/"; then
showError "The path ${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/ does not exist or is empty, first run a ${VDM_CONTAINER_TYPE^} setup."
else
# set some local variables
local type_migration
local vdm_migrate_me
local container
# list containers... and allow selection to edit
container=$(getSelectedDirectory "Select the container you would like to migrate.\n[Only continue if you know what your doing!] (We will only move docker-composer.yml file)" \
"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/" '' "Migrate ${VDM_CONTAINER_TYPE^} Container")
# check that we have something, else return to main menu
if [ ${#container} -ge 1 ]; then
# add the parent dir back
vdm_migrate_me="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${container}/docker-compose.yml"
# check if this docker-composer.yml exist
if [ -f "${vdm_migrate_me}" ]; then
# select the type of migration
type_migration=$(getMigrationType)
# get remote system
remote_system=$(getRemoteSystem)
# make sure we have a remote
if [ ${#remote_system} -ge 2 ] && [ "${remote_system}" != "none_selected" ]; then
# give little heads-up
if (whiptail --yesno "${USER^}, you selected the container:<${container}> action:<${type_migration}> remote:<${remote_system}>\nIs this correct, and can we continue with the migration ${type_migration}?" \
--title "Confirm Migration ${type_migration^}" --backtitle "${BACK_TITLE}" 8 112); then
# run migration
"${type_migration}ContainerMigration" "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${container}" "${VDM_CONTAINER_TYPE}/available/${container}" "${remote_system}"
fi
else
showError "Migration cancelled since no remote system was selected."
fi
fi
fi
fi
}
#####################################################################################################################VDM
######################################## Migrate OPENSSH
function openssh__TRuST__migrate() {
# check if this type have available containers
if ! hasDirectories "${VDM_CONTAINER_TYPE}/available/"; then
showError "The path ${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/ does not exist or is empty, first run a ${VDM_CONTAINER_TYPE^} setup."
else
# set some local variables
local vdm_migrate_me
local container
# list containers... and allow selection to edit
container=$(getSelectedDirectory "Select the container you would like to migrate.\n[Only continue if you know what your doing!] (We will only move docker-composer.yml file)" \
"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/" '' "Migrate ${VDM_CONTAINER_TYPE^} Container")
# check that we have something, else return to main menu
if [ ${#container} -ge 1 ]; then
# add the parent dir back
vdm_migrate_me="${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${container}/docker-compose.yml"
# check if this docker-composer.yml exist
if [ -f "${vdm_migrate_me}" ]; then
# select the type of migration
type_migration=$(getMigrationType)
# get remote system
remote_system=$(getRemoteSystem)
# make sure we have a remote
if [ ${#remote_system} -ge 2 ] && [ "${remote_system}" != "none_selected" ]; then
# give little heads-up
if (whiptail --yesno "${USER^}, you selected the container:<${container}> action:<${type_migration}> remote:<${remote_system}>\nIs this correct, and can we continue with the migration ${type_migration}?" \
--title "Confirm Migration ${type_migration^}" --backtitle "${BACK_TITLE}" 8 112); then
# run migration
"${type_migration}ContainerMigration" "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/available/${container}" "${VDM_CONTAINER_TYPE}/available/${container}" "${remote_system}"
fi
else
showError "Migration cancelled since no remote system was selected."
fi
fi
fi
fi
}
#####################################################################################################################VDM
######################################## Migrate Directory
function directory__TRuST__migrate() {
# set some local variables
local vdm_migrate_me
local directory
# Would you also like to move a project folder
if hasDirectories '' "${VDM_PROJECT_PATH}"; then
# get project directories to migrate
directory=$(getSelectedDirectory "Select project directory to migrate.\n[Only continue if you know what your doing!]" \
"${VDM_PROJECT_PATH}" "Select Project Directory")
# check that we have something, else return to main menu
if [ ${#directory} -ge 1 ]; then
# add the parent dir back
vdm_migrate_me="${VDM_PROJECT_PATH}/${directory}"
# check that we have something
if [ -d "${vdm_migrate_me}" ]; then
# select the type of migration
type_migration=$(getMigrationType)
# get remote system
remote_system=$(getRemoteSystem)
# make sure we have a remote
if [ ${#remote_system} -ge 2 ] && [ "${remote_system}" != "none_selected" ]; then
# give little heads-up
if (whiptail --yesno "${USER^}, you selected the directory:<${directory}> action:<${type_migration}> remote:<${remote_system}>\nIs this correct, and can we continue with the migration ${type_migration}?" \
--title "Confirm Migration ${type_migration^}" --backtitle "${BACK_TITLE}" 8 112); then
# run migration
"${type_migration}DirectoryMigration" "${vdm_migrate_me}" "${directory}" "${remote_system}"
fi
else
showError "Migration cancelled since no remote system was selected."
fi
fi
fi
fi
}
#####################################################################################################################VDM
######################################## MENU ACTIONS
# setup a container
function setupContainer() {
# make sure the networks are set
setNetworks
# make sure of our container type
VDM_CONTAINER_TYPE="${1}"
VDM_TASK="setup"
# execute the task
main
}
# setup multiple containers
bulkSetupContainers() {
# make sure the networks are set
setNetworks
# make sure of our container type
VDM_CONTAINER_TYPE="${1}"
VDM_TASK="bulk"
# execute the task
main
}
# edit a container
function editContainer() {
# make sure of our container type
VDM_CONTAINER_TYPE="${1}"
VDM_TASK="edit"
# execute the task
main
}
# enable a container
function enableContainer() {
# make sure of our container type
VDM_CONTAINER_TYPE="${1}"
VDM_TASK="enable"
# execute the task
main
}
# disable a container
function disableContainer() {
# make sure of our container type
VDM_CONTAINER_TYPE="${1}"
VDM_TASK="disable"
# execute the task
main
}
# down containers
function downContainers() {
# make sure of our container type
VDM_CONTAINER_TYPE="${1}"
VDM_TASK="down"
# execute the task
main
}
# up containers
function upContainers() {
# make sure of our container type
VDM_CONTAINER_TYPE="${1}"
VDM_TASK="up"
# execute the task
main
}
# delete a container
function deleteContainer() {
# make sure of our container type
VDM_CONTAINER_TYPE="${1}"
VDM_TASK="delete"
# execute the task
main
}
# migrate a container
function migrateContainer() {
# make sure of our container type
VDM_CONTAINER_TYPE="${1}"
VDM_TASK="migrate"
# execute the task
main
}
# To fix the permissions of Joomla containers
function fixContainersPermissions() {
# check if we have persistent volumes
if [ ! -d "${VDM_PROJECT_PATH}" ]; then
showError "The ${VDM_PROJECT_PATH} does not exist."
elif ! hasDirectories '' "${VDM_PROJECT_PATH}"; then
showError "There are no persistent volumes in ${VDM_PROJECT_PATH} available."
else
# set some local variables
local vdm_fix_me
local persistent
# get containers to enable
vdm_fix_me=$(getSelectedDirectories "Select persistent volume to fix." \
"${VDM_PROJECT_PATH}" "Fix Joomla Permissions")
# check that we have something, else return to main menu
if [ ${#vdm_fix_me} -ge 1 ] && (whiptail --yesno "${USER^}, to fix these permissions we need sudo privileges." \
--title "Give sudo Privileges" --backtitle "${BACK_TITLE}" 8 112); then
# convert the string to and array
IFS=' ' read -r -a vdm_fix_me_array <<<"${vdm_fix_me[@]}"
# just to get sudo pass
sudo -v
# loop over the directories to build the
for volume in "${vdm_fix_me_array[@]}"; do
# remove the " from the string
persistent="${volume//\"/}"
# make sure this is a joomla system
if [ -d "${VDM_PROJECT_PATH}/${persistent}/joomla" ]; then
# show the notice of the volume being fixed
showNotice "Fixing ${persistent}/joomla permissions now."
# if this is our octoleo images we can also set the user ID and user-group ID
setContainerUser "$(id -u)"
### Fix the folder ownership of Joomla folders
# id -u www-data
# id -g www-data
#
progressSwitchOn
{
sudo chown -R "$VDM_PUID":"$VDM_PGID" "${VDM_PROJECT_PATH}/${persistent}/joomla"
progressSwitchOff
} &
showProgress "Setting the ownership of ${persistent} Joomla directory/files.\n(chown -R $VDM_PUID:$VDM_PGID ${persistent}/joomla)"
### Fix the folder permissions for the Joomla websites
#
# Change the file permissions
progressSwitchOn
{
sudo find "${VDM_PROJECT_PATH}/${persistent}/joomla" -type f -exec chmod 644 {} \;
[ -f "${VDM_PROJECT_PATH}/${persistent}/joomla/configuration.php" ] &&
sudo chmod 444 "${VDM_PROJECT_PATH}/${persistent}/joomla/configuration.php"
[ -f "${VDM_PROJECT_PATH}/${persistent}/joomla/.htaccess" ] &&
sudo chmod 400 "${VDM_PROJECT_PATH}/${persistent}/joomla/.htaccess"
[ -f "${VDM_PROJECT_PATH}/${persistent}/joomla/php.ini" ] &&
sudo chmod 400 "${VDM_PROJECT_PATH}/${persistent}/joomla/php.ini"
# at last we are done
progressSwitchOff
} &
showProgress "Setting the files permissions for the ${persistent} Joomla website.\n(find ${persistent}/joomla -type f -exec chmod 644 {} \;)"
# Change the folder permissions
progressSwitchOn
{
sudo find /"home/${USER}/Projects/${persistent}/joomla" -type d -exec chmod 755 {} \;
# lock jetbrains folder
[ -e "${VDM_PROJECT_PATH}/${persistent}/joomla/.idea" ] && {
sudo chmod -R 700 "${VDM_PROJECT_PATH}/${persistent}/joomla/.idea"
# add a locking .htaccess file and set its access
lockFolder >"${VDM_PROJECT_PATH}/${persistent}/joomla/.idea/.htaccess"
sudo chmod 400 "${VDM_PROJECT_PATH}/${persistent}/joomla/.idea/.htaccess"
}
# lock hidden folder
[ -e "${VDM_PROJECT_PATH}/${persistent}/joomla/.hidden" ] && {
sudo chmod -R 700 "${VDM_PROJECT_PATH}/${persistent}/joomla/.hidden"
# add a locking .htaccess file and set its access
lockFolder >"${VDM_PROJECT_PATH}/${persistent}/joomla/.hidden/.htaccess"
sudo chmod 400 "${VDM_PROJECT_PATH}/${persistent}/joomla/.hidden/.htaccess"
}
# lock git folder
[ -e "${VDM_PROJECT_PATH}/${persistent}/joomla/.git" ] && {
sudo chmod -R 700 "${VDM_PROJECT_PATH}/${persistent}/joomla/.git"
# add a locking .htaccess file and set its access
lockFolder >"${VDM_PROJECT_PATH}/${persistent}/joomla/.git/.htaccess"
sudo chmod 400 "${VDM_PROJECT_PATH}/${persistent}/joomla/.git/.htaccess"
}
# lock the tmp folder
[ -e "${VDM_PROJECT_PATH}/${persistent}/joomla/tmp" ] && {
sudo chmod -R 700 "${VDM_PROJECT_PATH}/${persistent}/joomla/tmp"
# add a locking .htaccess file and set its access
# lockFolder > "${VDM_PROJECT_PATH}/${persistent}/joomla/tmp/.htaccess"
# sudo chmod 400 "${VDM_PROJECT_PATH}/${persistent}/joomla/tmp/.htaccess"
}
# at last we are done
progressSwitchOff
} &
showProgress "Setting the directory permissions for the ${persistent} Joomla website.\n(find ${persistent}/joomla -type d -exec chmod 755 {} \;)"
# Change the image folder permissions
# chmod 707 "${VDM_PROJECT_PATH}/${persistent}/joomla/images"
# chmod 707 "${VDM_PROJECT_PATH}/${persistent}/joomla/images/stories"
#
# get current user ID
user_id="$(id -u)"
# check if the current user mismatch
if [ "$user_id" != "$VDM_PUID" ]; then
# Check if the setfacl command is installed
# shellcheck disable=SC2015
if command -v setfacl >/dev/null 2>&1; then
### Fix the folder permissions so the active user (1000) can access the files
progressSwitchOn
{
sudo setfacl -R -m u:"$USER":rwx "${VDM_PROJECT_PATH}/${persistent}/joomla"
progressSwitchOff
} &
showProgress "Setting the permissions of ${persistent} Joomla so user:$USER can access and edit them both the files and folders."
else
showError "[ERROR] Could not fix the permissions of the ${persistent} Joomla so user:$USER can access them.\n\n\
You will need to install: setfacl for this option to work, then run this fix again."
fi
elif command -v setfacl >/dev/null 2>&1; then
# we remove the acl map if it was set before
sudo setfacl -R -b "${VDM_PROJECT_PATH}/${persistent}/joomla"
fi
### Fix the folder ownership of database folders
# id -u systemd-coredump
# id -g systemd-coredump
#
progressSwitchOn
{
sudo chown -R 999:999 "${VDM_PROJECT_PATH}/${persistent}/db"
progressSwitchOff
} &
showProgress "Setting the ownership of ${persistent} database directory/files.\n(chown -R 999:999 ${persistent}/db)"
### Fix the folder permissions for the database files
#
# Change the file permissions
progressSwitchOn
{
sudo find "${VDM_PROJECT_PATH}/${persistent}/db" -type f -exec chmod 660 {} \;
progressSwitchOff
} &
showProgress "Setting the file permissions for the ${persistent} database.\n(find ${persistent}/db -type f -exec chmod 660 {} \;)"
progressSwitchOn
{
sudo find "${VDM_PROJECT_PATH}/${persistent}/db" -type d -exec chmod 700 {} \;
progressSwitchOff
} &
showProgress "Setting the directory permissions for the ${persistent} database.\n(find ${persistent}/db -type d -exec chmod 700 {} \;)"
# show the completion of this permission fix
showNotice "Permissions update completed!"
else
showError "${VDM_PROJECT_PATH}/${persistent} is not a joomla persistent volume and was skipped."
fi
done
fi
fi
}
# delete persistent volumes
function deletePersistentVolumes() {
# we first check if we have some volumes
if hasDirectories '' "${VDM_PROJECT_PATH}"; then
# set some local variables
local vdm_delete_volumes
local persistent
# saved the file
showNotice "Only delete persistent volumes of which you have made absolutely sure it's no longer in use!"
# get containers to enable
vdm_delete_volumes=$(getSelectedDirectories "Select persistent volume\s to delete." \
"${VDM_PROJECT_PATH}" "Select Persistent Volume\s to Delete")
# check that we have something, else return to main menu
if [ ${#vdm_delete_volumes} -ge 1 ]; then
# convert the string to and array
IFS=' ' read -r -a vdm_delete_volumes_array <<<"${vdm_delete_volumes[@]}"
# loop over the directories to build the
for volumes in "${vdm_delete_volumes_array[@]}"; do
# remove the " from the string
persistent="${volumes//\"/}"
# last serious check and then its gone
if [ -d "${VDM_PROJECT_PATH}/${persistent}" ] &&
(whiptail --yesno "Are you absolutely sure you would like to delete this (${persistent}) persistent volume? THIS CAN'T BE UNDONE!\n(we need sudo privileges)" \
--title "Delete Persistent Volume" --backtitle "${BACK_TITLE}" 15 112); then
# then remove soft link
sudo rm -rf "${VDM_PROJECT_PATH}/${persistent}"
fi
done
fi
else
showError "There are no persistent volumes found in ${VDM_PROJECT_PATH}."
fi
}
# make an update
function runUpdate() {
# we need sudo permissions
if (whiptail --yesno "${USER^}, to update ${PROGRAM_NAME} we need sudo privileges." \
--title "Give sudo Privileges" --backtitle "${BACK_TITLE}" 8 112); then
# remove the current version
if [ -f /usr/local/bin/octojoom ]; then
# just backup in case of failure
sudo mv /usr/local/bin/octojoom /usr/local/bin/octojoom.bak
fi
# some local values
local branch
# get the target branch to use in our update
isExpert && branch=$(getTargetBranch)
# pull the latest version. Master is always the latest
if sudo curl --fail -L "https://git.vdm.dev/api/v1/repos/octoleo/octojoom/raw/src/octojoom?ref=${branch:-master}" -o /usr/local/bin/octojoom 2>/dev/null; then
# give success message
echo "SUCCESS: Update was successful."
# do we have a backup
if [ -f /usr/local/bin/octojoom.bak ]; then
# lets remove it now
sudo rm -f /usr/local/bin/octojoom.bak
fi
else
# show the error
echo >&2 "ERROR: Update failed! Please try again later."
# do we have a backup
if [ -f /usr/local/bin/octojoom.bak ]; then
# move backup back
sudo mv /usr/local/bin/octojoom.bak /usr/local/bin/octojoom
fi
fi
# always set the permission again if we have a file
if [ -f /usr/local/bin/octojoom ]; then
# the we make sure its executable
sudo chmod +x /usr/local/bin/octojoom
fi
# always exit so the new script can load
quitProgram
fi
}
# make an uninstall
function runUninstall() {
# little notice
showNotice "We have three uninstall options: 1) Complete. 2) Just Script. 3) Make your selection."
# first safety check
if (whiptail --yesno "We are just trying to be careful here, therefore we have a few questions. Please remember there is an auto update option!\n\
Are you absolutely sure you want to continue with the uninstalling process?\n(we need sudo privileges)" \
--defaultno --title "Uninstalling ${PROGRAM_NAME} v${_VERSION} " --backtitle "${BACK_TITLE}" 15 112); then
# we have four main options
if (whiptail --yesno "Okay, So do you want to completely remove everything? This is the most dangerous option! IT CAN'T BE UNDONE!\
We will remove literally everything like this script was never here." \
--defaultno --title "Complete Uninstall of ${PROGRAM_NAME} v${_VERSION} " --backtitle "${BACK_TITLE}" 12 112); then
if [ -d "${VDM_REPO_PATH}/joomla" ]; then
# take down all joomla containers
downContainers 'joomla'
# now completely remove Joomla configurations
sudo rm -fr "${VDM_REPO_PATH}/joomla"
fi
# Remove all of Openssh Docker stuff
if [ -d "${VDM_REPO_PATH}/openssh" ]; then
# take down all joomla containers
downContainers 'openssh'
# now completely remove Joomla configurations
sudo rm -fr "${VDM_REPO_PATH}/openssh"
fi
# Remove all of Portainer Docker stuff
if [ -d "${VDM_REPO_PATH}/portainer" ]; then
# take down all portainer containers
disableContainer 'portainer'
# now completely remove Portainer configurations
sudo rm -fr "${VDM_REPO_PATH}/portainer"
fi
# Remove all of Traefik Docker stuff
if [ -d "${VDM_REPO_PATH}/traefik" ]; then
# take down all traefik containers
disableContainer 'traefik'
# now completely remove Traefik configurations
sudo rm -fr "${VDM_REPO_PATH}/traefik"
fi
# remove config if found
if [ -d "${VDM_SRC_PATH}" ]; then
sudo rm -fr "${VDM_SRC_PATH}"
fi
# remove config if found
if [ -d "${VDM_REPO_PATH}" ]; then
sudo rm -fr "${VDM_REPO_PATH}"
fi
elif (whiptail --yesno "Would you like to only remove the actual ${PROGRAM_NAME} v${_V} script but keep all the Docker stuff?" \
--title "Keep Docker Stuff" --backtitle "${BACK_TITLE}" 8 112); then
# now remove the octojoom script
if [ -f /usr/local/bin/octojoom ]; then
sudo rm -f /usr/local/bin/octojoom
fi
# give the final message
whiptail --title "${PROGRAM_NAME} v${_VERSION} is UNINSTALLED" --msgbox "\n\
${PROGRAM_NAME} v${_V} has been uninstalled.\n\n\
We have not touched any of the Docker stuff.\n\
To also remove these you will have to manually pull down the Docker containers (if there are any running) and then remove the following directories.\n\n\
DOCKER: ${VDM_REPO_PATH} \n\
VOLUMES: ${VDM_PROJECT_PATH} \n\
CONFIG: ${VDM_SRC_PATH}" --backtitle "${BACK_TITLE}" 20 112
# we exit here... where done!
quitProgram
else
# little notice
showNotice "This option lets you choose what you keep, so read the questions carefully! IT CAN'T BE UNDONE!"
# shellcheck disable=SC1090
# ----------------------------------------------------- MULTI CONTAINERS
# Remove all of Joomla Docker stuff
if [ -d "${VDM_REPO_PATH}/joomla" ] &&
(whiptail --yesno "Would you like to completely remove the Joomla Docker yaml configurations in (${VDM_REPO_PATH}/joomla)?" \
--defaultno --title "Remove Docker Config" --backtitle "${BACK_TITLE}" 12 112); then
# take down all joomla containers
downContainers 'joomla'
# now completely remove Joomla configurations
sudo rm -fr "${VDM_REPO_PATH}/joomla"
fi
# check if we have possible joomla containers (this will only run if they did not remove it above)
if [ -e "${VDM_REPO_PATH}/joomla/enabled" ] &&
(whiptail --yesno "Would you like to take down Joomla containers?" \
--defaultno --title "Take Down Containers" --backtitle "${BACK_TITLE}" 8 112); then
# take down all joomla containers
downContainers 'joomla'
# remove all enabled
sudo rm -fr "${VDM_REPO_PATH}/joomla/enabled"
fi
# Remove all of Openssh Docker stuff
if [ -d "${VDM_REPO_PATH}/openssh" ] &&
(whiptail --yesno "Would you like to completely remove the Openssh Docker yaml configurations in (${VDM_REPO_PATH}/openssh)?" \
--defaultno --title "Remove Docker Config" --backtitle "${BACK_TITLE}" 12 112); then
# take down all joomla containers
downContainers 'openssh'
# now completely remove Joomla configurations
sudo rm -fr "${VDM_REPO_PATH}/openssh"
fi
# check if we have possible openssh containers (this will only run if they did not remove it above)
if [ -e "${VDM_REPO_PATH}/openssh/enabled" ] &&
(whiptail --yesno "Would you like to take down Openssh containers?" \
--defaultno --title "Take Down Containers" --backtitle "${BACK_TITLE}" 8 112); then
# take down all joomla containers
downContainers 'openssh'
# remove all enabled
sudo rm -fr "${VDM_REPO_PATH}/openssh/enabled"
fi
# ----------------------------------------------------- SINGLE CONTAINER
# Remove all of Portainer Docker stuff
if [ -d "${VDM_REPO_PATH}/portainer" ] &&
(whiptail --yesno "Would you like to completely remove the Portainer Docker yaml configurations in (${VDM_REPO_PATH}/portainer)?" \
--defaultno --title "Remove Docker Config" --backtitle "${BACK_TITLE}" 12 112); then
# take down all portainer containers
disableContainer 'portainer'
# now completely remove Portainer configurations
sudo rm -fr "${VDM_REPO_PATH}/portainer"
fi
# check if we have possible portainer container (this will only run if they did not remove it above)
if [ -f "${VDM_REPO_PATH}/portainer/docker-compose.yml" ] &&
(whiptail --yesno "Would you like to take down Portainer container?" \
--defaultno --title "Take Down Container" --backtitle "${BACK_TITLE}" 8 112); then
# take down the container
disableContainer 'portainer'
fi
# Remove all of Traefik Docker stuff
if [ -d "${VDM_REPO_PATH}/traefik" ] &&
(whiptail --yesno "Would you like to completely remove the Traefik Docker yaml configurations in (${VDM_REPO_PATH}/traefik)?" \
--defaultno --title "Remove Docker Config" --backtitle "${BACK_TITLE}" 12 112); then
# take down all traefik containers
disableContainer 'traefik'
# now completely remove Traefik configurations
sudo rm -fr "${VDM_REPO_PATH}/traefik"
fi
# check if we have possible traefik container (this will only run if they did not remove it above)
if [ -f "${VDM_REPO_PATH}/traefik/docker-compose.yml" ] &&
(whiptail --yesno "Would you like to take down Traefik container?" \
--defaultno --title "Take Down Container" --backtitle "${BACK_TITLE}" 8 112); then
# take down the container
disableContainer 'traefik'
fi
# remove config if found
if [ -d "${VDM_SRC_PATH}" ] &&
(whiptail --yesno "Would you like to remove the global docker configurations?" \
--defaultno --title "Remove Docker Config" --backtitle "${BACK_TITLE}" 8 112); then
sudo rm -fr "${VDM_SRC_PATH}"
fi
fi
# now remove the octojoom script
if [ -f /usr/local/bin/octojoom ]; then
sudo rm -f /usr/local/bin/octojoom
fi
# last and final question as this is most dangerous and serious issue.
if [ -d "${VDM_PROJECT_PATH}" ] &&
(whiptail --yesno "Last question, would you like to remove all persistent volumes of your containers in (${VDM_PROJECT_PATH})?" \
--defaultno --title "Completely DELETE persistent volumes" --backtitle "${BACK_TITLE}" 12 112); then
sudo rm -rf "${VDM_PROJECT_PATH}"
fi
# give the final message
whiptail --title "${PROGRAM_NAME} v${_VERSION} is UNINSTALLED" --msgbox "\n\n\
${PROGRAM_NAME} v${_V} has been uninstalled." --backtitle "${BACK_TITLE}" 10 112
# exit the program right now
quitProgram
fi
}
# we show the octoleo info quietly
octojoomQuietly() {
local message
# now set the message
message=" https://git.vdm.dev/octoleo/octojoom
Welcome to an Octoleo Program (${PROGRAM_NAME} v$_VERSION)
Description
With this script we can easily deploy docker containers of Joomla and Openssh.
This combination of these tools give rise to a powerful and very secure shared
development environment.
This program has **command input** options as seen in the menus item called
**Show command help**, but these commands are _not the only way_ to set these
values. When the values are **omitted** you will be _asked in the terminal_ to
manually enter the required values as needed. Furthermore, the use of
**env variables** are also heavily used across the script. There are more
than one .env file and the script will set those up for you whenever you run a
task that make use of env variables. The script will check if those values exist,
and if they don't it will ask for them, and store them automatically for future use.
That same time the output message to the terminal will show you where the specific
.env file can be found.
Author Licence
Llewellyn van der Merwe <octoleo@vdm.io> GNU GENERAL PUBLIC LICENSE Version 2
--quiet"
whiptail --msgbox "${message}" --fb --backtitle "${BACK_TITLE}" 32 112
}
# show the commands help menu
function showCommandsHelpMenu() {
help=$(showHelp)
whiptail --msgbox --scrolltext "${help}" --fb --backtitle "${BACK_TITLE}" 30 90
}
#####################################################################################################################VDM
######################################## MENUS
# show Joomla menu
function showJoomla() {
# menu for dynamic addition
local menu_options=()
# our counter
local i=3
# load the back menu
menu_options+=("back" "<-- Return to the main menu.")
# setup new container
menu_options+=("setup" "Setup new container")
# enable existing container
hasDirectories 'joomla/available' &&
menu_options+=("enable" "Enable existing container") && i=$((i + 1))
# disable enabled container
hasDirectories 'joomla/enabled' &&
menu_options+=("disable" "Disable enabled container") && i=$((i + 1))
# take all enabled containers down
hasDirectories 'joomla/enabled' &&
menu_options+=("down" "Take all enabled containers down") && i=$((i + 1))
# pull up all enabled containers
hasDirectories 'joomla/enabled' &&
menu_options+=("up" "Pull up all enabled containers") && i=$((i + 1))
# edit available container
isExpert && hasDirectories 'joomla/available' &&
menu_options+=("edit" "Edit available container") && i=$((i + 1))
# fix permissions
hasDirectories '' "${VDM_PROJECT_PATH}" &&
menu_options+=("fix" "Fix permissions of folders and files of a container") &&
i=$((i + 1))
# delete a container
hasDirectories 'joomla/available' &&
menu_options+=("delete" "Delete a container") && i=$((i + 1))
# Get Joomla env details
isExpert && hasDirectories 'joomla/available' &&
menu_options+=("joomla_env" "Open Joomla .env Details") && i=$((i + 1))
# bulk deploy
isExpert && menu_options+=("bulk" "Bulk deploy") && i=$((i + 1))
# Quit Octoleo Program
menu_options+=("quit" "Quit ${PROGRAM_NAME}")
# get the selection
CHOICE=$(
whiptail --menu "Make your selection" 20 112 $i \
--title "Joomla | ${PROGRAM_NAME} v${_V}" --fb \
--backtitle "${BACK_TITLE}" --nocancel --notags \
"${menu_options[@]}" 3>&2 2>&1 1>&3
)
# menu actions
case $CHOICE in
"setup")
setupContainer 'joomla'
;;
"edit")
editContainer 'joomla'
;;
"enable")
enableContainer 'joomla'
;;
"disable")
disableContainer 'joomla'
;;
"down")
downContainers 'joomla'
;;
"up")
upContainers 'joomla'
;;
"fix")
fixContainersPermissions
;;
"delete")
deleteContainer 'joomla'
;;
"joomla_env")
openEnv 'joomla'
;;
"bulk")
bulkSetupContainers 'joomla'
;;
"quit") quitProgram ;;
esac
# menu loop
case $CHOICE in
"setup" | "edit" | "enable" | "disable" | "down" | "up" | "fix" | "delete" | "joomla_env" | "bulk")
showJoomla
;;
esac
}
# show Openssh menu
function showOpenssh() {
# menu for dynamic addition
local menu_options=()
# our counter
local i=3
# load the back menu
menu_options+=("back" "<-- Return to the main menu.")
# setup new container
menu_options+=("setup" "Setup new container")
# enable existing container
hasDirectories 'openssh/available' &&
menu_options+=("enable" "Enable existing container") && i=$((i + 1))
# disable enabled container
hasDirectories 'openssh/enabled' &&
menu_options+=("disable" "Disable enabled container") && i=$((i + 1))
# take all enabled containers down
hasDirectories 'openssh/enabled' &&
menu_options+=("down" "Take all enabled containers down") && i=$((i + 1))
# pull up all enabled containers
hasDirectories 'openssh/enabled' &&
menu_options+=("up" "Pull up all enabled containers") && i=$((i + 1))
# edit available container
isExpert && hasDirectories 'openssh/available' &&
menu_options+=("edit" "Edit available container") && i=$((i + 1))
# delete a container
hasDirectories 'openssh/available' &&
menu_options+=("delete" "Delete a container") && i=$((i + 1))
# Get Openssh env details
isExpert && hasDirectories 'openssh/available' &&
menu_options+=("openssh_env" "Open Openssh .env Details") && i=$((i + 1))
# Quit Octoleo Program
menu_options+=("quit" "Quit ${PROGRAM_NAME}")
# get the selection
CHOICE=$(
whiptail --menu "Make your selection" 20 112 $i \
--title "Openssh | ${PROGRAM_NAME} v${_V}" --fb \
--backtitle "${BACK_TITLE}" --nocancel --notags \
"${menu_options[@]}" 3>&2 2>&1 1>&3
)
case $CHOICE in
"setup")
setupContainer 'openssh'
;;
"edit")
editContainer 'openssh'
;;
"enable")
enableContainer 'openssh'
;;
"disable")
disableContainer 'openssh'
;;
"down")
downContainers 'openssh'
;;
"up")
upContainers 'openssh'
;;
"delete")
deleteContainer 'openssh'
;;
"openssh_env")
openEnv 'openssh'
;;
"quit") quitProgram ;;
esac
# menu loop
case $CHOICE in
"setup" | "edit" | "enable" | "disable" | "down" | "up" | "delete" | "openssh_env" )
showOpenssh
;;
esac
}
# show Traefik menu
function showTraefik() {
# menu for dynamic addition
local menu_options=()
# our counter
local i=3
# load the back menu
menu_options+=("back" "<-- Return to the main menu.") && i=$((i + 1))
# setup new container
menu_options+=("setup" "Setup or rebuild Traefik")
# enable existing container
[ -f "${VDM_REPO_PATH}/traefik/docker-compose.yml" ] &&
menu_options+=("enable" "Enable Traefik") && i=$((i + 1))
# disable enabled container
[ -f "${VDM_REPO_PATH}/traefik/docker-compose.yml" ] &&
menu_options+=("disable" "Disable Traefik") && i=$((i + 1))
# edit available container
isExpert && [ -f "${VDM_REPO_PATH}/traefik/docker-compose.yml" ] &&
menu_options+=("edit" "Edit Traefik") && i=$((i + 1))
# delete traefik container
[ -f "${VDM_REPO_PATH}/traefik/docker-compose.yml" ] &&
menu_options+=("delete" "Delete Traefik") && i=$((i + 1))
# Quit Octoleo Program
menu_options+=("quit" "Quit ${PROGRAM_NAME}")
# get the selection
CHOICE=$(
whiptail --menu "Make your selection" 20 112 $i \
--title "Traefik | ${PROGRAM_NAME} v${_V}" --fb \
--backtitle "${BACK_TITLE}" --nocancel --notags \
"${menu_options[@]}" 3>&2 2>&1 1>&3
)
# menu actions
case $CHOICE in
"setup")
setupContainer 'traefik'
;;
"edit")
editContainer 'traefik'
;;
"enable")
enableContainer 'traefik'
;;
"disable")
disableContainer 'traefik'
;;
"delete")
deleteContainer 'traefik'
;;
"quit") quitProgram ;;
esac
# menu loop
case $CHOICE in
"setup" | "edit" | "enable" | "disable" | "delete")
showTraefik
;;
esac
}
# show Portainer menu
function showPortainer() {
# menu for dynamic addition
local menu_options=()
# our counter
local i=3
# load the back menu
menu_options+=("back" "<-- Return to the main menu.")
# setup new container
menu_options+=("setup" "Setup or rebuild Portainer")
# enable existing container
[ -f "${VDM_REPO_PATH}/portainer/docker-compose.yml" ] &&
menu_options+=("enable" "Enable Portainer") && i=$((i + 1))
# disable enabled container
[ -f "${VDM_REPO_PATH}/portainer/docker-compose.yml" ] &&
menu_options+=("disable" "Disable Portainer") && i=$((i + 1))
# edit available container
isExpert && [ -f "${VDM_REPO_PATH}/portainer/docker-compose.yml" ] &&
menu_options+=("edit" "Edit Portainer") && i=$((i + 1))
# delete traefik container
[ -f "${VDM_REPO_PATH}/portainer/docker-compose.yml" ] &&
menu_options+=("delete" "Delete Portainer") && i=$((i + 1))
# Quit Octoleo Program
menu_options+=("quit" "Quit ${PROGRAM_NAME}")
# get the selection
CHOICE=$(
whiptail --menu "Make your selection" 20 112 $i \
--title "Portainer | ${PROGRAM_NAME} v${_V}" --fb \
--backtitle "${BACK_TITLE}" --nocancel --notags \
"${menu_options[@]}" 3>&2 2>&1 1>&3
)
# menu actions
case $CHOICE in
"setup")
setupContainer 'portainer'
;;
"edit")
editContainer 'portainer'
;;
"enable")
enableContainer 'portainer'
;;
"disable")
disableContainer 'portainer'
;;
"delete")
deleteContainer 'portainer'
;;
"quit") quitProgram ;;
esac
# menu loop
case $CHOICE in
"setup" | "edit" | "enable" | "disable" | "delete")
showPortainer
;;
esac
}
# show systems help menu
function showSettings() {
# menu for dynamic addition
local menu_options=()
# our counter
local i=8
# load the back menu
menu_options+=("back" "<-- Return to the main menu.")
# the mode switch
isExpert && menu_options+=("basic-mode" "Switch to basic mode")
! isExpert && menu_options+=("expert-mode" "Switch to expert mode")
i=$((i + 1))
# Show command help
menu_options+=("command-help" "Help with commands")
# Show folder paths
menu_options+=("important-paths" "Important paths")
# Edit the global config
isExpert && [ -f "${VDM_SRC_PATH}/.env" ] &&
menu_options+=("edit-config" "Edit Config") && i=$((i + 1))
# the remote-control option
isExpert && menu_options+=("remote" "Access Remote ${PROGRAM_NAME}") && i=$((i + 1))
# Report an Issue
menu_options+=("report-issue" "Report an issue")
# Update the whole script
menu_options+=("update" "Update ${PROGRAM_NAME,,}")
# Uninstall the whole script
menu_options+=("uninstall" "Uninstall ${PROGRAM_NAME,,}")
# Octoleo details
menu_options+=("octojoom" "${PROGRAM_NAME}")
# Quit Octoleo Program
menu_options+=("quit" "Quit ${PROGRAM_NAME}")
# get the selection
CHOICE=$(
whiptail --menu "Make your selection" 20 112 $i \
--title "Settings Menu | ${PROGRAM_NAME} v${_V}" --fb \
--backtitle "${BACK_TITLE}" --nocancel --notags \
"${menu_options[@]}" 3>&2 2>&1 1>&3
)
# menu actions
case $CHOICE in
"basic-mode")
setMode 'basic'
;;
"expert-mode")
setMode 'expert'
;;
"command-help")
showCommandsHelpMenu
;;
"important-paths")
showImportantPaths
;;
"edit-config")
editConfigFile
;;
"remote")
hasRemoteSystemSet && connectToRemoteSystem
;;
"report-issue")
showLink "https://git.vdm.dev/octoleo/octojoom/issues" "To report an issue go to:" "Report an Issue"
;;
"update")
runUpdate
;;
"uninstall")
runUninstall
;;
"octojoom")
octojoomQuietly
;;
"quit") quitProgram ;;
esac
# menu loop
case $CHOICE in
"basic-mode" | "expert-mode" | "command-help" | "important-paths" | "edit-config" | "report-issue" | "octojoom" | "remote")
showSettings
;;
esac
}
# show domains menu
function domainsMenu() {
# menu for dynamic addition
local menu_options=()
# our counter
local i=3
# load the back menu
menu_options+=("back" "<-- Return to the main menu.")
# add more domains
allowMultiDomains &&
menu_options+=("add" "Add Domain") && i=$((i + 1))
# remove existing domains
[ -f "${VDM_SRC_PATH}/.domains" ] &&
menu_options+=("delete" "Delete Domain") && i=$((i + 1))
# edit available container
isExpert && allowEditHostFile &&
menu_options+=("edit" "Edit Host File") && i=$((i + 1))
# Quit Octoleo Program
menu_options+=("quit" "Quit ${PROGRAM_NAME}")
# get the selection
CHOICE=$(
whiptail --menu "Make your selection" 20 112 $i \
--title "Domains Menu | ${PROGRAM_NAME} v${_V}" --fb \
--backtitle "${BACK_TITLE}" --nocancel --notags \
"${menu_options[@]}" 3>&2 2>&1 1>&3
)
# menu actions
case $CHOICE in
"add")
setMultiDomains
;;
"delete")
deleteMultiDomains
;;
"edit")
editHostFile
;;
"quit") quitProgram ;;
esac
# menu loop
case $CHOICE in
"add" | "delete" | "edit")
domainsMenu
;;
esac
}
# show migration menu
function migrateMenu() {
# menu for dynamic addition
local menu_options=()
# our counter
local i=4
# load the back menu
menu_options+=("back" "<-- Return to the main menu.")
# Select a joomla container to migrate
menu_options+=("joomla" "Migrate Joomla Container")
# Select a openssh container to migrate
menu_options+=("openssh" "Migrate Openssh Container")
# Select project directories to migrate
hasDirectories '' "${VDM_PROJECT_PATH}" &&
menu_options+=("directory" "Migrate Project Directory") && i=$((i + 1))
# the remote-control option
isExpert && menu_options+=("remote" "Access Remote ${PROGRAM_NAME}") && i=$((i + 1))
# Quit Octoleo Program
menu_options+=("quit" "Quit ${PROGRAM_NAME}")
# get the selection
CHOICE=$(
whiptail --menu "Make your selection" 20 112 $i \
--title "Migration Menu | ${PROGRAM_NAME} v${_V}" --fb \
--backtitle "${BACK_TITLE}" --nocancel --notags \
"${menu_options[@]}" 3>&2 2>&1 1>&3
)
# menu actions
case $CHOICE in
"joomla")
migrateContainer 'joomla'
;;
"openssh")
migrateContainer 'openssh'
;;
"directory")
migrateContainer 'directory'
;;
"remote")
connectToRemoteSystem
;;
"quit") quitProgram
;;
esac
# menu loop
case $CHOICE in
"joomla" | "openssh" | "directory" | "remote")
migrateMenu
;;
esac
}
# MAIN MENU
function mainMenu() {
# get the selection
while true; do
# menu for dynamic addition
local menu_options=()
# our counter
local i=6
# Joomla containers
menu_options+=("joomla" "Joomla Containers")
# Openssh containers
menu_options+=("openssh" "Openssh Containers")
# Traefik container
menu_options+=("traefik" "Traefik Container")
# Portainer container
menu_options+=("portainer" "Portainer Container")
# Manage Domains
if isExpert && (allowEditHostFile || allowMultiDomains); then
menu_options+=("domains" "Manage Domains")
i=$((i + 1))
fi
# Migrate available container
isExpert &&
menu_options+=("migrate" "Migration Options") && i=$((i + 1))
# Delete Persistent Volumes
isExpert && hasDirectories '' "${VDM_PROJECT_PATH}" &&
menu_options+=("delete" "Delete Persistent Volumes") && i=$((i + 1))
# Octoleo settings
menu_options+=("settings" "${PROGRAM_NAME} Settings")
# Quit Octoleo Program
menu_options+=("quit" "Quit ${PROGRAM_NAME}")
CHOICE=$(
whiptail --menu "Make your selection" 20 112 $i \
--title "${PROGRAM_NAME} v${_V}" --fb \
--backtitle "${BACK_TITLE}" --nocancel --notags \
"${menu_options[@]}" 3>&2 2>&1 1>&3
)
case $CHOICE in
"joomla")
showJoomla
;;
"openssh")
showOpenssh
;;
"traefik")
showTraefik
;;
"portainer")
showPortainer
;;
"domains")
domainsMenu
;;
"migrate")
hasRemoteSystemSet && migrateMenu
;;
"delete")
deletePersistentVolumes
;;
"settings")
showSettings
;;
"quit") quitProgram ;;
esac
done
}
#####################################################################################################################VDM
######################################## GENERAL SHARED FUNCTIONS
# show error
function showError() {
whiptail --title "ERROR | ${PROGRAM_NAME} v${_V}" --backtitle "${BACK_TITLE}" \
--msgbox "${1}" "${2:-12}" 112
}
# show info
function showInfo() {
whiptail --title "INFO | ${PROGRAM_NAME} v${_V}" --backtitle "${BACK_TITLE}" \
--infobox "${1}" "${2:-12}" 112
}
# show notice
function showNotice() {
whiptail --title "NOTICE | ${PROGRAM_NAME} v${_V}" --backtitle "${BACK_TITLE}" \
--msgbox "${1}" "${2:-12}" 112
}
# show link
function showLink() {
whiptail --title "${3:-Open Link} | ${PROGRAM_NAME} v${_V}" --backtitle "${BACK_TITLE}" \
--msgbox "${2:-To open the link click here:} ${1}" 8 112
}
# show progress bar
function showProgress() {
# some locals
local title
local message
local per
# get input
message="$1"
title="${2:-Please wait!}"
# our little loop progress
{
per=1
while (true); do
if ! inProgress; then
# we are finished, so we slow down to 100%
sleep .2
echo 88
sleep .2
echo 90
sleep .$((1 + "$RANDOM" % 6))
echo 98
sleep .$((1 + "$RANDOM" % 5))
echo 100
sleep .$((1 + "$RANDOM" % 5))
break
elif [[ "87" -eq "$per" ]]; then
# if it takes longer we loop
per="33"
fi
# sleep a little moment
sleep .$((1 + "$RANDOM" % 9))
echo $per
per=$((per + 1))
done
} | whiptail --title "${title}" --gauge "${message}" --backtitle "${BACK_TITLE}" 8 112 0
}
# turn on progress
function progressSwitchOn() {
echo "Progress ON" >"${VDM_SRC_PATH}/.progress"
}
# switch off the progress
function progressSwitchOff() {
rm -f "${VDM_SRC_PATH}/.progress"
}
# get the progress
function inProgress() {
if [ -f "${VDM_SRC_PATH}/.progress" ]; then
# found it
return 0
fi
# did not find it
return 1
}
# show important paths
function showImportantPaths() {
local message
# now set the message
message=" ${PROGRAM_NAME} v$_VERSION
We have a few important paths that you should know, and use to manually manage your setup.
DOCKER: ${VDM_REPO_PATH}
SOURCE: ${VDM_SRC_PATH}/.images-source
DOMAINS: ${VDM_SRC_PATH}/.domains
CONFIG: ${VDM_SRC_PATH}/.env
SSH: ${VDM_REPO_PATH}/openssh/.ssh
VOLUMES: ${VDM_PROJECT_PATH}
Then we have some key environment variable files that hold very useful and important information.
Since we do not store any passwords or other important details in the docker-compose.yml files
they are stored in >>these environment variable files<< and therefore we set these .env file
permission to (600) for security.
JOOMLA: ${VDM_REPO_PATH}/joomla/.env
OPENSSH: ${VDM_REPO_PATH}/openssh/.env
TRAEFIK: ${VDM_REPO_PATH}/traefik/.env
PORTAINER: ${VDM_REPO_PATH}/portainer/.env
Not all these files or folders may exist, they are created only when needed.
"
whiptail --msgbox "${message}" --fb --backtitle "${BACK_TITLE}" 32 112
}
# show show the Joomla config details
function showJoomlaConfigDetails() {
# load the env back to show if set previously
# shellcheck disable=SC1090
# [ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ] && source "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
# set some locals
local message
# now set the message
message=" ${PROGRAM_NAME} v$_VERSION
Running the Joomla container for the first time you will need these details:
--------------------------------------------------------------------
URL: ${VDM_HTTP_SCHEME}${VDM_SUBDOMAIN}.${VDM_DOMAIN}
DATABASE_HOST: mariadb${VDM_KEY}:3306
--------------------------------------------------------------------
VDM_${VDM_ENV_KEY^^}_DB: ${vdm_database_name}
VDM_${VDM_ENV_KEY^^}_DB_USER: ${vdm_database_user}
VDM_${VDM_ENV_KEY^^}_DB_PASS: ${vdm_database_pass}
VDM_${VDM_ENV_KEY^^}_DB_ROOT: ${vdm_database_rootpass}
--------------------------------------------------------------------
These details are securely stored in this environment variable file
${VDM_REPO_PATH}/joomla/.env
--------------------------------------------------------------------
Do not remove these details from the file, as it's used to deploy the container.
"
whiptail --msgbox "${message}" --fb --backtitle "${BACK_TITLE}" 30 112
}
# we must get a random key
function getRandomPass() {
local length="${1:-128}"
tr -dc 'A-HJ-NP-Za-km-z2-9' </dev/urandom | head -c "$length"
}
# we must get a random key
function getRandomName() {
local length="${1:-128}"
tr -dc 'A-Za-z' </dev/urandom | head -c "$length"
}
# Get input from the user using whiptail utility
# $1: Prompt message
# $2 (optional): Default input value
# $3 (optional): Title for the input dialog
function getInput() {
# set local var
local answer
# get the answer
answer=$(whiptail --inputbox "$1" 10 112 "${2:-}" --title "${3:-Get Input}" \
--backtitle "${BACK_TITLE}" --nocancel 3>&1 1>&2 2>&3)
# return the answer
echo "${answer}"
}
# get the input until is gotten
function getInputNow() {
local message
local default
local title
local answer=""
# get the values
message="${1:-Enter a value}"
default="${2:-}"
title="${3:-value}"
# get the value if not already set
while [ -z "$answer" ] || [ ${#answer} -le 1 ]; do
# get the value
answer=$(getInput "${message}" \
"${default}" "${title}")
# keep asking if empty or does exist
if [ ${#answer} -le 1 ]; then
showError "You must enter a $title"
fi
done
# return the answer
echo "${answer}"
}
# get a selected directory
function getSelectedDirectory() {
# the selected folder
local answer
# set the local path
local path="${2:-}"
# set local var
local folder="${3:-}"
# we start the selection array
local selected=()
# our counter
local i=0
# whiptail box size details
local description_lines
local height
# now check if this dir has sub dirs
if hasDirectories '' "$path"; then
# loop over the directory
for dir_ in "${path%/}/"*; do
# remove the full path
dir_="${dir_/$path/}"
# load the selection
[ "$folder" = "${dir_#/}" ] && selected+=("${dir_#/}" "${dir_#/}" "ON") || selected+=("${dir_#/}" "${dir_#/}" "OFF")
# increment our pointer
if [ "$i" -le 10 ]; then
i=$((i + 1))
fi
done
# Calculate the height based on the description length and directory count
description_lines=$(echo -e "${1}" | wc -l)
height=$((description_lines + i + 7))
# now make the selection
answer=$(whiptail --title "${4:-Make a Selection}" --radiolist \
"${1}" $height 112 $i \
"${selected[@]}" --backtitle "${BACK_TITLE}" --nocancel --notags 3>&1 1>&2 2>&3)
fi
# return the answer
echo "${answer:-$folder}"
}
# select multiple directories from one directory
function getSelectedDirectories() {
# the selected folder
local answer
# set the local path
local path="${2:-}"
# we start the selection array
local selected=()
# our counter
local i=0
# whiptail box size details
local description_lines
local height
# now check if this dir has sub dirs
if hasDirectories '' "$path"; then
# loop over the directory
for dir_ in "${path%/}/"*; do
# remove the full path
dir_="${dir_/$path/}"
# load the selection
selected+=("${dir_#/}" "${dir_#/}" "OFF")
# increment our pointer
if [ "$i" -le 10 ]; then
i=$((i + 1))
fi
done
# Calculate the height based on the description length and directory count
description_lines=$(echo -e "${1}" | wc -l)
height=$((description_lines + i + 7))
# now make the selection
answer=$(whiptail --title "${3:-Make a Selection}" --checklist\
"${1}" $height 112 $i \
"${selected[@]}" --backtitle "${BACK_TITLE}" --nocancel --notags 3>&1 1>&2 2>&3)
# return the answer
echo "${answer[@]}"
else
echo ''
fi
}
# create a yml new line with 3 indents
function getYMLine3() {
# return line
cat <<EOF
${1}
EOF
}
# create a yml new line with 2 indents
function getYMLine2() {
# return line
cat <<EOF
${1}
EOF
}
# create a yml new line with 1 indent
function getYMLine1() {
# return line
cat <<EOF
${1}
EOF
}
# get input from user
function getPassword() {
# set local var
local PASSWORD
# get the pass
PASSWORD=$(whiptail --passwordbox "$1" 10 112 "${2:-}" --title "${3:-Get Password}" \
--backtitle "${BACK_TITLE}"--nocancel 3>&1 1>&2 2>&3)
# return the password
echo "${PASSWORD}"
}
# get the target branch to use in update
function getTargetBranch() {
# now make the selection
answer=$(whiptail --title "Select Update Channel" \
--radiolist --backtitle "${BACK_TITLE}" --nocancel --notags \
"You can select the update channel you would like to use." 10 80 2 \
"master" "Stable Version" "ON" \
"staging" "Developer Version" "OFF" \
3>&1 1>&2 2>&3)
# return the answer (default master)
echo "${answer:-master}"
}
# get the target repository to use in update
function getImageSource() {
# we set some local stuff
local image
local image_source
local images_source
local default
local default_octojoom
# menu for dynamic addition
local menu_options=()
# our counter
local i=2
# set the defaults
default="joomla|https://hub.docker.com/_/joomla?tab=tags;https://raw.githubusercontent.com/joomla-docker/docker-joomla/master/docker-entrypoint.sh"
default_octojoom="llewellyn/joomla|https://hub.docker.com/r/llewellyn/joomla/tags;https://git.vdm.dev/octoleo/docker-joomla/raw/branch/octoleo/docker-entrypoint.sh"
# we only ask if we are in expert mode
if isExpert; then
# set the base images source
menu_options+=("${default}" "Joomla official image" "OFF")
menu_options+=("${default_octojoom}" "Octoleo Joomla image" "OFF")
# get existing source
if [ -f "${VDM_SRC_PATH}/.images-source" ] && readarray -t images_source <"${VDM_SRC_PATH}/.images-source"; then
# build the menus
if [ "${#images_source[@]}" -gt 0 ]; then
# loop source images
for image in "${images_source[@]}"; do
# the image name (get before first comma)
image_name="${image%%,*}"
# the image description (get after last comma)
image_desc="${image##*,}"
# make sure we have a value, and it is not the defaults already set
if [ "${#image_name}" -ge 1 ] && [ "${#image_desc}" -ge 1 ] &&
[ "${image_name}" != "${default}" ] && [ "${image_name}" != "${default_octojoom}" ]; then
# load the source name and description
menu_options+=("${image_name}" "${image_desc}" "OFF")
# increment our counter
i=$((i + 1))
fi
done
fi
fi
# now make the selection
image_source=$(whiptail --title "Select image source repository" \
--radiolist --backtitle "${BACK_TITLE}" --nocancel --notags \
"You can select the source of your Joomla! image." 10 80 $i \
"${menu_options[@]}" 3>&1 1>&2 2>&3)
fi
# return the answer (default joomla)
echo "${image_source:-$default}"
}
# get a list of domains locally set
function getListDomains() {
# get the separator
local separator="${1}"
# menu for dynamic addition
local menu_options=()
local domains
# get existing domains
if [ -f "${VDM_SRC_PATH}/.domains" ] && readarray -t domains <"${VDM_SRC_PATH}/.domains"; then
# check that we have values
if [ "${#domains[@]}" -gt 0 ]; then
# build the menu
for domain in "${domains[@]}"; do
# load the back menu
[ "${#domain}" -ge 1 ] && menu_options+=("${domain}")
done
# we show a list of options including the option to add another
# shellcheck disable=SC2005
echo "$(printf "${separator}%s" "${menu_options[@]}")"
fi
fi
}
# to set a global multiple domains file and values
function getMultiDomain() {
# we set some local stuff
local domain_name
local domains
# menu for dynamic addition
local menu_options=()
# our counter
local i=0
# always add the main domain or (default) first
# so we should always have a selection
saveMultiDomain "${VDM_DOMAIN}"
# now clear the main domain (in case we use getDomain)
unset VDM_DOMAIN
# get existing domains
if [ -f "${VDM_SRC_PATH}/.domains" ] && readarray -t domains <"${VDM_SRC_PATH}/.domains"; then
# build the menu
if [ "${#domains[@]}" -gt 0 ]; then
# loop domains
for domain in "${domains[@]}"; do
# load the domain if it has a length
[ "${#domain}" -ge 1 ] && menu_options+=("${domain}" "${domain}" "OFF")
# increment our counter
[ "${#domain}" -ge 1 ] && i=$((i + 1))
done
# make sure we have domains
if [ "${#menu_options[@]}" -gt 0 ]; then
# we show a list of options including the option to add another
domain_name=$(whiptail --title "Select a Domain" \
--radiolist --backtitle "${BACK_TITLE}" --nocancel --notags \
"Select a domain, or none to add another." 30 80 $i \
"${menu_options[@]}" 3>&1 1>&2 2>&3)
fi
fi
fi
# check if we have a selection
if [ "${domain_name:-none}" = 'none' ]; then
# we must let them enter the new domain name
getDomain 'Enter a domain name' 'Enter a Domain Name'
else
# set the new main domain
VDM_DOMAIN="${domain_name}"
# update the main domain
export VDM_DOMAIN
fi
# add for next time
saveMultiDomain "${VDM_DOMAIN}"
}
# set the VDM domain value
function getDomain() {
# set some locals
local message="Enter main domain name"
local title="Enter Main Domain"
local tld="${VDM_CONTAINER_TYPE:-vdm}"
# get the arg passed if any
message="${1:-$message}"
title="${2:-$title}"
# get the VDM Domain value if not already set
while [ ${#VDM_DOMAIN} -le 1 ] || [[ "${VDM_DOMAIN}" != *.* ]]; do
# get the value
VDM_DOMAIN=$(getInput "${message}\n[must have at least one dot]" \
"${USER:-octoleo}.${tld,,}" "${title}")
# keep asking if empty or does exist
if [ ${#VDM_DOMAIN} -le 1 ]; then
showError "You must enter a domain name!"
elif [[ "${VDM_DOMAIN}" != *.* ]]; then
showError "You must enter a domain name with at least one dot"
fi
done
# update the main domain
export VDM_DOMAIN
}
# set the main domain
function getMainDomain() {
# we first check if we have a main domain passed as command argument
if $VDM_ARG_DOMAIN; then
# if domain passed by arg we just return it
getDomain 'Enter a domain name' 'Enter a Domain Name'
else
# update the main domain with a selection
getMultiDomain
fi
}
# set the container user
function setContainerUser() {
# ask if a new User ID should be set if one is set
if [ -n "${VDM_PUID}" ] && [[ "${VDM_PUID}" =~ ^[0-9]+$ ]] &&
(whiptail --yesno "The user ID in ${PROGRAM_NAME} memory is ${VDM_PUID}, would you like to change this user ID?" \
--defaultno --title "Set User ID" --backtitle "${BACK_TITLE}" 8 112); then
# always first reset
unset VDM_PUID
fi
# give little notice
# showNotice "To get the ID of a user in a container:\n\n$ docker exec -it container_name /bin/bash\n$ id -u www-data"
# we first get the container user ID
while [ -z "${VDM_PUID}" ] || [ ${#VDM_PUID} -le 1 ] || ! [[ "${VDM_PUID}" =~ ^[0-9]+$ ]]; do
VDM_PUID=$(getInput "Enter user ID for the ${VDM_CONTAINER_TYPE^} container. Use default:${1:-1000} if you don't know.\n[add only a number]" \
"${1:-1000}" 'Enter User ID')
# check if we have success
if [ ${#VDM_PUID} -le 1 ] || ! [[ "${VDM_PUID}" =~ ^[0-9]+$ ]]; then
showError "You must enter a user ID like: ${1:-1000} (only the number)"
fi
done
# ask if a new Group ID should be set if one is set
if [ -n "${VDM_PGID}" ] && [[ "${VDM_PGID}" =~ ^[0-9]+$ ]] &&
(whiptail --yesno "The user-group ID in ${PROGRAM_NAME} memory is ${VDM_PGID}, would you like to change this user-group ID?" \
--defaultno --title "Set User-Group ID" --backtitle "${BACK_TITLE}"8 112); then
# always first reset
unset VDM_PGID
fi
# give little notice
# showNotice "To get the ID of a user-group in a container:\n\n$ docker exec -it container_name /bin/bash\n$ id -u www-data"
# we get the container user-group ID
while [ -z "${VDM_PGID}" ] || [ ${#VDM_PGID} -le 1 ] || ! [[ "${VDM_PGID}" =~ ^[0-9]+$ ]]; do
VDM_PGID=$(getInput "Enter user-group ID for the ${VDM_CONTAINER_TYPE^} container. Use default:${1:-1000} if you don't know.\n[add only a number]" \
"${1:-1000}" 'Enter User Group ID')
# check if we have success
if [ ${#VDM_PGID} -le 1 ] || ! [[ "${VDM_PGID}" =~ ^[0-9]+$ ]]; then
showError "You must enter a user-group ID like: ${1:-1000} (only the number)"
fi
done
# make available
export VDM_PUID
export VDM_PGID
}
# Set the program mode
function setMode() {
# Local variable to store the mode
local mode="${1:-basic}"
# Local variable to store the VDM_EXPERT_MODE value
local vdm_expert_mode="false"
# Set the VDM_EXPERT_MODE value based on the mode
case "$mode" in
basic)
vdm_expert_mode="false"
;;
expert)
vdm_expert_mode="true"
;;
*)
echo "Error: Unsupported mode. Use 'basic' or 'expert'."
return 1
;;
esac
# Set persistent
setUniqueEnvVariable "VDM_EXPERT_MODE=${vdm_expert_mode}"
# Make global
export VDM_EXPERT_MODE="$vdm_expert_mode"
}
# set the domain
function setDomain() {
# allow multi domain setup
if allowMultiDomains; then
# select a domain name
getMainDomain
else
# set the main domain if not set
setMainDomain
fi
}
# set the main domain
function setMainDomain() {
# set the main domain if not set
getDomain
# add this value if not set variable
setUniqueEnvVariable "VDM_DOMAIN=\"${VDM_DOMAIN}\""
}
# set the sub domain
function setSubDomain() {
# make sure it has not been used before,
# also make sure its not a port or a ....db
while [ ${#VDM_SUBDOMAIN} -le 1 ] || [[ "${VDM_SUBDOMAIN}" =~ [^a-zA-Z] ]] ||
[ -d "${VDM_REPO_PATH}/${3:-$VDM_CONTAINER_TYPE}/available/${VDM_SUBDOMAIN}.${VDM_DOMAIN}" ] ||
[ -d "${VDM_REPO_PATH}/${3:-$VDM_CONTAINER_TYPE}/available/${VDM_SUBDOMAIN%db}.${VDM_DOMAIN}" ] ||
[ "${VDM_SUBDOMAIN}" = "${2}" ]; do
# get the value
VDM_SUBDOMAIN=$(getInput "Enter sub-domain used for this ${VDM_CONTAINER_TYPE^} container.\n[Text with no spaces that is only alphabetical]" \
"${1}" 'Enter Sub-Domain')
# keep asking if empty or does exist
if [ ${#VDM_SUBDOMAIN} -ge 1 ] && [ -d "${VDM_REPO_PATH}/${3:-$VDM_CONTAINER_TYPE}/available/${VDM_SUBDOMAIN}.${VDM_DOMAIN}" ] ||
[ -d "${VDM_REPO_PATH}/${3:-$VDM_CONTAINER_TYPE}/available/${VDM_SUBDOMAIN%db}.${VDM_DOMAIN}" ]; then
showError "The sub-domain:${VDM_SUBDOMAIN} is already used. Select another"
elif [[ "${VDM_SUBDOMAIN}" =~ [^a-zA-Z] ]]; then
showError "You must enter a sub-domain that is only alphabetical!"
elif [ ${#VDM_SUBDOMAIN} -le 1 ]; then
showError "You must enter a sub-domain!"
fi
done
# make sure it is available
export VDM_SUBDOMAIN
}
# to set a global multiple domains file and values
function setMultiDomains() {
# set some locals
local domain_name
local list_domains
local question
# allow multi domain setup
if allowMultiDomains; then
# get the list of domains
list_domains=$(getListDomains "\n")
# the question based on current state
[ -f "${VDM_SRC_PATH}/.domains" ] && question="Would you like to add another domain to ${PROGRAM_NAME}?\nThese Domains already set:\n${list_domains}" ||
question="Would you like to add a domain to ${PROGRAM_NAME}?"
# get the key if not set
while (whiptail --yesno "${question}" --scrolltext --defaultno \
--title "Add Domain" --backtitle "${BACK_TITLE}" 20 112); do
# now clear the main domain each time
unset VDM_DOMAIN
# we must let them enter the new domain name
getDomain 'Enter a domain name' 'Enter a Domain Name'
# add for next time
saveMultiDomain "${VDM_DOMAIN}"
# get the list of domains
list_domains=$(getListDomains "\n")
# update the question
question="Would you like to add another domain to ${PROGRAM_NAME}?\nThese Domains already set:\n${list_domains}"
done
fi
}
# set the multi domain switch
function setMultiDomainSwitch() {
# Allow multiple domains
if [ "${VDM_MULTI_DOMAIN:-not}" = 'not' ]; then
# explain the pros and cons...
showNotice "Next you should make the selection of using a single or multiple domain setup.\n\n\
With multiple domain setups you will need to select a main domain each time you setup a new container.\n\
With a single domain setup you setup the main domain once, and then only need setup the subdomains\n\
with each new container."
# check the security switch
if (whiptail --yesno "Would you like to use a multiple domains setup?" \
--defaultno --title "Allow Multi Domains" --backtitle "${BACK_TITLE}" 8 112); then
# we set the secure switch
VDM_MULTI_DOMAIN=true
else
VDM_MULTI_DOMAIN=false
fi
fi
# add this value if not set variable
setEnvVariable "VDM_MULTI_DOMAIN=${VDM_MULTI_DOMAIN}"
# make sure it is available
export VDM_MULTI_DOMAIN
}
# set the unique key
function setUniqueKey() {
# get the key if not set
while [ ${#VDM_KEY} -le 1 ] || [ -d "${VDM_PROJECT_PATH}/${VDM_KEY}" ] || [[ "${VDM_KEY}" =~ [^a-zA-Z] ]]; do
# get the value
VDM_KEY=$(getInput "${1:-Enter key used for container naming and name of the persistent volume folder.}\n[Text with no spaces that is only alphabetical]" \
'' 'Enter Key')
# keep asking if empty or does exist
if [ ${#VDM_KEY} -ge 1 ] && [ -d "${VDM_PROJECT_PATH}/${VDM_KEY}" ]; then
showError "The key:${VDM_KEY} is already used. Select another"
elif [[ "${VDM_KEY}" =~ [^a-zA-Z] ]]; then
showError "You must enter a key with no spaces that is only alphabetical!"
elif [ ${#VDM_KEY} -le 1 ]; then
showError "You must enter a key!"
fi
done
# make sure it is available
export VDM_KEY
}
# set the Joomla website details
function setJoomlaWebsiteDetails() {
# ask if we should add mailcatcher
if (whiptail --yesno "Would you like to enable website autodeploy for ${VDM_CONTAINER_TYPE,}:${VDM_JV}" \
--defaultno --title "Enable Autodeploy" --backtitle "${BACK_TITLE}" 8 112); then
# ask for website name
setJoomlaSiteName
# ask for username
setJoomlaUsername
# ask for user
setJoomlaUser
# ask for email
setJoomlaEmail
# ask for username password
setJoomlaPassword
fi
}
# set the website name
function setJoomlaSiteName() {
# get the key if not set
while [ ${#VDM_J_SITE_NAME} -le 2 ]; do
# get the value
VDM_J_SITE_NAME=$(getInput "Enter a Joomla website name." \
'Joomla! CMS' 'Enter Site Name')
# keep asking if empty
if [ ${#VDM_J_SITE_NAME} -le 2 ]; then
showError "You must enter a site name longer than 2 characters!"
fi
done
# make sure it is available
export VDM_J_SITE_NAME
}
# set the username
function setJoomlaUsername() {
# get the key if not set
while [ ${#VDM_J_USERNAME} -le 1 ] || [[ "${VDM_J_USERNAME}" =~ [^a-zA-Z] ]]; do
# get the value
VDM_J_USERNAME=$(getInput "Enter a Joomla username.\n[Text with no spaces that is only alphabetical]" \
'user' 'Enter Username')
# keep asking if empty
if [[ "${VDM_J_USERNAME}" =~ [^a-zA-Z] ]]; then
showError "You must enter a username with no spaces that is only alphabetical!"
elif [ ${#VDM_J_USERNAME} -le 1 ]; then
showError "You must enter a username!"
fi
done
# make sure it is available
export VDM_J_USERNAME
}
# set the user
function setJoomlaUser() {
# get the key if not set
while [ ${#VDM_J_USER} -le 2 ]; do
# get the value
VDM_J_USER=$(getInput "Enter a Joomla user." \
'John Doe' 'Enter User Name')
# keep asking if empty
if [ ${#VDM_J_USER} -le 2 ]; then
showError "You must enter a user!"
fi
done
# make sure it is available
export VDM_J_USER
}
# set the email
function setJoomlaEmail() {
# Email regex for basic validation
local email_regex="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
# Keep prompting until a valid email is provided
while [[ ! "${VDM_J_EMAIL}" =~ $email_regex ]]; do
# Get the email
VDM_J_EMAIL=$(getInput "Enter a Joomla email address." \
'admin@example.org' 'Enter Email')
# Check if the input matches the basic email regex pattern
if [[ ! "${VDM_J_EMAIL}" =~ $email_regex ]]; then
showError "You must enter a valid email address!"
fi
done
# Export the variable to make it available for child processes
export VDM_J_EMAIL
}
# set the username
function setJoomlaPassword() {
# get the key if not set
while [ ${#VDM_J_PASSWORD} -le 12 ]; do
# get the value
VDM_J_PASSWORD=$(getInput "Enter Joomla User Password" \
'joomla-17082005' 'Enter Joomla User Password')
# keep asking if empty
if [ ${#VDM_J_PASSWORD} -le 12 ]; then
showError "You must enter a password with more than 4 characters!"
fi
done
# make sure it is available
export VDM_J_PASSWORD
}
# set the number of containers to build
function setNumberContainers() {
local valid=0
while [ "$valid" -eq 0 ]; do
# get the value
VDM_NUMBER_CONTAINERS=$(getInput "Enter the number of containers you would like to deploy.\n[Just a number!]" \
10 'Enter Number')
# check that the number is above 1 and below 100
if ! [[ $VDM_NUMBER_CONTAINERS =~ ^[0-9]+$ ]]; then
showError "You must enter a number!"
elif [[ $VDM_NUMBER_CONTAINERS -le 1 ]]; then
showError "The number (${VDM_NUMBER_CONTAINERS}) must be above 1"
elif [[ $VDM_NUMBER_CONTAINERS -ge 100 ]]; then
showError "The number (${VDM_NUMBER_CONTAINERS}) must be below 100"
else
valid=1
fi
done
# make sure it is available
export VDM_NUMBER_CONTAINERS
}
# set the Environment key
function setEnvironmentKey() {
# get the env key if not set
while [ ${#VDM_ENV_KEY} -le 1 ] || [[ "${VDM_ENV_KEY}" =~ [^a-zA-Z] ]]; do
# get the value
VDM_ENV_KEY=$(getInput "Enter environment key used to load the container environment variables.\n[Text with no spaces that is only alphabetical UPPERCASE]" \
"${VDM_KEY^^}" 'Enter ENV Key')
# keep asking if empty or does exist
if [ ${#VDM_ENV_KEY} -le 1 ]; then
showError "You must enter an environment key!"
elif [[ "${VDM_ENV_KEY}" =~ [^a-zA-Z] ]]; then
showError "You must enter an environment key with no spaces that is only alphabetical!"
fi
done
# make sure it is available
export VDM_ENV_KEY
}
# set the update of host files
function setUpdateHostFile() {
# check if we have secure switch set
if [ "${VDM_UPDATE_HOST:-not}" = 'not' ]; then
# check the security switch
if (whiptail --yesno "Would you like to update your host file with each new domain you add?" \
--defaultno --title "Update /etc/hosts" --backtitle "${BACK_TITLE}" 8 112); then
# we set the secure switch
VDM_UPDATE_HOST=true
else
VDM_UPDATE_HOST=false
fi
fi
# add this value since its not set variable
setEnvVariable "VDM_UPDATE_HOST=${VDM_UPDATE_HOST}"
# make sure it is available
export VDM_UPDATE_HOST
}
# set the image source values
function setImageSource() {
# some local values
local vdm_image_source
local vdm_tag_url
# get the Joomla version if not set
while [ -z "${VDM_J_REPO}" ] || [ ${#VDM_J_REPO} -le 3 ]; do
# get the image source
vdm_image_source=$(getImageSource)
# build the source key (string before the first | )
VDM_J_REPO="${vdm_image_source%%|*}"
# set the source entry-point (url after the last ; )
VDM_ENTRY_REPO="${vdm_image_source##*;}"
# remove the J_REPO (remove everything before the first | )
vdm_image_source="${vdm_image_source##*|}"
# set the source entry-point (string before the first ; )
vdm_tag_url="${vdm_image_source%%;*}"
# keep asking
[ ${#VDM_J_REPO} -le 3 ] && {
showError "Seems like the source selected is not correctly configured, please select another."
}
# make sure the source is set
[[ "${VDM_ENTRY_REPO}" == *'docker-entrypoint.sh' ]] || {
VDM_J_REPO=''
showError "Seems like the source selected is not correctly configured, please select another."
}
done
# get the Joomla version if not set
while [ ${#VDM_JV} -le 1 ]; do
# get the value
VDM_JV=$(getInput "Enter Joomla version tag for this container.\n[See available tags here ${vdm_tag_url}]" '5.0' 'Enter Version Tag')
# keep asking
[ ${#VDM_JV} -ge 1 ] || {
showError "You must enter a version tag. See available tags here ${vdm_tag_url}"
}
done
# make the value available globally
export VDM_ENTRY_REPO
export VDM_J_REPO
export VDM_JV
}
# check version
function isVersionAbove() {
local tag="$1"
local target_version="$2"
local tag_major
local tag_minor
local target_major
local target_minor
# Extract major and minor versions for the tag and the target_version
tag_major=$(echo "$tag" | awk -F'[.-]' '{print $1}')
tag_minor=$(echo "$tag" | awk -F'[.-]' '{print $2}')
target_major=$(echo "$target_version" | awk -F'.' '{print $1}')
target_minor=$(echo "$target_version" | awk -F'.' '{print $2}')
# Compare major versions
if [[ "$tag_major" -gt "$target_major" ]]; then
return 0
elif [[ "$tag_major" -eq "$target_major" && "$tag_minor" -ge "$target_minor" ]]; then
return 0
fi
return 1
}
# set persistence volumes
function setPersistence() {
# ask the question
if (whiptail --yesno "Would you like to enable persistence on this $1." \
--title "Persist Volume" --backtitle "${BACK_TITLE}" 8 112); then
# yes persistence
return 0
fi
# no persistence
return 1
}
# set the PHP settings
function setPHPSettings() {
# ask the question
if (whiptail --yesno "Would you like to set some PHP overrides for the Joomla container.\n\nTo make these changes we need sudo privileges." \
--defaultno --title "PHP.ini values" --backtitle "${BACK_TITLE}" 9 112); then
# max_execution_time
VDM_max_execution_time=$(getInputNow "Enter max execution time" \
"${VDM_max_execution_time:-124}" 'max_execution_time')
# remember this for next time
setUniqueEnvVariable "VDM_max_execution_time=${VDM_max_execution_time}"
# max_input_time
VDM_max_input_time=$(getInputNow "Enter max input time" \
"${VDM_max_input_time:-1500}" 'max_input_time')
# remember this for next time
setUniqueEnvVariable "VDM_max_input_time=${VDM_max_input_time}"
# max_input_vars
VDM_max_input_vars=$(getInputNow "Enter max_input_vars" \
"${VDM_max_input_vars:-3000}" 'max_input_vars')
# remember this for next time
setUniqueEnvVariable "VDM_max_input_vars=${VDM_max_input_vars}"
# error_reporting
default_error_reporting="E_ALL & ~E_DEPRECATED & ~E_STRICT"
VDM_error_reporting=$(getInputNow "Enter error reporting" \
"${VDM_error_reporting:-$default_error_reporting}" 'error_reporting')
# remember this for next time
setUniqueEnvVariable "VDM_error_reporting=\"${VDM_error_reporting}\""
# upload_max_filesize
VDM_upload_max_filesize=$(getInputNow "Enter upload max filesize" \
"${VDM_upload_max_filesize:-256M}" 'upload_max_filesize')
# remember this for next time
setUniqueEnvVariable "VDM_upload_max_filesize=\"${VDM_upload_max_filesize}\""
# post_max_size
VDM_post_max_size=$(getInputNow "Enter post max size" \
"${VDM_post_max_size:-256M}" 'post_max_size')
# remember this for next time
setUniqueEnvVariable "VDM_post_max_size=\"${VDM_post_max_size}\""
# memory_limit
VDM_memory_limit=$(getInputNow "Enter memory limit" \
"${VDM_memory_limit:-256M}" 'memory_limit')
# remember this for next time
setUniqueEnvVariable "VDM_memory_limit=\"${VDM_memory_limit}\""
# make sure the directory exist
mkdir -p "${VDM_PROJECT_PATH}/${VDM_PHP_PROJECT_PATH}"
# push all these values to the php.ini file
{
echo "max_execution_time = ${VDM_max_execution_time}"
echo "max_input_time = ${VDM_max_input_time}"
echo "max_input_vars = ${VDM_max_input_vars}"
echo "error_reporting = ${VDM_error_reporting}"
echo "upload_max_filesize = ${VDM_upload_max_filesize}"
echo "post_max_size = ${VDM_post_max_size}"
echo "memory_limit = ${VDM_memory_limit}"
} > "${VDM_PROJECT_PATH}/${VDM_PHP_PROJECT_PATH}/php.ini"
# allow custom edit
if isExpert && (whiptail --yesno "Would you like to set some more custom PHP overrides for this Joomla container" \
--defaultno --title "Edit PHP.ini" --backtitle "${BACK_TITLE}" 8 112); then
# give little heads-up
showNotice "${USER^}, to save the changes you've made or to just close the file again press:\n\n[ctrl+x] with nano on ubuntu." 13
# lets open the file with nano for now
sudo "${EDITOR:-nano}" "${VDM_PROJECT_PATH}/${VDM_PHP_PROJECT_PATH}/php.ini"
fi
# set the ownership
if [ -n "${VDM_PUID}" ] && [ -n "${VDM_PGID}" ]; then
sudo chown "${VDM_PUID}":"${VDM_PGID}" "${VDM_PROJECT_PATH}/${VDM_PHP_PROJECT_PATH}/php.ini"
else
sudo chown www-data:www-data "${VDM_PROJECT_PATH}/${VDM_PHP_PROJECT_PATH}/php.ini"
fi
# make sure the permission are good
sudo chmod 600 "${VDM_PROJECT_PATH}/${VDM_PHP_PROJECT_PATH}/php.ini"
# yes load php.ini volume to the container
return 0
fi
return 1
}
# set the docker entrypoint
function setDockerEntrypoint() {
# ask the question
if (whiptail --yesno "Would you like to customize the entrypoint script for this Joomla container" \
--defaultno --title "entrypoint.sh values" --backtitle "${BACK_TITLE}" 8 112); then
# make sure the directory exist
mkdir -p "${VDM_PROJECT_PATH}/${VDM_ENTRY_PROJECT_PATH}"
# unattended deploy
# if (whiptail --yesno "Would you like to to setup unattended deployment for this Joomla container" --defaultno --title "Unattended Deployment" 8 112); then
# echo "soon we will have this ready"
# fi
# download entrypoint.sh file to the project folder
if sudo curl --fail -L "${VDM_ENTRY_REPO}" -o "${VDM_PROJECT_PATH}/${VDM_ENTRY_PROJECT_PATH}/entrypoint.sh" 2>/dev/null; then
# give little heads-up
showNotice "${USER^}, to save the changes you've made or to just close the file again press:\n\n[ctrl+x] with nano on ubuntu." 13
# lets open the file with nano for now
sudo "${EDITOR:-nano}" "${VDM_PROJECT_PATH}/${VDM_ENTRY_PROJECT_PATH}/entrypoint.sh"
# set the ownership
sudo chown root:root "${VDM_PROJECT_PATH}/${VDM_ENTRY_PROJECT_PATH}/entrypoint.sh"
# make sure the permission are good
sudo chmod +x "${VDM_PROJECT_PATH}/${VDM_ENTRY_PROJECT_PATH}/entrypoint.sh"
# we have the file set
return 0
else
# show the error
showError "The entrypoint.sh could not be set."
fi
fi
return 1
}
# set the secure state
function setSecureCloudflareState() {
# check the security switch
if (whiptail --yesno "Will this container be proxied by Cloudflare [ONLY for server proxied in none-strict mode via Cloudflare]" \
--defaultno --title "Cloudflare" --backtitle "${BACK_TITLE}" 8 112); then
# we set the secure switch
VDM_SECURE_CLOUDFLARE=true
else
VDM_SECURE_CLOUDFLARE=false
fi
# make sure it is available
export VDM_SECURE_CLOUDFLARE
}
# set the secure state
function setSecureState() {
if [ "${VDM_SECURE:-not}" = 'not' ]; then
# check the security switch
if (whiptail --yesno "Would you like to use Letsencrypt auto setup for your containers [ONLY for server with public static IP]" \
--defaultno --title "Letsencrypt" --backtitle "${BACK_TITLE}" 8 112); then
# we set the secure switch
VDM_SECURE=true
else
VDM_SECURE=false
fi
fi
# add this value if not set variable
setEnvVariable "VDM_SECURE=${VDM_SECURE}"
# make sure it is available
export VDM_SECURE
}
# Create Docker networks if they do not exist
function setNetworks() {
# Default network names and subnets
local traefik_gateway="${VDM_TRAEFIK_GATEWAY:-traefik_webgateway}"
local traefik_subnet="${VDM_TRAEFIK_SUBNET:-172.22.0.0/24}"
local openssh_gateway="${VDM_OPENSSH_GATEWAY:-openssh_gateway}"
local openssh_subnet="${VDM_OPENSSH_SUBNET:-172.23.0.0/24}"
# Create traefik network if it does not exist
docker network inspect "${traefik_gateway}" >/dev/null 2>&1 ||
docker network create "${traefik_gateway}" --subnet "${traefik_subnet}"
# Create openssh network if it does not exist
docker network inspect "${openssh_gateway}" >/dev/null 2>&1 ||
docker network create "${openssh_gateway}" --subnet "${openssh_subnet}"
}
# to set a global Env Variable
function setUniqueEnvVariable() {
# some locals
local environment_variable="$1"
# always remove previous environment variable
deleteEnvVariable "${environment_variable%%=*}"
# set the new environment variable
setEnvVariable "${environment_variable}" && return 0
# or failed
return 12
}
# to set a global Env Variable
function setEnvVariable() {
# check if the env file exist
if [ -f "${VDM_SRC_PATH}/.env" ]; then
grep -q "${1}" "${VDM_SRC_PATH}/.env" || echo "${1}" >>"${VDM_SRC_PATH}/.env"
elif (whiptail --yesno "Can we create the ${VDM_SRC_PATH}/.env file" \
--title "Environment Variable File" --backtitle "${BACK_TITLE}" 8 112); then
# make sure the folder exist
mkdir -p "${VDM_SRC_PATH}"
# so we creat the file
echo "${1}" >"${VDM_SRC_PATH}/.env"
# make sure the permissions are secured
chmod 600 "${VDM_SRC_PATH}/.env"
else
showError "The ${VDM_SRC_PATH}/.env file does not exist. So ${1} could not be added!"
# we return false
return 12
fi
# we return true
return 0
}
# to set a container Env Variable
function setContainerEnvVariable() {
# check if the env file exist
if [ -f "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" ]; then
grep -q "${1}" "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env" || echo "${1}" >>"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
elif (whiptail --yesno "Can we create the ${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env file" \
--title "Container Environment Variable File" --backtitle "${BACK_TITLE}" 8 112); then
# make sure the folder exist
mkdir -p "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}"
# so we creat the file
echo "${1}" >"${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
# make sure the permissions are secured
chmod 600 "${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env"
else
showError "The ${VDM_REPO_PATH}/${VDM_CONTAINER_TYPE}/.env file does not exist. So ${1} could not be added!"
# we return false
return 12
fi
# we return true
return 0
}
# check if a Directory exist and if it has sub-directories
function hasDirectories() {
# shellcheck disable=SC2046
# shellcheck disable=SC2012
if [ -d "${2:-$VDM_REPO_PATH}/${1:-}" ] && [ $(ls -A "${2:-$VDM_REPO_PATH}/${1:-}" | wc -l) -ne 0 ]; then
return 0
fi
return 1
}
# take down apache
function downApache() {
# make sure port 80 is not used by apache
command -v apache2 >/dev/null 2>&1 && [[ $(service apache2 status) == *"active (running)"* ]] && {
if (whiptail --yesno "Traefik needs port 80/443 and since Apache is also enabled we don't know if is using these ports, so Traefik may not work. Can we disable Apache?\n(we need sudo privileges)" \
--defaultno --title "Disable Apache" --backtitle "${BACK_TITLE}" 12 112); then
sudo systemctl stop apache2.service
sudo systemctl disable apache2.service
fi
}
}
# lock a folder path
function lockFolder() {
cat <<EOF
# Apache 2.4+
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
# Apache 2.0-2.2
<IfModule !mod_authz_core.c>
Deny from all
</IfModule>
EOF
}
# clear the main environment variables
function quitProgram() {
####### CLEAR ALL
unset VDM_PUID
unset VDM_PGID
unset VDM_CONTAINER_TYPE
unset VDM_TASK
unset VDM_SRC_PATH
unset VDM_REPO_PATH
unset VDM_PROJECT_PATH
unset VDM_DOMAIN
unset VDM_MULTI_DOMAIN
unset VDM_SECURE
unset VDM_SECURE_CLOUDFLARE
unset VDM_UPDATE_HOST
unset VDM_CONTAINER
unset VDM_ACCESS_TOKEN
# exit at this point
exit 0
}
# do we allow multiple domains
function allowMultiDomains() {
# Allow multiple domains
setMultiDomainSwitch
# allow multi domain setup
if $VDM_MULTI_DOMAIN; then
# yes we do
return 0
fi
# now we don't
return 12
}
# do we allow multiple domains
function allowEditHostFile() {
# check if we allow host file updates
setUpdateHostFile
# allow multi domain setup
if $VDM_UPDATE_HOST; then
# yes we do
return 0
fi
# now we don't
return 12
}
# to set a global multiple domain file and values
function saveMultiDomain() {
# set some locals
local domain_name
local src_path_domain
# set the domain and remove any whitespace
domain_name="$(echo -e "${1}" | tr -d '[:space:]')"
src_path_domain="${VDM_SRC_PATH}/.domains"
# check that we have a domain string
if [ -n "${domain_name}" ]; then
# make sure the folder exists
mkdir -p "${VDM_SRC_PATH}"
# if the file does not exist, create it and set the proper permissions
if [ ! -f "${src_path_domain}" ]; then
touch "${src_path_domain}"
chmod 600 "${src_path_domain}"
fi
# check if the domain is not already in the file, and if not, add it
if ! grep -q "${domain_name}" "${src_path_domain}"; then
echo "${domain_name}" >>"${src_path_domain}"
fi
fi
# we return true
return 0
}
# delete a global Environment Variable
function deleteEnvVariable() {
# some locals
local env_key
# check if the env file exist
if [ -f "${VDM_SRC_PATH}/.env" ]; then
# check that we have the key
env_key="${1:-none}"
# shellcheck disable=SC2015
grep -vx "${env_key}=.*" "${VDM_SRC_PATH}/.env" >"${VDM_SRC_PATH}/.env_tmp" &&
mv "${VDM_SRC_PATH}/.env_tmp" "${VDM_SRC_PATH}/.env" ||
rm "${VDM_SRC_PATH}/.env_tmp"
fi
}
# delete multiple domains
function deleteMultiDomains() {
local menu_options=()
local domains
local i=0
local domain_file="${VDM_SRC_PATH}/.domains"
if [ -f "${domain_file}" ] && readarray -t domains <"${domain_file}"; then
if [ "${#domains[@]}" -gt 0 ]; then
for domain in "${domains[@]}"; do
menu_options+=("${domain}" "${domain}" "OFF")
i=$((i + 1))
done
answer=$(whiptail --title "Delete Domains" --checklist \
"Select the domain/s you would like to delete" 20 112 $i \
"${menu_options[@]}" \
--backtitle "${BACK_TITLE}" --nocancel --notags 3>&1 1>&2 2>&3)
if [ -n "${answer}" ]; then
IFS=' ' read -r -a array_answer <<<"${answer[@]}"
for remove in "${array_answer[@]}"; do
remove_domain="${remove//\"/}"
# shellcheck disable=SC2015
grep -vx "${remove_domain}" "${domain_file}" >"${domain_file}_tmp" && \
mv "${domain_file}_tmp" "${domain_file}" || \
rm "${domain_file}_tmp"
done
fi
fi
fi
}
# check if expert mode is on
function isExpert() {
# check if its set
if [ -n "${VDM_EXPERT_MODE}" ] && [ "${VDM_EXPERT_MODE}" = "true" ]; then
# is expert
return 0
else
# not expert
return 1
fi
}
# check if some thing is a function
function isFunc() {
declare -F "$1" >/dev/null
}
# update the host file
function updateHostFile() {
# check if we should add to host file
if allowEditHostFile; then
# check if already in host file
if grep -q "${1:-$VDM_SUBDOMAIN}.${2:-$VDM_DOMAIN}" /etc/hosts; then
showNotice "${USER^}, ${1:-$VDM_SUBDOMAIN}.${2:-$VDM_DOMAIN} is already in the /etc/hosts file."
elif (whiptail --yesno "${USER^}, to add the ${1:-$VDM_SUBDOMAIN}.${2:-$VDM_DOMAIN} entry to your host file we need sudo privileges." \
--title "Give sudo Privileges" --backtitle "${BACK_TITLE}" 8 112); then
# add the domain to the host file
echo "127.0.0.1 ${1:-$VDM_SUBDOMAIN}.${2:-$VDM_DOMAIN}" | sudo tee -a /etc/hosts >/dev/null
# show notice
showNotice "${USER^}, ${1:-$VDM_SUBDOMAIN}.${2:-$VDM_DOMAIN} was added to the /etc/hosts file."
fi
fi
}
# the manually edit the host file
function editHostFile() {
# check if we should add to host file
if allowEditHostFile; then
# if this container is enabled ask if it should be redeployed
if (whiptail --yesno "To edit the host file we need sudo privileges.\n[Only continue if you know what your doing!]" \
--title "Give sudo Privileges" --backtitle "${BACK_TITLE}" 15 112); then
# give little heads-up
showNotice "${USER^}, to save the changes you've made or to just close the file again press:\n\n[ctrl+x] with nano on ubuntu." 13
# lets open the file with nano for now
sudo "${EDITOR:-nano}" /etc/hosts
fi
fi
}
# the manually edit the config file
function editConfigFile() {
# check if the file exist
if [ -f "${VDM_SRC_PATH}/.env" ]; then
# give little warning for less command ready people
if (whiptail --yesno "Only continue if you know what your doing!\n\n\
${USER^}, to save the changes you've made or to just close the file again press:\n\n\
[ctrl+x] with nano on ubuntu." --title "Continue to edit ${PROGRAM_NAME} global config." \
--backtitle "${BACK_TITLE}" 15 112); then
# all direct edit of the global config file
"${EDITOR:-nano}" "${VDM_SRC_PATH}/.env"
fi
fi
}
# the manually edit the container env file
function openEnv() {
# some local values
local container_type="$1"
# check if the file exist
if [ -f "${VDM_REPO_PATH}/${container_type}/.env" ]; then
# give little warning for less command ready people
if (whiptail --yesno "Only continue if you know what your doing!\n\n\
${USER^}, to save the changes you've made or to just close the file again press:\n\n\
[ctrl+x] with nano on ubuntu." --title "Continue to edit ${PROGRAM_NAME} ${container_type} env." \
--backtitle "${BACK_TITLE}" 15 112); then
# all direct edit of the container env file
"${EDITOR:-nano}" "${VDM_REPO_PATH}/${container_type}/.env"
fi
else
showError "${VDM_REPO_PATH}/${container_type}/.env does not exist, make sure you have at least one ${container_type} setup."
fi
}
# Check if any hosts are set in the SSH config file
function hasRemoteSystemSet() {
local ssh_config="/home/${USER}/.ssh/config"
if [ ! -d "/home/${USER}/.ssh" ] || [ ! -f "${ssh_config}" ] ||
[[ $(grep -i -c '^host' "${ssh_config}") -eq 0 ]]; then
showError "To use this feature you must first set up the needed remote host details in (~/.ssh/config) to allow easy and secure SSH access."
return 1
fi
return 0
}
# Get a selected remote system
function getRemoteSystem() {
# The selected folder
local answer
if [ -f "/home/${USER}/.ssh/config" ]; then
# We start the selection array
local selected=()
# Our counter
local i=0
# Add the remote systems
while IFS= read -r remote_system; do
# Load the remote systems
selected+=("${remote_system}" "${remote_system}" "OFF")
# Increment our pointer
if [ "$i" -le 10 ]; then
i=$((i + 1))
fi
done < <(grep -i '^host' "/home/${USER}/.ssh/config" | awk '{print $2}' | sort)
# Add manual input option
selected+=("Enter manually" "Enter manually" "OFF")
# now make the selection
answer=$(whiptail --title "Remote Systems" --radiolist \
"Select the remote system you would like to use." 20 112 $i \
"${selected[@]}" --backtitle "${BACK_TITLE}" --notags 3>&1 1>&2 2>&3)
if [[ $answer == "Enter manually" ]]; then
answer=$(getInputNow "Enter the remote host manually:" "" "Remote Host")
fi
else
answer=$(getInputNow "Enter the remote host:" "" "Remote Host")
fi
# Return the answer
echo "${answer:-none_selected}"
}
# get a selected migration type
function getMigrationType() {
# the selected folder
local answer
# we start the selection array
local selected=()
# our counter
local i=2
# now check if this dir has sub dirs
selected+=("push" "Push to Remote System" "ON")
selected+=("pull" "Pull from Remote System" "OFF")
# now make the selection
answer=$(whiptail --title "Migration Type" --radiolist \
"What kind of migration will be preformed?" 20 112 $i \
"${selected[@]}" --backtitle "${BACK_TITLE}" --nocancel --notags 3>&1 1>&2 2>&3)
# return the answer
echo "${answer:-push}"
}
# Check if the remote .env file exists
function remoteEnvFileExists() {
local remote_system="$1"
# Check if the file exists on the remote system
# shellcheck disable=SC2029
ssh "${remote_system}" "[ -f \"/home/${USER}/.config/octojoom/.env\" ]"
}
# Get a specific value from the remote .env file
function getRemoteEnvValue() {
local remote_system="$1"
local env_key="$2"
local remote_env_value
if remoteEnvFileExists "${remote_system}"; then
# shellcheck disable=SC2029
remote_env_value=$(ssh "${remote_system}" "grep '^${env_key}=' \"/home/${USER}/.config/octojoom/.env\"" | cut -d '=' -f 2-)
fi
# Remove any double quotes from the returned value
remote_env_value=$(echo "${remote_env_value}" | tr -d '"')
echo "${remote_env_value:-none_found}"
}
# Pull the remote container migration
function pullContainerMigration() {
# set some local variables
local local_path="$1"
local container_path="$2"
local remote="$3"
local remote_repo_path
remote_repo_path=$(getRemoteEnvValue "${remote}" "VDM_REPO_PATH")
if [ ! "${remote_repo_path}" = 'none_found' ]; then
showNotice "PULL<<[NOT READY]>>DETAILS>> ${local_path}<-path ${container_path}<-container name ${remote}<-remote (${remote_repo_path})" 13
else
showError "Remote system does not appear to have ${PROGRAM_NAME} installed, or your access was denied. Therefore the migration has been cancelled!"
return 1
fi
}
# Push the remote container migration
function pushContainerMigration() {
# set some local variables
local local_path="$1"
local container_path="$2"
local remote="$3"
local remote_repo_path
remote_repo_path=$(getRemoteEnvValue "${remote}" "VDM_REPO_PATH")
if [ ! "${remote_repo_path}" = 'none_found' ]; then
local remote_path="${remote_repo_path}/${container_path}"
# check how we must do this
if remoteFolderExists "${remote_path}" "${remote}" && (whiptail --yesno "${USER^}, would you like to backup the remote container?" \
--backtitle "${BACK_TITLE}" --title "Backup Remote" 15 112); then
backupRemoteFolder "${remote_path}" "${remote}"
fi
# sync folder
syncWithRemote "${local_path}" "${remote_path}" "${remote}"
# check if it was done successfully
if transferWasSuccessful "${local_path}" "${remote_path}" "${remote}"; then
showNotice "The PUSH of ${local_path} to ${remote}:${remote_path} was a success." 13
return 0
else
showError "The PUSH of ${local_path} to ${remote}:${remote_path} failed."
return 1
fi
else
showError "Remote system does not appear to have ${PROGRAM_NAME} installed, or your access was denied. Therefore the migration has been cancelled!"
return 1
fi
}
# Pull the remote directory migration
function pullDirectoryMigration() {
# set some local variables
local local_path="$1"
local directory_name="$2"
local remote="$3"
local remote_project_path
remote_project_path=$(getRemoteEnvValue "${remote}" "VDM_PROJECT_PATH")
if [ ! "${remote_project_path}" = 'none_found' ]; then
showNotice "PULL<<[NOT READY]>>DETAILS>> ${local_path}<-path ${directory_name}<-directory name ${remote}<-remote (${remote_project_path})" 13
else
showError "Remote system does not appear to have ${PROGRAM_NAME} installed, or your access was denied. Therefore the migration has been cancelled!"
return 1
fi
}
# Push the remote directory migration
function pushDirectoryMigration() {
# set some local variables
local local_path="$1"
local directory_name="$2"
local remote="$3"
local remote_project_path
remote_project_path=$(getRemoteEnvValue "${remote}" "VDM_PROJECT_PATH")
if [ ! "${remote_project_path}" = 'none_found' ]; then
local backup_dir
local remote_path="${remote_project_path}/${directory_name}"
# make a backup of this project directory
backup_dir=$(createTempBackup "${local_path}")
# give current user full ownership of this folder
chownBackup "${backup_dir}"
# tar the directory
tar_path=$(tarAndMoveTempBackup "${local_path}" "${backup_dir}")
# clear the backup
rm -rf "${backup_dir}"
# move zip file to remote
moveTarToRemote "${tar_path}" "${remote_project_path}/" "${remote}"
# check if it was done successfully
if transferTarWasSuccessful "${tar_path}" "${remote_path}.tar.gz" "${remote}"; then
# clear the tmp tar
rm -rf "${tar_path}"
# check how we must do this
if remoteFolderExists "${remote_path}" "${remote}" &&
(whiptail --yesno "${USER^}, would you like to backup the remote directory?" \
--title "Backup Remote" --backtitle "${BACK_TITLE}" 15 112);
then
backupRemoteFolder "${remote_path}" "${remote}"
fi
# un-tar the remote file
remoteUntarGz "${remote_path}.tar.gz" "${remote_path}" "${remote}"
# we are done
showNotice "The PUSH of ${local_path} to ${remote}:${remote_path} was a success." 13
# permission fix
if (whiptail --yesno "${USER^}, would you like to fix the permissions of this remote directory?\nWe will start the ${PROGRAM_NAME} on the remote server and then you should navigate to the fix, and exit when done." \
--title "Permissions Fix" --backtitle "${BACK_TITLE}" 15 112); then
connectToRemoteSystem "${remote}"
fi
return 0
else
showError "The PUSH of ${local_path} to ${remote}:${remote_path} failed."
return 1
fi
else
showError "Remote system does not appear to have ${PROGRAM_NAME} installed, or your access was denied. Therefore the migration has been cancelled!"
return 1
fi
}
# Create a temporary backup of the folder with root access
function createTempBackup() {
local source_dir="$1"
# shellcheck disable=SC2155
local backup_dir="/tmp/backup_$(basename "${source_dir}")_$(date +%Y%m%d%H%M%S)"
sudo cp -a "${source_dir}" "${backup_dir}"
echo "${backup_dir}"
}
# Create a tar.gz archive of the temporary backup folder and move the resulting archive to the parent directory of the source directory
function tarAndMoveTempBackup() {
local source_dir="$1"
local backup_dir="$2"
local parent_dir
local tar_filename
local current_dir
# Get the parent directory of the source directory
parent_dir=$(dirname "${source_dir}")
# Create the tar.gz filename
tar_filename="$(basename "${source_dir}").tar.gz"
# Store the current working directory
current_dir=$(pwd)
# Change to the backup directory
cd "${backup_dir}" || return
# Create the tar.gz archive without preserving the full path
tar -czf "${parent_dir}/${tar_filename}" .
# Change back to the original working directory
cd "${current_dir}" || return
# Return the path to the moved tar.gz archive
echo "${parent_dir}/${tar_filename}"
}
# Change the ownership of the backup directory to the current user
function chownBackup() {
local backup_dir="$1"
sudo chown -R "${USER}":"${USER}" "${backup_dir}"
}
# Check if the folder exists on the remote server
function remoteFolderExists() {
local remote_path="$1"
local remote="$2"
# Check if the remote folder exists
# shellcheck disable=SC2029
if ssh "${remote}" "[ -d '${remote_path}' ]"; then
return 0
else
return 1
fi
}
# run Octojoom on a remote system
function connectToRemoteSystem() {
# set some local variables
local remote_system="${1:-none_set}"
local remote_repo_path
# get remote system
if [ "${remote_system}" == "none_set" ]; then
remote_system=$(getRemoteSystem)
fi
# make sure we have a remote
if [ ${#remote_system} -ge 2 ] && [ "${remote_system}" != "none_selected" ]; then
showNotice "We will first validate that the remote system has ${PROGRAM_NAME,,} config settings in place!" 13
if remoteEnvFileExists "${remote_system}"; then
if (whiptail --yesno "${USER^} we found ${PROGRAM_NAME,,} config settings on the ${remote_system}. Please take note of the following important information.\n\nSince we will start ${PROGRAM_NAME,,} on ${remote_system} it will not look that different, seeing that it has the same user graphical interface. Yet, whatever changes you make on ${remote_system} WILL PERMINANTLY effect this remote system, and can not be undone!!!\n\nAre you ready to connect to ${remote_system}:${PROGRAM_NAME,,}?" \
--title "Confirm ${remote_system} Connection" --backtitle "${BACK_TITLE}" 15 112); then
showNotice "Connection to ${remote_system} will now be made!" 13
ssh -t "${remote_system}" "bash octojoom"
showNotice "You have been disconnected from ${remote_system}!" 13
return 0
else
showNotice "The connection to ${remote_system} was cancelled!" 13
return 1
fi
else
showError "Remote system does not appear to have ${PROGRAM_NAME,,} installed, or your access was denied. Therefore the connection has been closed!"
return 1
fi
fi
showError "Connection to the remote system was cancelled since no remote system was selected."
return 1
}
# Change the ownership of the remote folder to the current user
function chownRemoteFolder() {
local remote_path="$1"
local remote="$2"
ssh -t "${remote}" "sudo chown -R ${USER}:${USER} ${remote_path}"
}
# Check if the folder exists on the remote server, and if so, rename it for backup purposes
function backupRemoteFolder() {
local remote_path="$1"
local remote="$2"
# shellcheck disable=SC2155
local backup_name="${remote_path}_backup_$(date +%Y%m%d%H%M%S)"
# shellcheck disable=SC2029
ssh "${remote}" "if [ -d '${remote_path}' ]; then mv '${remote_path}' '${backup_name}'; fi"
}
# Prep remote folder
function prepRemoteFolder() {
local remote_path="$1"
local remote="$2"
# shellcheck disable=SC2029
ssh "${remote}" "mkdir -p ${remote_path}"
}
# Remotely extract a tar.gz file to a specified folder on the remote host
function remoteUntarGz() {
local remote_file_path="$1"
local remote_extract_path="$2"
local remote="$3"
# Remote un-tar.gz command
# shellcheck disable=SC2029
ssh "${remote}" "mkdir -p '${remote_extract_path}' && tar --overwrite -xzf '${remote_file_path}' -C '${remote_extract_path}'"
# shellcheck disable=SC2029
ssh "${remote}" "if [ -f '${remote_file_path}' ]; then rm '${remote_file_path}'; fi"
}
# Transfer the folder to the remote server using rsync
function syncFolder() {
local local_path="$1"
local remote_path="$2"
local remote="$3"
rsync -avz --delete "${local_path}/" "${remote}:${remote_path}"
}
# Move/copy the local tar file to the remote server
function moveTarToRemote() {
local local_path="$1"
local remote_path="$2"
local remote="$3"
if [ -f "/home/${USER}/.ssh/config" ]; then
scp -F "/home/${USER}/.ssh/config" "${local_path}" "${remote}:${remote_path}"
else
scp "${local_path}" "${remote}:${remote_path}"
fi
}
# Sync the local folder to the remote server and remove the local backup
function syncWithRemote() {
local local_path="$1"
local remote_path="$2"
local remote="$3"
prepRemoteFolder "${remote_path}" "${remote}"
syncFolder "${local_path}" "${remote_path}" "${remote}"
}
# Check if the transfer was successful by comparing local and remote directory contents
function transferWasSuccessful() {
local local_path="$1"
local remote_path="$2"
local remote="$3"
# Perform a dry-run with rsync to compare directories
rsync_output=$(rsync -avz --dry-run --checksum --delete "${local_path}/" "${remote}:${remote_path}/")
# Check if there are any file differences or deletions
echo "${rsync_output}" | grep -E -q "^(>|<|deleting)"
# Check the exit status of the grep command to determine if there are any differences
# shellcheck disable=SC2181
if [ $? -eq 0 ]; then
# Differences found, return failure
return 1
else
# No differences found, return success
return 0
fi
}
# Check if the transfer was successful by comparing local and remote zip file checksums
function transferTarWasSuccessful() {
local local_path="$1"
local remote_path="$2"
local remote="$3"
# Compute the checksum of the local zip file
local_checksum=$(md5sum "${local_path}" | awk '{print $1}')
# Compute the checksum of the remote zip file
# shellcheck disable=SC2029
remote_checksum=$(ssh "${remote}" "md5sum ${remote_path}" | awk '{print $1}')
# Compare the checksums
if [ "${local_checksum}" == "${remote_checksum}" ]; then
# Checksums match, return success
return 0
else
# Checksums do not match, return failure
return 1
fi
}
#####################################################################################################################VDM
######################################## CLI MENU ʕ•ᴥ•ʔ
# help message
function showHelp() {
cat <<EOF
Usage: octojoom [OPTION...]
Options
======================================================
--type <type>
set type you would like to work with
example: octojoom --type joomla
======================================================
--task <task>
set type of task you would like to perform
example: octojoom --task setup
======================================================
--container <container.domain.name>
Directly enabling or disabling a container with
the type=joomla and task=enable/disable set
The container must exist, which means it was
setup previously
Used without type and task Joomla-Enable is (default)
example: octojoom --container "io.vdm.dev"
======================================================
--update
to update your install
example: octojoom --update
======================================================
--access-token <token>
to update the program you will need an access token
from https://git.vdm.dev/user/settings/applications
example: octojoom --access-token xxxxxxxxxxx
======================================================
--uninstall
to uninstall this script
example: octojoom --uninstall
======================================================
AVAILABLE FOR TO ANY CONTAINER
======================================================
-k|--key <key>
set key for the docker compose container naming
!! no spaces allowed in the key !!
example: octojoom -k="vdm"
example: octojoom --key="vdm"
======================================================
-e|--env-key <key>
set key for the environment variable naming
!! no spaces allowed in the key & must be UPPERCASE !!
example: octojoom -e="VDM"
example: octojoom --env-key="VDM"
======================================================
-d|--domain <domain.com>
set key website domain
!! must be domain.tld !!
example: octojoom -d="joomla.org"
example: octojoom --domain="joomla.org"
======================================================
-s|--sub-domain <domain.com>
set key website sub domain
!! no spaces allowed in the sub domain !!
example: octojoom -s="jcb"
example: octojoom --sub-domain="jcb"
======================================================
AVAILABLE FOR JOOMLA CONTAINER
======================================================
-j|--joomla-version <version-tag>
see available tags here https://hub.docker.com/_/joomla
example: octojoom -j=5.0
example: octojoom --joomla-version=5.0
======================================================
AVAILABLE FOR OPENSSH CONTAINER
======================================================
-u|--username <username>
set username of the container
example: octojoom -u="ubuntu"
example: octojoom --username="ubuntu"
======================================================
--uid <id>
set container user id
example: octojoom --uid=1000
======================================================
--gid <id>
set container user group id
example: octojoom --gid=1000
======================================================
-p|--port <port>
set ssh port to use
!! do not use 22 !!
example: octojoom -p=2239
example: octojoom --port=2239
======================================================
--ssh-dir <dir>
set ssh directory name found in the .ssh dir
of this repo for the container keys
This directory has separate files for
each public key allowed to access
the container
example: octojoom --ssh-dir="teamname"
======================================================
--sudo
switch to add the container user to the
sudo group of the container
example: octojoom --sudo
======================================================
-t|--time-zone <time/zone>
set time zone of the container
!! must valid time zone !!
example: octojoom -t="Africa/Windhoek"
example: octojoom --time-zone="Africa/Windhoek"
======================================================
HELP ʕ•ᴥ•ʔ
======================================================
-h|--help
display this help menu
example: octojoom -h
example: octojoom --help
======================================================
${PROGRAM_NAME} v${_VERSION}
======================================================
EOF
}
#####################################################################################################################VDM
######################################## CLI INPUT ¯\_(ツ)_/¯
# defaults
VDM_ARG_DOMAIN=false
# check if we have options
while :; do
case $1 in
-h | --help)
showHelp # Display a usage synopsis.
quitProgram
;;
--update)
runUpdate
shift
;;
--access-token) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_ACCESS_TOKEN=$2
shift
else
showError '"--access-token" requires a non-empty option argument.'
exit 17
fi
;;
--access-token=?*)
# shellcheck disable=SC2034
VDM_ACCESS_TOKEN=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
--access-token=) # Handle the case of an empty --type=
showError '"--access-token=" requires a non-empty option argument.'
exit 17
;;
--uninstall)
runUninstall
shift
;;
--type) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_CONTAINER_TYPE=$2
shift
else
showError '"--type" requires a non-empty option argument.'
exit 17
fi
;;
--type=?*)
VDM_CONTAINER_TYPE=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
--type=) # Handle the case of an empty --type=
showError '"--type=" requires a non-empty option argument.'
exit 17
;;
--task) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_TASK=$2
shift
else
showError '"--task" requires a non-empty option argument.'
exit 17
fi
;;
--task=?*)
VDM_TASK=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
--task=) # Handle the case of an empty --task=
showError '"--task=" requires a non-empty option argument.'
exit 17
;;
--container) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_CONTAINER=$2
shift
else
showError '"--container" requires a non-empty option argument.'
exit 17
fi
;;
--container=?*)
VDM_CONTAINER=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
--container=) # Handle the case of an empty --container=
showError '"--container=" requires a non-empty option argument.'
exit 17
;;
-j | --joomla-version) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_JV=$2
shift
else
showError '"--joomla-version" requires a non-empty option argument.'
exit 17
fi
;;
-j=?* | --joomla-version=?*)
VDM_JV=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
-j= | --joomla-version=) # Handle the case of an empty --joomla-version=
showError '"--joomla-version=" requires a non-empty option argument.'
exit 17
;;
-k | --key) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_KEY=$2
shift
else
showError '"--key" requires a non-empty option argument.'
exit 17
fi
;;
-k=?* | --key=?*)
VDM_KEY=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
-k= | --key=) # Handle the case of an empty --key=
showError '"--key=" requires a non-empty option argument.'
exit 17
;;
-e | --env-key) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_ENV_KEY=$2
shift
else
showError '"--env-key" requires a non-empty option argument.'
exit 17
fi
;;
-e=?* | --env-key=?*)
VDM_ENV_KEY=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
-e= | --env-key=) # Handle the case of an empty --env-key=
showError '"--env-key=" requires a non-empty option argument.'
exit 17
;;
-d | --domain) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_DOMAIN=$2
# set the ARG domain as true
VDM_ARG_DOMAIN=true
shift
else
showError '"--domain" requires a non-empty option argument.'
exit 17
fi
;;
-d=?* | --domain=?*)
VDM_DOMAIN=${1#*=} # Delete everything up to "=" and assign the remainder.
# set the ARG domain as true
VDM_ARG_DOMAIN=true
;;
-d= | --domain=) # Handle the case of an empty --domain=
showError '"--domain=" requires a non-empty option argument.'
exit 17
;;
-s | --sub-domain) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_SUBDOMAIN=$2
shift
else
showError '"--sub-domain" requires a non-empty option argument.'
exit 17
fi
;;
-s=?* | --sub-domain=?*)
VDM_SUBDOMAIN=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
-s= | --sub-domain=) # Handle the case of an empty --sub-domain=
showError '"--sub-domain=" requires a non-empty option argument.'
exit 17
;;
--sudo)
VDM_SUDO_ACCESS=true
shift
;;
-u | --username) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_USER_NAME=$2
shift
else
showError '"--username" requires a non-empty option argument.'
exit 17
fi
;;
-u=?* | --username=?*)
VDM_USER_NAME=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
-u= | --username=) # Handle the case of an empty --username=
showError '"--username=" requires a non-empty option argument.'
exit 17
;;
--uid) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_PUID=$2
shift
else
showError '"--uid" requires a non-empty option argument.'
exit 17
fi
;;
--uid=?*)
VDM_PUID=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
--uid=) # Handle the case of an empty --uid=
showError '"--uid=" requires a non-empty option argument.'
exit 17
;;
--gid) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_PGID=$2
shift
else
showError '"--gid" requires a non-empty option argument.'
exit 17
fi
;;
--gid=?*)
VDM_PGID=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
--gid=) # Handle the case of an empty --gid=
showError '"--gid=" requires a non-empty option argument.'
exit 17
;;
-p | --port) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_PORT=$2
shift
else
showError '"--port" requires a non-empty option argument.'
exit 17
fi
;;
-p=?* | --port=?*)
VDM_PORT=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
-p= | --port=) # Handle the case of an empty --port=
showError '"--port=" requires a non-empty option argument.'
exit 17
;;
--ssh-dir) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_PUBLIC_KEY_DIR=$2
shift
else
showError '"--ssh-dir" requires a non-empty option argument.'
exit 17
fi
;;
--ssh-dir=?*)
VDM_PUBLIC_KEY_DIR=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
-ssh-dir=) # Handle the case of an empty --ssh-dir=
showError '"--ssh-dir=" requires a non-empty option argument.'
exit 17
;;
-t | --time-zone) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
VDM_TZ=$2
shift
else
showError '"--time-zone" requires a non-empty option argument.'
exit 17
fi
;;
-t=?* | --time-zone=?*)
VDM_TZ=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
-t= | --time-zone=) # Handle the case of an empty --time-zone=
showError '"--time-zone=" requires a non-empty option argument.'
exit 17
;;
*) # Default case: No more options, so break out of the loop.
break ;;
esac
shift
done
#####################################################################################################################VDM
######################################## CLI PREP
# set the type and task if we have a container value
if [ ${#VDM_CONTAINER} -ge 1 ]; then
# check that the type is set (default Joomla)
VDM_CONTAINER_TYPE="${VDM_CONTAINER_TYPE:-joomla}"
# check that the task is set (default enable)
VDM_TASK="${VDM_TASK:-enable}"
fi
# set the container value if we have type and task set and not the container value
if [ ${#VDM_CONTAINER} -le 1 ] &&
[ ${#VDM_CONTAINER_TYPE} -ge 1 ] &&
[ ${#VDM_TASK} -ge 1 ] &&
[ ${#VDM_DOMAIN} -ge 1 ]; then
# we set the sub based on what was set
sub=''
if [ ${#VDM_SUBDOMAIN} -ge 1 ]; then
sub="${VDM_SUBDOMAIN}"
elif [ "${VDM_CONTAINER_TYPE}" = 'portainer' ]; then
sub="port"
elif [ "${VDM_CONTAINER_TYPE}" = 'traefik' ]; then
sub="traefik"
elif [ ${#VDM_USER_NAME} -ge 1 ]; then
sub="${VDM_USER_NAME}"
fi
# check if we now have a value
if [ ${#sub} -le 1 ]; then
showError 'Setting the type and task, and not setting the container details will require further input.'
else
# we set the container defaults based an user input
VDM_CONTAINER="${sub:-vdm}.${VDM_DOMAIN}"
fi
fi
#####################################################################################################################VDM
######################################## SETUP KEY PATHS
# the src folder path is where we store the script global env
VDM_SRC_PATH="/home/${USER}/.config/octojoom"
# create the folder if not set
# shellcheck disable=SC2174
mkdir -p -m '700' "${VDM_SRC_PATH}"
# first run switch
VDM_FIRST_RUN=false
# load the globals
# shellcheck disable=SC1090 source=/dev/null
[ -f "${VDM_SRC_PATH}/.env" ] && source "${VDM_SRC_PATH}/.env"
# get repo path where store the container deploy scripts
while [ ${#VDM_REPO_PATH} -le 1 ] || [ ! -d "${VDM_REPO_PATH}" ]; do
# creat the path if it exist
if [ ${#VDM_REPO_PATH} -ge 1 ] && (whiptail --yesno "Can we create the ${VDM_REPO_PATH} repository folder" \
--title "Create the Path" --backtitle "${BACK_TITLE}" 8 112); then
mkdir -p "${VDM_REPO_PATH}"
else
# get the value
VDM_REPO_PATH=$(getInput "Enter the repository path where we can store the containers' docker-composer.yml deployment files." \
"/home/${USER}/Docker" 'Enter Repository Path')
# keep asking if empty or does exist
if [ ${#VDM_REPO_PATH} -ge 1 ] && [ ! -d "${VDM_REPO_PATH}" ] && (whiptail --yesno "Can we create the ${VDM_REPO_PATH} repository folder" \
--title "Create the Path" --backtitle "${BACK_TITLE}" 8 112); then
mkdir -p "${VDM_REPO_PATH}"
elif [ ${#VDM_REPO_PATH} -le 1 ]; then
showError "You must set a repository path where we can store the containers' docker-composer.yml deployment files."
fi
fi
# trip switch of first run
VDM_FIRST_RUN=true
done
# add this value if not set variable
setEnvVariable "VDM_REPO_PATH=\"${VDM_REPO_PATH}\""
# get repo path where store the container deploy scripts
while [ ${#VDM_PROJECT_PATH} -le 1 ] || [ ! -d "${VDM_PROJECT_PATH}" ]; do
# create the path if it exist
if [ ${#VDM_PROJECT_PATH} -ge 1 ] && (whiptail --yesno "Can we create the ${VDM_PROJECT_PATH} projects' folder" \
--title "Create the Path" --backtitle "${BACK_TITLE}" 8 112); then
mkdir -p "${VDM_PROJECT_PATH}"
else
# get the value
VDM_PROJECT_PATH=$(getInput "Enter the projects' path where we can store the containers' persistent volumes." \
"/home/${USER}/Projects" "Enter Projects' Path")
# keep asking if empty or does exist
if [ ${#VDM_PROJECT_PATH} -ge 1 ] && [ ! -d "${VDM_PROJECT_PATH}" ] && (whiptail --yesno "Can we create the ${VDM_PROJECT_PATH} projects folder" \
--title "Create the Path" --backtitle "${BACK_TITLE}" 8 112); then
mkdir -p "${VDM_PROJECT_PATH}"
elif [ ${#VDM_PROJECT_PATH} -le 1 ]; then
showError "You must set a projects' path where we can store the containers' persistent volumes."
fi
fi
# trip switch of first run
VDM_FIRST_RUN=true
done
# add this value if not set variable
setEnvVariable "VDM_PROJECT_PATH=\"${VDM_PROJECT_PATH}\""
# set these globally
export VDM_REPO_PATH
export VDM_PROJECT_PATH
# if this is the first run we should setup traefik
$VDM_FIRST_RUN && {
# set traefik as the container type
: "${VDM_CONTAINER_TYPE:=traefik}"
# and enable it
: "${VDM_TASK:=setup}"
# first setup the network
setNetworks
# trigger main
main
# clear it again
VDM_CONTAINER_TYPE=''
VDM_TASK=''
}
#####################################################################################################################VDM
######################################## MAIN ┬┴┬┴┤(・_├┬┴┬┴
main