chore(cleanup): retire appGenerate — dead-on-arrival app-skeleton wizard
`libreportal app generate <name>` (and the menu's "g. Generate App" entry)
was broken three independent ways and incompatible with the per-app
architecture the project actually uses now:
1. Copies from $install_containers_dir/template/ which doesn't exist —
the only template/ in the tree was in scripts/unused/OLD_CONTAINERS/
and was never installed into the live tree. cp -r would just fail.
2. Every sed call used BSD/macOS syntax `sed -i '' -e …`. On Linux
(every distro this targets) the empty '' becomes a positional file
argument, so the substitutions never ran. 8 calls, all broken.
3. Even if it had run, the produced skeleton would have been a
pre-modular-tools / pre-per-port-subdomain app shape: no tools/,
no scripts/ subdir, HOST_NAME=test in the .config. Every active
containers/<app>/ today carries the modular layout the rest of the
framework expects.
Plus the recent cleanups (the prompt loop fix in 9ffc8e4, the per-port
subdomain refactor in 2e4f420) had been peeling pieces off it without
the root question — does the function still belong? — getting asked.
Delete the whole surface:
- scripts/app/app_generate.sh (157 lines, the function body)
- scripts/unused/OLD_CONTAINERS/template/ (the never-installed source
files appGenerate would have copied — stale enough to still carry
HOST_NAME=test, CFG_<X>_HOST_NAME, and 248 lines of compose template)
- menu entry "g. Generate App" + its dispatch in menu_main.sh
- "generate" case branch in cli_app_commands.sh
- `libreportal app generate` line in cli_app_header.sh
- The corresponding entries auto-drop from files_app.sh +
function_manifest.sh via regen.
New apps are added the way the catalog already grew — by hand-crafting
containers/<app>/{<app>.sh, <app>.config, docker-compose.yml,
tools/<app>.tools.json, scripts/<app>_*.sh}. Copying an existing app's
folder + renaming is the closest thing to a "generator" and it's a one-
command operation.
Net: -556 lines, no behaviour lost (the function never worked).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
parent
b63e60c85f
commit
52e0227bb6
@ -1,157 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
appGenerate()
|
||||
{
|
||||
local app_name="$1"
|
||||
|
||||
isHeader "LibrePortal Application Generator"
|
||||
isNotice "USAGE : This is for generating new container installation scripts for LibrePortal"
|
||||
echo ""
|
||||
|
||||
while true; do
|
||||
if [[ -z "$app_name" ]]; then
|
||||
isQuestion "Please enter the name of the application you would like to create a script for: "
|
||||
read -p "" app_name
|
||||
app_name=$(echo "$app_name" | sed 's/^[ \t]*//;s/[ \t]*$//') # Trim leading/trailing whitespace
|
||||
fi
|
||||
|
||||
# Debug output to see the actual input
|
||||
# echo "DEBUG: app_name = '$app_name'"
|
||||
|
||||
if [[ -d "$install_containers_dir$app_name" ]]; then
|
||||
isError "A folder with that name already exists. Please choose another name."
|
||||
app_name="" # Reset app_name to prompt for a new input
|
||||
elif echo "$app_name" | grep -q '[[:space:]]\|[0-9]'; then
|
||||
isError "The application name cannot contain any numbers or spaces. Please choose another name."
|
||||
app_name="" # Reset app_name to prompt for a new input
|
||||
else
|
||||
isSuccessful "Valid application name given."
|
||||
cap_first_app_name=$(echo "$app_name" | awk '{print toupper(substr($0,1,1)) tolower(substr($0,2))}')
|
||||
full_caps_app_name=$(echo "$app_name" | awk '{print toupper($0)}')
|
||||
echo ""
|
||||
break
|
||||
fi
|
||||
isNotice "Please provide a valid app name."
|
||||
echo ""
|
||||
done
|
||||
|
||||
while true; do
|
||||
isQuestion "Please enter a short description (e.g a Finance Mananger): "
|
||||
read -p "" app_description
|
||||
if [[ $? -eq 0 ]]; then
|
||||
break
|
||||
fi
|
||||
echo "Please provide a valid description"
|
||||
done
|
||||
|
||||
while true; do
|
||||
echo ""
|
||||
isNotice "Please select the application category:"
|
||||
echo ""
|
||||
for i in "${!app_categories[@]}"; do
|
||||
local capitalized_category=$(echo "${app_categories[$i]}" | awk '{print toupper(substr($0, 1, 1)) tolower(substr($0, 2))}')
|
||||
isOption "$((i + 1)). ${capitalized_category} App"
|
||||
done
|
||||
echo ""
|
||||
isQuestion "Enter your choice (1-${#app_categories[@]}): "
|
||||
read -rp "" app_selection
|
||||
echo ""
|
||||
|
||||
# Validate input
|
||||
if [[ "$app_selection" =~ ^[1-9][0-9]*$ ]] && [ "$app_selection" -le "${#app_categories[@]}" ]; then
|
||||
local selected_category="${app_categories[$((app_selection - 1))]}"
|
||||
isNotice "Application will be set to a ${selected_category^} App"
|
||||
app_category=$selected_category
|
||||
break
|
||||
else
|
||||
isNotice "Invalid choice. Please enter a number between '1' and '${#app_categories[@]}'."
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ! -d "$install_containers_dir$app_name" ]]; then
|
||||
|
||||
local app_script_file="$install_containers_dir$app_name/$app_name.sh"
|
||||
local app_config_file="$install_containers_dir$app_name/$app_name.config"
|
||||
|
||||
local result=$(createFolders "loud" $docker_install_user $install_containers_dir$app_name)
|
||||
checkSuccess "Creating new folder named $app_name"
|
||||
local result=$(runInstallOp cp -r $install_containers_dir/template/* $install_containers_dir$app_name)
|
||||
checkSuccess "Copying template files to the $app_name folder"
|
||||
local result=$(runInstallOp mv $install_containers_dir$app_name/template.sh "$app_script_file")
|
||||
checkSuccess "Renaming script file for $app_name"
|
||||
local result=$(runInstallOp mv $install_containers_dir$app_name/template.config "$app_config_file")
|
||||
checkSuccess "Renaming config file for $app_name"
|
||||
|
||||
# Script updates
|
||||
local result=$(runInstallOp sed -i '' -e 's/Template/'"$cap_first_app_name"'/g' "$app_script_file" > /dev/null 2>&1)
|
||||
checkSuccess "Update $app_name.sh - all cases of Template to $cap_first_app_name"
|
||||
local result=$(runInstallOp sed -i '' -e 's/template/'"$app_name"'/g' "$app_script_file" > /dev/null 2>&1)
|
||||
checkSuccess "Update $app_name.sh - all cases of template to $app_name"
|
||||
local result=$(runInstallOp sed -i '' -e 's/TEMPLATE/'"$full_caps_app_name"'/g' "$app_script_file" > /dev/null 2>&1)
|
||||
checkSuccess "Update $app_name.sh - all cases of TEMPLATE to $full_caps_app_name"
|
||||
local result=$(runInstallOp sed -i '' -e 's/old/'"$app_category"'/g' "$app_script_file" > /dev/null 2>&1)
|
||||
checkSuccess "Updating $app_name.sh - category to $app_category"
|
||||
local result=$(runInstallOp sed -i '' -e 's/Placeholder!/'"$app_description"'/g' "$app_script_file" > /dev/null 2>&1)
|
||||
checkSuccess "Updating $app_name.sh - description to $app_description"
|
||||
|
||||
# Config updates
|
||||
local result=$(runInstallOp sed -i '' -e 's/Template/'"$cap_first_app_name"'/g' "$app_config_file" > /dev/null 2>&1)
|
||||
checkSuccess "Update $app_name.config - all cases of Template to $cap_first_app_name"
|
||||
local result=$(runInstallOp sed -i '' -e 's/template/'"$app_name"'/g' "$app_config_file" > /dev/null 2>&1)
|
||||
checkSuccess "Update $app_name.config - all cases of template to $app_name"
|
||||
local result=$(runInstallOp sed -i '' -e 's/TEMPLATE/'"$full_caps_app_name"'/g' "$app_config_file" > /dev/null 2>&1)
|
||||
checkSuccess "Update $app_name.config - all cases of TEMPLATE to $full_caps_app_name"
|
||||
|
||||
while true; do
|
||||
echo ""
|
||||
isQuestion "Would you like to add contents to the docker-compose.yml? (y/n): "
|
||||
read -p "" app_docker_compose
|
||||
if [[ -n "$app_docker_compose" ]]; then
|
||||
break
|
||||
fi
|
||||
isNotice "Please provide a valid input."
|
||||
done
|
||||
if [[ "$app_docker_compose" == [yY] ]]; then
|
||||
$CFG_TEXT_EDITOR "$install_containers_dir$app_name/docker-compose.yml"
|
||||
fi
|
||||
|
||||
while true; do
|
||||
echo ""
|
||||
isQuestion "Would you like to edit the $app_name.config? (y/n): "
|
||||
read -p "" app_config
|
||||
if [[ -n "$app_config" ]]; then
|
||||
break
|
||||
fi
|
||||
isNotice "Please provide a valid input."
|
||||
done
|
||||
if [[ "$app_config" == [yY] ]]; then
|
||||
$CFG_TEXT_EDITOR "$install_containers_dir$app_name/$app_name.config"
|
||||
fi
|
||||
|
||||
while true; do
|
||||
echo ""
|
||||
isQuestion "Would you like to edit the $app_name.sh install script? (y/n): "
|
||||
read -p "" app_script
|
||||
if [[ -n "$app_script" ]]; then
|
||||
break
|
||||
fi
|
||||
isNotice "Please provide a valid input."
|
||||
done
|
||||
if [[ "$app_script" == [yY] ]]; then
|
||||
$CFG_TEXT_EDITOR "$install_containers_dir$app_name/$app_name.sh"
|
||||
fi
|
||||
|
||||
while true; do
|
||||
echo ""
|
||||
isQuestion "Would you like to install $app_name? (y/n): "
|
||||
read -p "" app_install
|
||||
if [[ -n "$app_install" ]]; then
|
||||
break
|
||||
fi
|
||||
isNotice "Please provide a valid input."
|
||||
done
|
||||
if [[ "$app_install" == [yY] ]]; then
|
||||
dockerInstallApp $app_name
|
||||
fi
|
||||
fi
|
||||
}
|
||||
@ -96,15 +96,6 @@ cliHandleAppCommands()
|
||||
fi
|
||||
;;
|
||||
|
||||
"generate")
|
||||
if [[ -z "$app_name" ]]; then
|
||||
isNotice "No app provided."
|
||||
cliShowAppHelp
|
||||
else
|
||||
appGenerate "$app_name"
|
||||
fi
|
||||
;;
|
||||
|
||||
"status")
|
||||
if [[ -z "$app_name" ]]; then
|
||||
isNotice "No app provided."
|
||||
|
||||
@ -30,7 +30,6 @@ cliShowAppHelp()
|
||||
echo " libreportal app restore [name*] [file|--latest] [password] - Restore from local/remote, prefers local"
|
||||
echo " libreportal app restore [name*] [local|remote1|remote2] [file] [password]"
|
||||
echo " - Restore from a specific location"
|
||||
echo " libreportal app generate [name*] - Generates new application container install files"
|
||||
echo " libreportal app status [name*] - Show status of specified app"
|
||||
echo " libreportal app tool [name*] [tool*] [args]"
|
||||
echo " - Run a per-app tool (Tools tab actions)."
|
||||
|
||||
@ -20,7 +20,6 @@ mainMenu()
|
||||
isHeader "Install Menu"
|
||||
isOption "i. Install Apps"
|
||||
isOption "u. Uninstall Apps"
|
||||
isOption "g. Generate App"
|
||||
isHeader "Backup/Restore/Migrate"
|
||||
isOption "b. Backup"
|
||||
isOption "r. Restore"
|
||||
@ -51,10 +50,6 @@ mainMenu()
|
||||
u)
|
||||
appUninstallMenu;
|
||||
|
||||
;;
|
||||
g)
|
||||
appGenerate;
|
||||
|
||||
;;
|
||||
s)
|
||||
setupWizardReset;
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
# Do not edit manually - run './scripts/source/files/generate_arrays.sh run' to regenerate
|
||||
|
||||
app_scripts=(
|
||||
"app/app_generate.sh"
|
||||
"app/app_get_key_data.sh"
|
||||
"app/app_scan_available.sh"
|
||||
"app/app_status.sh"
|
||||
|
||||
@ -38,7 +38,6 @@ declare -gA LP_FN_MAP=(
|
||||
[appFocalboardListUsers]="focalboard/tools/focalboard_list_users.sh"
|
||||
[appFocalboardResetPassword]="focalboard/tools/focalboard_reset_password.sh"
|
||||
[appFocalboardSetAdmin]="focalboard/scripts/focalboard_set_admin.sh"
|
||||
[appGenerate]="app/app_generate.sh"
|
||||
[appGetKeyData]="app/app_get_key_data.sh"
|
||||
[appGiteaCreateAccount]="gitea/tools/gitea_create_account.sh"
|
||||
[appGiteaDeleteUser]="gitea/tools/gitea_delete_user.sh"
|
||||
@ -483,6 +482,7 @@ declare -gA LP_FN_MAP=(
|
||||
[installRecommendedApps]="start/start_recommended.sh"
|
||||
[installResticHost]="install/install_restic.sh"
|
||||
[installResticMigrateLegacyPasswords]="install/install_restic.sh"
|
||||
[installRootlessApparmorForPasta]="docker/install/rootless/rootless_apparmor.sh"
|
||||
[installSearxng]="searxng/searxng.sh"
|
||||
[installSpeedtest]="speedtest/speedtest.sh"
|
||||
[installSQLiteDatabase]="database/install_sqlite.sh"
|
||||
@ -901,7 +901,6 @@ declare -gA LP_FN_ROOT=(
|
||||
[appFocalboardListUsers]="containers"
|
||||
[appFocalboardResetPassword]="containers"
|
||||
[appFocalboardSetAdmin]="containers"
|
||||
[appGenerate]="scripts"
|
||||
[appGetKeyData]="scripts"
|
||||
[appGiteaCreateAccount]="containers"
|
||||
[appGiteaDeleteUser]="containers"
|
||||
@ -1346,6 +1345,7 @@ declare -gA LP_FN_ROOT=(
|
||||
[installRecommendedApps]="scripts"
|
||||
[installResticHost]="scripts"
|
||||
[installResticMigrateLegacyPasswords]="scripts"
|
||||
[installRootlessApparmorForPasta]="scripts"
|
||||
[installSearxng]="containers"
|
||||
[installSpeedtest]="containers"
|
||||
[installSQLiteDatabase]="scripts"
|
||||
@ -1782,7 +1782,6 @@ appFocalboardDeleteUser() { source "${install_containers_dir}focalboard/tools/fo
|
||||
appFocalboardListUsers() { source "${install_containers_dir}focalboard/tools/focalboard_list_users.sh"; appFocalboardListUsers "$@"; }
|
||||
appFocalboardResetPassword() { source "${install_containers_dir}focalboard/tools/focalboard_reset_password.sh"; appFocalboardResetPassword "$@"; }
|
||||
appFocalboardSetAdmin() { source "${install_containers_dir}focalboard/scripts/focalboard_set_admin.sh"; appFocalboardSetAdmin "$@"; }
|
||||
appGenerate() { source "${install_scripts_dir}app/app_generate.sh"; appGenerate "$@"; }
|
||||
appGetKeyData() { source "${install_scripts_dir}app/app_get_key_data.sh"; appGetKeyData "$@"; }
|
||||
appGiteaCreateAccount() { source "${install_containers_dir}gitea/tools/gitea_create_account.sh"; appGiteaCreateAccount "$@"; }
|
||||
appGiteaDeleteUser() { source "${install_containers_dir}gitea/tools/gitea_delete_user.sh"; appGiteaDeleteUser "$@"; }
|
||||
@ -2227,6 +2226,7 @@ installPrometheus() { source "${install_containers_dir}prometheus/prometheus.sh"
|
||||
installRecommendedApps() { source "${install_scripts_dir}start/start_recommended.sh"; installRecommendedApps "$@"; }
|
||||
installResticHost() { source "${install_scripts_dir}install/install_restic.sh"; installResticHost "$@"; }
|
||||
installResticMigrateLegacyPasswords() { source "${install_scripts_dir}install/install_restic.sh"; installResticMigrateLegacyPasswords "$@"; }
|
||||
installRootlessApparmorForPasta() { source "${install_scripts_dir}docker/install/rootless/rootless_apparmor.sh"; installRootlessApparmorForPasta "$@"; }
|
||||
installSearxng() { source "${install_containers_dir}searxng/searxng.sh"; installSearxng "$@"; }
|
||||
installSpeedtest() { source "${install_containers_dir}speedtest/speedtest.sh"; installSpeedtest "$@"; }
|
||||
installSQLiteDatabase() { source "${install_scripts_dir}database/install_sqlite.sh"; installSQLiteDatabase "$@"; }
|
||||
|
||||
@ -1,248 +0,0 @@
|
||||
# ╔══════════════════════════════════════════════════════════════╗
|
||||
# ║ LibrePortal - Comprehensive Test Template ║
|
||||
# ║ Tests All Tagging System Features ║
|
||||
# ╚══════════════════════════════════════════════════════════════╝
|
||||
#
|
||||
# ⚠️ AUTOMATICALLY GENERATED - DO NOT EDIT MANUALLY ⚠️
|
||||
# All configurations are managed by LibrePortal tagging system
|
||||
#
|
||||
# 🏷️ TAGGING SYSTEM EXPLANATIONS:
|
||||
# =====================================
|
||||
#
|
||||
# 📋 SERVICE TAGS:
|
||||
#
|
||||
# - SERVICE_TAG_N: Identifies services for IP allocation
|
||||
# - Format: #LIBREPORTAL|SERVICE_TAG_N|service_name
|
||||
# - Services with IP_DATA_N tags get IP addresses allocated
|
||||
# - Services without IP_DATA_N are skipped for IP allocation
|
||||
#
|
||||
# 🔌 PORT SYSTEM:
|
||||
#
|
||||
# - PORT_DATA_N: Port number placeholder (gets replaced with allocated port)
|
||||
# - PORT_TAG_N: Port tracking tag (gets updated with same port number)
|
||||
# - Used in: ports section, Traefik config, UFW labels
|
||||
# - Global replacement: All PORT_DATA_N instances get same port
|
||||
#
|
||||
# 🔐 PASSWORD SYSTEM:
|
||||
#
|
||||
# - PASSWORD_DATA_N: Password placeholder (gets replaced with generated password)
|
||||
# - PASSWORD_TAG_N: Password tracking tag (gets updated with same password)
|
||||
# - Global replacement: All PASSWORD_DATA_N instances get same password
|
||||
# - Shared passwords: Same PASSWORD_DATA_N used across multiple services
|
||||
#
|
||||
# 🌐 IP SYSTEM:
|
||||
#
|
||||
# - IP_DATA_N: IP address placeholder (gets replaced with allocated IP)
|
||||
# - IP_TAG_N: IP tracking tag (gets updated with same IP address)
|
||||
# - Only services with IP_DATA_N get IP addresses allocated
|
||||
# - Database tracking: Service-to-IP mappings stored persistently
|
||||
#
|
||||
# 📋 STANDARD TAGS:
|
||||
#
|
||||
# - TIMEZONE_DATA/TIMEZONE_TAG: Timezone configuration
|
||||
# - EMAIL_DATA/EMAIL_TAG: Email address configuration
|
||||
# - CATEGORY_DATA/CATEGORY_TAG: App category for LibrePortal
|
||||
# - TITLE_DATA/TITLE_TAG: App title for LibrePortal
|
||||
# - DOMAINSUBNAME_DATA/DOMAINSUBNAME_TAG: Domain for Traefik routing
|
||||
# - DOMAINNAME_DATA/DOMAINNAME_TAG: Full domain name
|
||||
# - DOMAINPREFIX_DATA/DOMAINPREFIX_TAG: Domain prefix
|
||||
# - PUBLICIP_DATA/PUBLICIP_TAG: Public IP address
|
||||
# - SUBNET_DATA/SUBNET_TAG: Network subnet
|
||||
# - GATEWAY_DATA/GATEWAY_TAG: Network gateway
|
||||
# - DOCKERNETWORK_DATA/DOCKERNETWORK_TAG: Docker network name
|
||||
# - MTU_DATA/MTU_TAG: Network MTU setting
|
||||
#
|
||||
# 🚦 TRAEFIK CONTROL:
|
||||
#
|
||||
# - TRAEFIK_ENABLE_DATA/TRAEFIK_ENABLE_TAG: Enable/disable Traefik
|
||||
# - When false: All Traefik labels are ignored but remain valid
|
||||
# - When true: Traefik processes all routing and SSL configuration
|
||||
#
|
||||
# ⚕️ HEALTHCHECK:
|
||||
#
|
||||
# - HEALTHCHECK_DATA/HEALTHCHECK_TAG: Enable/disable healthchecks
|
||||
# - true: Healthcheck disabled, false: Healthcheck enabled
|
||||
#
|
||||
# 🔧 DOCKER INSTALLATION:
|
||||
#
|
||||
# - SOCKET_TAG/SOCKET_DATA: Docker socket path for rootless/rooted
|
||||
# - UID_TAG/GID_TAG: User ID for rootless Docker installation
|
||||
# - DOCKERINSTALLUSER_TAG: Docker installation user tracking
|
||||
#
|
||||
# 🌐 PORT BINDING:
|
||||
#
|
||||
# - PORT_BINDING tag: Controls 0.0.0.0 vs 127.0.0.1 binding
|
||||
# - Private apps: 127.0.0.1 (localhost only)
|
||||
# - Public apps: 0.0.0.0 (accessible externally)
|
||||
#
|
||||
# 🎯 EXAMPLES IN THIS TEMPLATE:
|
||||
# ==========================
|
||||
#
|
||||
# 🔌 PORT USAGE:
|
||||
#
|
||||
# - PORT_DATA_1 used in 3 places: ports section, Traefik loadbalancer, UFW labels
|
||||
# - All instances get replaced with same allocated port (e.g., 3123)
|
||||
#
|
||||
# 🔐 PASSWORD SHARING:
|
||||
#
|
||||
# - PASSWORD_DATA_1: Shared between webapp (ADMIN_PASSWORD) and worker (ADMIN_PASSWORD)
|
||||
# - PASSWORD_DATA_2: Shared between webapp (DB_PASSWORD), database (POSTGRES_PASSWORD), worker (DB_PASSWORD)
|
||||
# - PASSWORD_DATA_3: Shared between webapp (API_KEY) and redis (REDIS_PASSWORD)
|
||||
#
|
||||
# 🌐 IP ALLOCATION:
|
||||
#
|
||||
# - SERVICE_TAG_1 (webapp) → IP_DATA_1 → Gets IP allocated
|
||||
# - SERVICE_TAG_2 (database) → IP_DATA_2 → Gets IP allocated
|
||||
# - SERVICE_TAG_3 (redis) → IP_DATA_3 → Gets IP allocated
|
||||
# - SERVICE_TAG_4 (worker) → No IP_DATA_N → No IP allocated (internal only)
|
||||
#
|
||||
# 🚦 TRAEFIK INTEGRATION:
|
||||
#
|
||||
# - TRAEFIK_ENABLE_DATA controls if webapp is accessible via domain
|
||||
# - Domain routing uses DOMAINSUBNAME_DATA for SSL certificate
|
||||
# - Load balancer uses PORT_DATA_1 for internal port mapping
|
||||
|
||||
networks:
|
||||
vpn:
|
||||
external: true
|
||||
|
||||
services:
|
||||
# Main web application service
|
||||
# SERVICE_TAG_1: This service needs IP allocation (has IP_DATA_1)
|
||||
webapp: #LIBREPORTAL|SERVICE_TAG_1|webapp
|
||||
container_name: test-webapp
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
# PORT_EXTERNAL_1: External port mapping (gets allocated port like 3123)
|
||||
# Used in 3 places: here, Traefik loadbalancer, UFW labels
|
||||
- "PORT_DATA_1:3000" #LIBREPORTAL|PORT_TAG_1|PORT_DATA_1
|
||||
volumes:
|
||||
- ./data:/app/data
|
||||
- ./config:/app/config:ro
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
# Standard LibrePortal configuration tags
|
||||
TZ: TIMEZONE_DATA #LIBREPORTAL|TIMEZONE_TAG|TIMEZONE_DATA
|
||||
EMAIL: EMAIL_DATA #LIBREPORTAL|EMAIL_TAG|EMAIL_DATA
|
||||
|
||||
# Password placeholders for testing
|
||||
# PASSWORD_DATA_1: Shared with worker service (same password everywhere)
|
||||
ADMIN_PASSWORD: PASSWORD_DATA_1 #LIBREPORTAL|PASSWORD_TAG_1|PASSWORD_DATA_1
|
||||
# PASSWORD_DATA_2: Shared with database and worker services
|
||||
DB_PASSWORD: PASSWORD_DATA_2 #LIBREPORTAL|PASSWORD_TAG_2|PASSWORD_DATA_2
|
||||
# PASSWORD_DATA_3: Shared with redis service
|
||||
API_KEY: PASSWORD_DATA_3 #LIBREPORTAL|PASSWORD_TAG_3|PASSWORD_DATA_3
|
||||
|
||||
# Application configuration
|
||||
APP_NAME: "Test Application"
|
||||
DEBUG: "true"
|
||||
LOG_LEVEL: "info"
|
||||
labels:
|
||||
# LibrePortal application metadata
|
||||
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
|
||||
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
|
||||
# UFW integration uses same port as external mapping
|
||||
libreportal.ufw-ports: "UFW_PORT_DATA_1" #LIBREPORTAL|UFW_PORTS_TAG|UFW_PORT_DATA_1
|
||||
libreportal.description: "Comprehensive test template for LibrePortal tagging system"
|
||||
|
||||
# Traefik reverse proxy configuration
|
||||
# TRAEFIK_ENABLE_DATA: Controls if this app is accessible via domain
|
||||
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
|
||||
traefik.http.routers.webapp.entrypoints: web,websecure
|
||||
# DOMAINSUBNAME_DATA: Domain name for SSL certificate and routing
|
||||
traefik.http.routers.webapp.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
|
||||
traefik.http.routers.webapp.tls: true
|
||||
traefik.http.routers.webapp.tls.certresolver: production
|
||||
# PORT_DATA_1: Internal port for Traefik load balancer (same as external)
|
||||
traefik.http.services.webapp.loadbalancer.server.port: 3000
|
||||
traefik.http.routers.webapp.middlewares:
|
||||
# DOCKERNETWORK_DATA: Docker network for Traefik communication
|
||||
traefik.docker.network: DOCKERNETWORK_DATA #LIBREPORTAL|DOCKERNETWORK_TAG|DOCKERNETWORK_DATA
|
||||
healthcheck:
|
||||
# HEALTHCHECK_DATA: Enable/disable healthcheck (true=disabled, false=enabled)
|
||||
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA
|
||||
networks:
|
||||
vpn:
|
||||
# IP_DATA_1: This service gets IP address allocated
|
||||
ipv4_address: IP_DATA_1 #LIBREPORTAL|IP_TAG_1|IP_DATA_1
|
||||
|
||||
# Database service (no external ports, only internal communication)
|
||||
# SERVICE_TAG_2: This service needs IP allocation (has IP_DATA_2)
|
||||
database: #LIBREPORTAL|SERVICE_TAG_2|database
|
||||
container_name: test-database
|
||||
image: postgres:13
|
||||
ports:
|
||||
# No external port mapping - internal only communication
|
||||
volumes:
|
||||
- ./db_data:/var/lib/postgresql/data
|
||||
environment:
|
||||
# Database configuration
|
||||
POSTGRES_DB: testdb
|
||||
POSTGRES_USER: admin
|
||||
# PASSWORD_DATA_2: Same password as webapp DB_PASSWORD and worker DB_PASSWORD
|
||||
POSTGRES_PASSWORD: PASSWORD_DATA_2 #LIBREPORTAL|PASSWORD_TAG_2|PASSWORD_DATA_2
|
||||
# TIMEZONE_DATA: Same timezone as all other services
|
||||
TZ: TIMEZONE_DATA #LIBREPORTAL|TIMEZONE_TAG|TIMEZONE_DATA
|
||||
labels:
|
||||
libreportal.category: "database"
|
||||
libreportal.description: "PostgreSQL database service"
|
||||
libreportal.internal: "true"
|
||||
healthcheck:
|
||||
disable: false
|
||||
networks:
|
||||
vpn:
|
||||
# IP_DATA_2: This service gets IP address allocated
|
||||
ipv4_address: IP_DATA_2 #LIBREPORTAL|IP_TAG_2|IP_DATA_2
|
||||
|
||||
# Redis cache service (no external ports, internal only)
|
||||
# SERVICE_TAG_3: This service needs IP allocation (has IP_DATA_3)
|
||||
redis: #LIBREPORTAL|SERVICE_TAG_3|redis
|
||||
container_name: test-redis
|
||||
image: redis:alpine
|
||||
ports:
|
||||
# No external port mapping - internal only communication
|
||||
volumes:
|
||||
- ./redis_data:/data
|
||||
environment:
|
||||
# Redis configuration
|
||||
# PASSWORD_DATA_3: Same password as webapp API_KEY
|
||||
REDIS_PASSWORD: PASSWORD_DATA_3 #LIBREPORTAL|PASSWORD_TAG_3|PASSWORD_DATA_3
|
||||
# TIMEZONE_DATA: Same timezone as all other services
|
||||
TZ: TIMEZONE_DATA #LIBREPORTAL|TIMEZONE_TAG|TIMEZONE_DATA
|
||||
# Redis uses environment variable for password
|
||||
command: redis-server --requirepass $REDIS_PASSWORD
|
||||
labels:
|
||||
libreportal.category: "cache"
|
||||
libreportal.description: "Redis cache service"
|
||||
libreportal.internal: "true"
|
||||
healthcheck:
|
||||
disable: false
|
||||
networks:
|
||||
vpn:
|
||||
# IP_DATA_3: This service gets IP address allocated
|
||||
ipv4_address: IP_DATA_3 #LIBREPORTAL|IP_TAG_3|IP_DATA_3
|
||||
|
||||
# Background worker service (no IP needed, internal processing only)
|
||||
# SERVICE_TAG_4: This service does NOT need IP allocation (no IP_DATA_N)
|
||||
worker: #LIBREPORTAL|SERVICE_TAG_4|worker
|
||||
container_name: test-worker
|
||||
image: python:alpine
|
||||
volumes:
|
||||
- ./worker:/app
|
||||
environment:
|
||||
# Worker configuration with shared passwords
|
||||
# PASSWORD_DATA_1: Same password as webapp ADMIN_PASSWORD
|
||||
ADMIN_PASSWORD: PASSWORD_DATA_1 #LIBREPORTAL|PASSWORD_TAG_1|PASSWORD_DATA_1
|
||||
# PASSWORD_DATA_2: Same password as webapp DB_PASSWORD and database POSTGRES_PASSWORD
|
||||
DB_PASSWORD: PASSWORD_DATA_2 #LIBREPORTAL|PASSWORD_TAG_2|PASSWORD_DATA_2
|
||||
# TIMEZONE_DATA: Same timezone as all other services
|
||||
TZ: TIMEZONE_DATA #LIBREPORTAL|TIMEZONE_TAG|TIMEZONE_DATA
|
||||
command: python /app/worker.py
|
||||
labels:
|
||||
libreportal.category: "worker"
|
||||
libreportal.description: "Background worker service"
|
||||
libreportal.internal: "true"
|
||||
networks:
|
||||
vpn:
|
||||
# No IP allocation for worker service (internal only, no IP_DATA_N)
|
||||
@ -1,28 +0,0 @@
|
||||
#
|
||||
# APP_NAME = name of the application for use in the scripts
|
||||
# COMPOSE_FILE = default for no app_name in the docker compose file name, app if there is
|
||||
# HOST NAME = subdomain name e.g test is the name for test.website.com
|
||||
# DOMAIN = number of the domain from the general config, useful when using multiple domains
|
||||
# PUBLIC = if true, application will be setup with the reverse proxy and accessible from the internet
|
||||
# WHITELIST = if true only allow whitelisted ips (see general config), if false allow all
|
||||
# HEALTHCHECK = if true, the default docker health checks for that container will be enabled
|
||||
# AUTHELIA = if true, use Authelia authentication, if false turned off.
|
||||
# HEADSCALE = options : false, local, remote (see general config). e.g false or local,remote
|
||||
# PORTS = port number(s) that the application will be used (comma seperated)
|
||||
#
|
||||
CFG_TEMPLATE_APP_NAME=template
|
||||
CFG_TEMPLATE_BACKUP=true
|
||||
CFG_TEMPLATE_COMPOSE_FILE=default
|
||||
CFG_TEMPLATE_HOST_NAME=test
|
||||
CFG_TEMPLATE_DOMAIN=1
|
||||
CFG_TEMPLATE_PUBLIC=true
|
||||
CFG_TEMPLATE_WHIELIST=true
|
||||
CFG_TEMPLATE_HEALTHCHECK=true
|
||||
CFG_TEMPLATE_AUTHELIA=false
|
||||
CFG_TEMPLATE_HEADSCALE=false
|
||||
CFG_TEMPLATE_PORTS=12324
|
||||
# Application metadata
|
||||
CFG_TEMPLATE_CATEGORY="Miscellaneous"
|
||||
CFG_TEMPLATE_TITLE="Template"
|
||||
CFG_TEMPLATE_DESCRIPTION="Placeholder!"
|
||||
CFG_TEMPLATE_ACTIONS="configure|install|restart|shutdown|uninstall"
|
||||
@ -1,107 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Category : Miscellaneous
|
||||
# Description : Template - Placeholder! (c/u/s/r/i):
|
||||
|
||||
installTemplate()
|
||||
{
|
||||
local config_variables="$1"
|
||||
|
||||
if [[ "$template" == *[cCtTuUsSrRiI]* ]]; then
|
||||
dockerConfigSetupToContainer silent template;
|
||||
local app_name=$CFG_TEMPLATE_APP_NAME
|
||||
initializeAppVariables $app_name;
|
||||
fi
|
||||
|
||||
if [[ "$template" == *[cC]* ]]; then
|
||||
editAppConfig $app_name;
|
||||
fi
|
||||
|
||||
if [[ "$template" == *[uU]* ]]; then
|
||||
dockerUninstallApp $app_name;
|
||||
fi
|
||||
|
||||
if [[ "$template" == *[sS]* ]]; then
|
||||
dockerComposeDown $app_name;
|
||||
fi
|
||||
|
||||
if [[ "$template" == *[rR]* ]]; then
|
||||
dockerComposeRestart $app_name;
|
||||
fi
|
||||
|
||||
if [[ "$template" == *[iI]* ]]; then
|
||||
echo ""
|
||||
echo "##########################################"
|
||||
echo "### Install $app_name"
|
||||
echo "##########################################"
|
||||
echo ""
|
||||
|
||||
((menu_number++))
|
||||
echo ""
|
||||
echo "---- $menu_number. Setting up install folder and config file for $app_name."
|
||||
echo ""
|
||||
|
||||
dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables";
|
||||
isSuccessful "Install folders and Config files have been setup for $app_name."
|
||||
|
||||
((menu_number++))
|
||||
echo ""
|
||||
|
||||
|
||||
((menu_number++))
|
||||
echo ""
|
||||
echo "---- $menu_number. Setting up the $app_name docker-compose.yml file."
|
||||
echo ""
|
||||
|
||||
dockerComposeSetupFile $app_name;
|
||||
|
||||
((menu_number++))
|
||||
echo ""
|
||||
echo "---- $menu_number. Updating file permissions before starting."
|
||||
echo ""
|
||||
|
||||
fixPermissionsBeforeStart $app_name;
|
||||
|
||||
((menu_number++))
|
||||
echo ""
|
||||
echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name"
|
||||
echo ""
|
||||
|
||||
dockerComposeUpdateAndStartApp $app_name install;
|
||||
|
||||
((menu_number++))
|
||||
echo ""
|
||||
echo "---- $menu_number. Running Application specific updates (if required)"
|
||||
echo ""
|
||||
|
||||
appUpdateSpecifics $app_name;
|
||||
|
||||
((menu_number++))
|
||||
echo ""
|
||||
echo "---- $menu_number. Running Headscale setup (if required)"
|
||||
echo ""
|
||||
|
||||
setupHeadscale $app_name;
|
||||
|
||||
((menu_number++))
|
||||
echo ""
|
||||
echo "---- $menu_number. Adding $app_name to the Apps Database table."
|
||||
echo ""
|
||||
|
||||
databaseInstallApp $app_name;
|
||||
|
||||
((menu_number++))
|
||||
echo ""
|
||||
echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name"
|
||||
echo ""
|
||||
echo " You can now navigate to your $app_name service using any of the options below : "
|
||||
echo ""
|
||||
|
||||
menuShowFinalMessages $app_name;
|
||||
|
||||
menu_number=0
|
||||
#sleep 3s
|
||||
cd
|
||||
fi
|
||||
template=n
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user