diff --git a/docs/contribution/HELPER_FUNCTIONS.md b/docs/contribution/HELPER_FUNCTIONS.md new file mode 100644 index 000000000..d9e355dd2 --- /dev/null +++ b/docs/contribution/HELPER_FUNCTIONS.md @@ -0,0 +1,690 @@ +# 🛠️ Helper Functions Reference + +**Quick reference for all helper functions available in `tools.func`** + +> These functions are automatically available in install scripts via `$FUNCTIONS_FILE_PATH` + +--- + +## 📋 Table of Contents + +- [Scripts to Watch](#scripts-to-watch) +- [Runtime & Language Setup](#runtime--language-setup) +- [Database Setup](#database-setup) +- [GitHub Release Helpers](#github-release-helpers) +- [Tools & Utilities](#tools--utilities) +- [SSL/TLS](#ssltls) +- [Utility Functions](#utility-functions) +- [Package Management](#package-management) + +--- + +## 📚 Scripts to Watch + +**Learn from real, well-implemented scripts. Each app requires TWO files that work together:** + +| File | Location | Purpose | +| ------------------ | ---------------------------- | ------------------------------------------------------------------------ | +| **CT Script** | `ct/appname.sh` | Runs on **Proxmox host** - creates container, contains `update_script()` | +| **Install Script** | `install/appname-install.sh` | Runs **inside container** - installs and configures the app | + +> ⚠️ **Both files are ALWAYS required!** The CT script calls the install script automatically during container creation. + +### Node.js + PostgreSQL + +**Koel** - Music streaming with PHP + Node.js + PostgreSQL +| File | Link | +|------|------| +| CT (update logic) | [ct/koel.sh](../../ct/koel.sh) | +| Install | [install/koel-install.sh](../../install/koel-install.sh) | + +**Actual Budget** - Finance app with npm global install +| File | Link | +|------|------| +| CT (update logic) | [ct/actualbudget.sh](../../ct/actualbudget.sh) | +| Install | [install/actualbudget-install.sh](../../install/actualbudget-install.sh) | + +### Python + uv + +**MeTube** - YouTube downloader with Python uv + Node.js + Deno +| File | Link | +|------|------| +| CT (update logic) | [ct/metube.sh](../../ct/metube.sh) | +| Install | [install/metube-install.sh](../../install/metube-install.sh) | + +**Endurain** - Fitness tracker with Python uv + PostgreSQL/PostGIS +| File | Link | +|------|------| +| CT (update logic) | [ct/endurain.sh](../../ct/endurain.sh) | +| Install | [install/endurain-install.sh](../../install/endurain-install.sh) | + +### PHP + MariaDB/MySQL + +**Wallabag** - Read-it-later with PHP + MariaDB + Redis + Nginx +| File | Link | +|------|------| +| CT (update logic) | [ct/wallabag.sh](../../ct/wallabag.sh) | +| Install | [install/wallabag-install.sh](../../install/wallabag-install.sh) | + +**InvoiceNinja** - Invoicing with PHP + MariaDB + Supervisor +| File | Link | +|------|------| +| CT (update logic) | [ct/invoiceninja.sh](../../ct/invoiceninja.sh) | +| Install | [install/invoiceninja-install.sh](../../install/invoiceninja-install.sh) | + +**BookStack** - Wiki/Docs with PHP + MariaDB + Apache +| File | Link | +|------|------| +| CT (update logic) | [ct/bookstack.sh](../../ct/bookstack.sh) | +| Install | [install/bookstack-install.sh](../../install/bookstack-install.sh) | + +### PHP + SQLite (Simple) + +**Speedtest Tracker** - Speedtest with PHP + SQLite + Nginx +| File | Link | +|------|------| +| CT (update logic) | [ct/speedtest-tracker.sh](../../ct/speedtest-tracker.sh) | +| Install | [install/speedtest-tracker-install.sh](../../install/speedtest-tracker-install.sh) | + +--- + +## Runtime & Language Setup + +### `setup_nodejs` + +Install Node.js from NodeSource repository. + +```bash +# Default (Node.js 22) +setup_nodejs + +# Specific version +NODE_VERSION="20" setup_nodejs +NODE_VERSION="22" setup_nodejs +NODE_VERSION="24" setup_nodejs +``` + +### `setup_go` + +Install Go programming language (latest stable). + +```bash +setup_go + +# Use in script +setup_go +cd /opt/myapp +$STD go build -o myapp . +``` + +### `setup_rust` + +Install Rust via rustup. + +```bash +setup_rust + +# Use in script +setup_rust +source "$HOME/.cargo/env" +$STD cargo build --release +``` + +### `setup_uv` + +Install Python uv package manager (fast pip/venv replacement). + +```bash +setup_uv + +# Use in script +setup_uv +cd /opt/myapp +$STD uv sync --locked +``` + +### `setup_ruby` + +Install Ruby from official repositories. + +```bash +setup_ruby +``` + +### `setup_php` + +Install PHP with configurable modules and FPM/Apache support. + +```bash +# Basic PHP +setup_php + +# Full configuration +PHP_VERSION="8.3" \ +PHP_MODULE="mysqli,gd,curl,mbstring,xml,zip,ldap" \ +PHP_FPM="YES" \ +PHP_APACHE="YES" \ +setup_php +``` + +**Environment Variables:** +| Variable | Default | Description | +|----------|---------|-------------| +| `PHP_VERSION` | `8.3` | PHP version to install | +| `PHP_MODULE` | `""` | Comma-separated list of modules | +| `PHP_FPM` | `NO` | Install PHP-FPM | +| `PHP_APACHE` | `NO` | Install Apache module | + +### `setup_composer` + +Install PHP Composer package manager. + +```bash +setup_php +setup_composer + +# Use in script +$STD composer install --no-dev +``` + +### `setup_java` + +Install Java (OpenJDK). + +```bash +# Default (Java 21) +setup_java + +# Specific version +JAVA_VERSION="17" setup_java +JAVA_VERSION="21" setup_java +``` + +--- + +## Database Setup + +### `setup_mariadb` + +Install MariaDB server. + +```bash +setup_mariadb +``` + +### `setup_mariadb_db` + +Create a MariaDB database and user. Sets `$MARIADB_DB_PASS` with the generated password. + +```bash +setup_mariadb +MARIADB_DB_NAME="myapp_db" MARIADB_DB_USER="myapp_user" setup_mariadb_db + +# After calling, these variables are available: +# $MARIADB_DB_NAME - Database name +# $MARIADB_DB_USER - Database user +# $MARIADB_DB_PASS - Generated password (saved to ~/[appname].creds) +``` + +### `setup_mysql` + +Install MySQL server. + +```bash +setup_mysql +``` + +### `setup_postgresql` + +Install PostgreSQL server. + +```bash +# Default (PostgreSQL 17) +setup_postgresql + +# Specific version +PG_VERSION="16" setup_postgresql +PG_VERSION="17" setup_postgresql +``` + +### `setup_postgresql_db` + +Create a PostgreSQL database and user. Sets `$PG_DB_PASS` with the generated password. + +```bash +PG_VERSION="17" setup_postgresql +PG_DB_NAME="myapp_db" PG_DB_USER="myapp_user" setup_postgresql_db + +# After calling, these variables are available: +# $PG_DB_NAME - Database name +# $PG_DB_USER - Database user +# $PG_DB_PASS - Generated password (saved to ~/[appname].creds) +``` + +### `setup_mongodb` + +Install MongoDB server. + +```bash +setup_mongodb +``` + +### `setup_clickhouse` + +Install ClickHouse analytics database. + +```bash +setup_clickhouse +``` + +--- + +## GitHub Release Helpers + +> **Note**: `fetch_and_deploy_gh_release` is the **preferred method** for downloading GitHub releases. It handles version tracking automatically. Only use `get_latest_github_release` if you need the version number separately. + +### `fetch_and_deploy_gh_release` + +**Primary method** for downloading and extracting GitHub releases. Handles version tracking automatically. + +```bash +# Basic usage - downloads tarball to /opt/appname +fetch_and_deploy_gh_release "appname" "owner/repo" + +# With explicit parameters +fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" "latest" "/opt/appname" + +# Pre-built release with specific asset pattern +fetch_and_deploy_gh_release "koel" "koel/koel" "prebuild" "latest" "/opt/koel" "koel-*.tar.gz" + +# Clean install (removes old directory first) - used in update_script +CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" "latest" "/opt/appname" +``` + +**Parameters:** +| Parameter | Default | Description | +|-----------|---------|-------------| +| `name` | required | App name (for version tracking) | +| `repo` | required | GitHub repo (`owner/repo`) | +| `type` | `tarball` | Release type: `tarball`, `zipball`, `prebuild`, `binary` | +| `version` | `latest` | Version tag or `latest` | +| `dest` | `/opt/[name]` | Destination directory | +| `asset_pattern` | `""` | For `prebuild`: glob pattern to match asset (e.g. `app-*.tar.gz`) | + +**Environment Variables:** +| Variable | Description | +|----------|-------------| +| `CLEAN_INSTALL=1` | Remove destination directory before extracting (for updates) | + +### `check_for_gh_release` + +Check if a newer version is available. Returns 0 if update needed, 1 if already at latest. **Use in `update_script()` function.** + +```bash +# In update_script() function in ct/appname.sh +if check_for_gh_release "appname" "owner/repo"; then + msg_info "Updating..." + # Stop services, backup, update, restore, start + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo" + msg_ok "Updated successfully" +fi +``` + +### `get_latest_github_release` + +Get the latest release version from a GitHub repository. **Only use if you need the version number separately** (e.g., for manual download or display). + +```bash +RELEASE=$(get_latest_github_release "owner/repo") +echo "Latest version: $RELEASE" +``` + +# Examples + +fetch_and_deploy_gh_release "bookstack" "BookStackApp/BookStack" +fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" "latest" "/opt/myapp" + +```` + +**Parameters:** +| Parameter | Default | Description | +|-----------|---------|-------------| +| `name` | required | App name (for version tracking) | +| `repo` | required | GitHub repo (`owner/repo`) | +| `type` | `tarball` | Release type: `tarball`, `zipball`, `binary` | +| `version` | `latest` | Version tag or `latest` | +| `dest` | `/opt/[name]` | Destination directory | + +--- + +## Tools & Utilities + +### `setup_yq` + +Install yq YAML processor. + +```bash +setup_yq + +# Use in script +yq '.server.port = 8080' -i config.yaml +```` + +### `setup_ffmpeg` + +Install FFmpeg with common codecs. + +```bash +setup_ffmpeg +``` + +### `setup_hwaccel` + +Setup GPU hardware acceleration (Intel/AMD/NVIDIA). + +```bash +# Only runs if GPU passthrough is detected (/dev/dri, /dev/nvidia0, /dev/kfd) +setup_hwaccel +``` + +### `setup_imagemagick` + +Install ImageMagick 7 from source. + +```bash +setup_imagemagick +``` + +### `setup_docker` + +Install Docker Engine. + +```bash +setup_docker +``` + +### `setup_adminer` + +Install Adminer for database management. + +```bash +setup_mariadb +setup_adminer + +# Access at http://IP/adminer +``` + +--- + +## SSL/TLS + +### `create_self_signed_cert` + +Create a self-signed SSL certificate. + +```bash +create_self_signed_cert + +# Creates files at: +# /etc/ssl/[appname]/[appname].key +# /etc/ssl/[appname]/[appname].crt +``` + +--- + +## Utility Functions + +### `import_local_ip` + +Set the `$LOCAL_IP` variable with the container's IP address. + +```bash +import_local_ip +echo "Container IP: $LOCAL_IP" + +# Use in config files +sed -i "s/localhost/$LOCAL_IP/g" /opt/myapp/config.yaml +``` + +### `ensure_dependencies` + +Ensure packages are installed (installs if missing). + +```bash +ensure_dependencies "jq" "unzip" "curl" +``` + +### `msg_info` / `msg_ok` / `msg_error` / `msg_warn` + +Display formatted messages. + +```bash +msg_info "Installing application..." +# ... do work ... +msg_ok "Installation complete" + +msg_warn "Optional feature not available" +msg_error "Installation failed" +``` + +--- + +## Package Management + +### `cleanup_lxc` + +Final cleanup function - call at end of install script. + +```bash +# At the end of your install script +motd_ssh +customize +cleanup_lxc # Handles autoremove, autoclean, cache cleanup +``` + +### `install_packages_with_retry` + +Install packages with automatic retry on failure. + +```bash +install_packages_with_retry "package1" "package2" "package3" +``` + +### `prepare_repository_setup` + +Prepare system for adding new repositories (cleanup old repos, keyrings). + +```bash +prepare_repository_setup "mariadb" "mysql" +``` + +--- + +## Complete Examples + +### Example 1: Node.js App with PostgreSQL (install script) + +```bash +#!/usr/bin/env bash + +# Copyright (c) 2021-2025 community-scripts ORG +# Author: YourUsername +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/example/myapp + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt install -y nginx +msg_ok "Installed Dependencies" + +# Setup runtimes and databases FIRST +NODE_VERSION="22" setup_nodejs +PG_VERSION="17" setup_postgresql +PG_DB_NAME="myapp" PG_DB_USER="myapp" setup_postgresql_db +import_local_ip + +# Download app using fetch_and_deploy (handles version tracking) +fetch_and_deploy_gh_release "myapp" "example/myapp" "tarball" "latest" "/opt/myapp" + +msg_info "Setting up MyApp" +cd /opt/myapp +$STD npm ci --production +msg_ok "Setup MyApp" + +msg_info "Configuring MyApp" +cat </opt/myapp/.env +DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost/${PG_DB_NAME} +HOST=${LOCAL_IP} +PORT=3000 +EOF +msg_ok "Configured MyApp" + +msg_info "Creating Service" +cat </etc/systemd/system/myapp.service +[Unit] +Description=MyApp +After=network.target postgresql.service + +[Service] +Type=simple +WorkingDirectory=/opt/myapp +ExecStart=/usr/bin/node /opt/myapp/server.js +Restart=on-failure + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now myapp +msg_ok "Created Service" + +motd_ssh +customize +cleanup_lxc +``` + +### Example 2: Matching Container Script (ct script) + +```bash +#!/usr/bin/env bash +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +# Copyright (c) 2021-2025 community-scripts ORG +# Author: YourUsername +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/example/myapp + +APP="MyApp" +var_tags="${var_tags:-webapp}" +var_cpu="${var_cpu:-2}" +var_ram="${var_ram:-2048}" +var_disk="${var_disk:-6}" +var_os="${var_os:-debian}" +var_version="${var_version:-12}" +var_unprivileged="${var_unprivileged:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + + if [[ ! -d /opt/myapp ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + # check_for_gh_release returns true if update available + if check_for_gh_release "myapp" "example/myapp"; then + msg_info "Stopping Service" + systemctl stop myapp + msg_ok "Stopped Service" + + msg_info "Creating Backup" + cp /opt/myapp/.env /tmp/myapp_env.bak + msg_ok "Created Backup" + + # CLEAN_INSTALL=1 removes old dir before extracting + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "myapp" "example/myapp" "tarball" "latest" "/opt/myapp" + + msg_info "Restoring Config & Rebuilding" + cp /tmp/myapp_env.bak /opt/myapp/.env + rm /tmp/myapp_env.bak + cd /opt/myapp + $STD npm ci --production + msg_ok "Restored Config & Rebuilt" + + msg_info "Starting Service" + systemctl start myapp + msg_ok "Started Service" + + msg_ok "Updated Successfully" + fi + exit +} + +start +build_container +description + +msg_ok "Completed Successfully!\n" +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" +echo -e "${INFO}${YW} Access it using the following URL:${CL}" +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}" +``` + +### Example 3: PHP App with MariaDB (install script) + +```bash +#!/usr/bin/env bash + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt install -y nginx +msg_ok "Installed Dependencies" + +# PHP with FPM and common modules +PHP_VERSION="8.4" PHP_FPM="YES" PHP_MODULE="bcmath,curl,gd,intl,mbstring,mysql,xml,zip" setup_php +setup_composer +setup_mariadb +MARIADB_DB_NAME="myapp" MARIADB_DB_USER="myapp" setup_mariadb_db +import_local_ip + +# Download pre-built release (with asset pattern) +fetch_and_deploy_gh_release "myapp" "example/myapp" "prebuild" "latest" "/opt/myapp" "myapp-*.tar.gz" + +msg_info "Configuring MyApp" +cd /opt/myapp +cp .env.example .env +sed -i "s|APP_URL=.*|APP_URL=http://${LOCAL_IP}|" .env +sed -i "s|DB_DATABASE=.*|DB_DATABASE=${MARIADB_DB_NAME}|" .env +sed -i "s|DB_USERNAME=.*|DB_USERNAME=${MARIADB_DB_USER}|" .env +sed -i "s|DB_PASSWORD=.*|DB_PASSWORD=${MARIADB_DB_PASS}|" .env +$STD composer install --no-dev --no-interaction +$STD php artisan key:generate --force +$STD php artisan migrate --force +chown -R www-data:www-data /opt/myapp +msg_ok "Configured MyApp" + +# ... nginx config, service creation ... + +motd_ssh +customize +cleanup_lxc +``` diff --git a/docs/contribution/README.md b/docs/contribution/README.md index 7737b6418..fa65ca12d 100644 --- a/docs/contribution/README.md +++ b/docs/contribution/README.md @@ -65,6 +65,7 @@ bash docs/contribution/setup-fork.sh ``` This will: + - Auto-detect your GitHub username - Update all documentation links to point to your fork - Create `.git-setup-info` with recommended git workflows @@ -97,6 +98,8 @@ All scripts and configurations must follow our coding standards to ensure consis - **[CONTRIBUTING.md](CONTRIBUTING.md)** - Essential coding standards and best practices - **[CODE_AUDIT.md](CODE_AUDIT.md)** - Code review checklist and audit procedures +- **[GUIDE.md](GUIDE.md)** - Comprehensive contribution guide +- **[HELPER_FUNCTIONS.md](HELPER_FUNCTIONS.md)** - Reference for all tools.func helper functions - **Container Scripts** - `/ct/` templates and guidelines - **Install Scripts** - `/install/` templates and guidelines - **JSON Configurations** - `/json/` structure and format @@ -121,6 +124,7 @@ Before submitting a pull request, ensure your code passes our audit: **See**: [CODE_AUDIT.md](CODE_AUDIT.md) for complete audit checklist Key points: + - Code consistency with existing scripts - Proper error handling - Correct variable naming @@ -145,6 +149,7 @@ Key points: ### Community Guides See [USER_SUBMITTED_GUIDES.md](USER_SUBMITTED_GUIDES.md) for excellent community-written guides: + - Home Assistant installation and configuration - Frigate setup on Proxmox - Docker and Portainer installation @@ -156,16 +161,24 @@ See [USER_SUBMITTED_GUIDES.md](USER_SUBMITTED_GUIDES.md) for excellent community Use these templates when creating new scripts: ```bash -# Container script -cp ct/example.sh ct/my-app.sh +# Container script template +cp docs/contribution/templates_ct/AppName.sh ct/my-app.sh -# Installation script -cp install/example-install.sh install/my-app-install.sh +# Installation script template +cp docs/contribution/templates_install/AppName-install.sh install/my-app-install.sh -# JSON configuration (if needed) -cp json/example.json json/my-app.json +# JSON configuration template +cp docs/contribution/templates_json/AppName.json frontend/public/json/my-app.json ``` +**Template Features:** + +- Updated to match current codebase patterns +- Includes all available helper functions from `tools.func` +- Examples for Node.js, Python, PHP, Go applications +- Database setup examples (MariaDB, PostgreSQL) +- Proper service creation and cleanup + --- ## 🔄 Git Workflow @@ -202,18 +215,21 @@ git push origin feature/my-feature ### Before Submitting PR 1. **Sync with upstream** + ```bash git fetch upstream git rebase upstream/main ``` 2. **Test your changes** + ```bash bash ct/my-app.sh # Follow prompts and test the container ``` 3. **Check code standards** + - [ ] Follows template structure - [ ] Proper error handling - [ ] Documentation updated (if needed) diff --git a/docs/contribution/templates_ct/AppName.sh b/docs/contribution/templates_ct/AppName.sh index 14c0244eb..aea058660 100644 --- a/docs/contribution/templates_ct/AppName.sh +++ b/docs/contribution/templates_ct/AppName.sh @@ -1,27 +1,31 @@ #!/usr/bin/env bash -source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG -# Author: [YourUserName] +# Author: [YourGitHubUsername] # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE -# Source: [SOURCE_URL] +# Source: [SOURCE_URL e.g. https://github.com/example/app] # App Default Values -APP="[APP_NAME]" -# Name of the app (e.g. Google, Adventurelog, Apache-Guacamole" -var_tags="[TAGS]" -# Tags for Proxmox VE, maximum 2 pcs., no spaces allowed, separated by a semicolon ; (e.g. database | adblock;dhcp) -var_cpu="[CPU]" -# Number of cores (1-X) (e.g. 4) - default are 2 -var_ram="[RAM]" -# Amount of used RAM in MB (e.g. 2048 or 4096) -var_disk="[DISK]" -# Amount of used disk space in GB (e.g. 4 or 10) -var_os="[OS]" -# Default OS (e.g. debian, ubuntu, alpine) -var_version="[VERSION]" -# Default OS version (e.g. 12 for debian, 24.04 for ubuntu, 3.20 for alpine) -var_unprivileged="[UNPRIVILEGED]" -# 1 = unprivileged container, 0 = privileged container +APP="[AppName]" +var_tags="${var_tags:-[category]}" +var_cpu="${var_cpu:-2}" +var_ram="${var_ram:-2048}" +var_disk="${var_disk:-4}" +var_os="${var_os:-debian}" +var_version="${var_version:-12}" +var_unprivileged="${var_unprivileged:-1}" + +# ============================================================================= +# CONFIGURATION GUIDE +# ============================================================================= +# APP - Display name, title case (e.g. "Koel", "Wallabag", "Actual Budget") +# var_tags - Max 2 tags, semicolon separated (e.g. "music;streaming", "finance") +# var_cpu - CPU cores: 1-4 typical +# var_ram - RAM in MB: 512, 1024, 2048, 4096 typical +# var_disk - Disk in GB: 4, 6, 8, 10, 20 typical +# var_os - OS: debian, ubuntu, alpine +# var_version - OS version: 12/13 (debian), 22.04/24.04 (ubuntu), 3.20/3.21 (alpine) +# var_unprivileged - 1 = unprivileged (secure, default), 0 = privileged (for docker etc.) header_info "$APP" variables @@ -29,51 +33,55 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources + header_info + check_container_storage + check_container_resources - # Check if installation is present | -f for file, -d for folder - if [[ ! -f [INSTALLATION_CHECK_PATH] ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - - # Crawling the new version and checking whether an update is required - RELEASE=$(curl -fsSL [RELEASE_URL] | [PARSE_RELEASE_COMMAND]) - if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then - # Stopping Services - msg_info "Stopping $APP" - systemctl stop [SERVICE_NAME] - msg_ok "Stopped $APP" - - # Creating Backup - msg_info "Creating Backup" - tar -czf "/opt/${APP}_backup_$(date +%F).tar.gz" [IMPORTANT_PATHS] - msg_ok "Backup Created" - - # Execute Update - msg_info "Updating $APP to v${RELEASE}" - [UPDATE_COMMANDS] - msg_ok "Updated $APP to v${RELEASE}" - - # Starting Services - msg_info "Starting $APP" - systemctl start [SERVICE_NAME] - msg_ok "Started $APP" - - # Cleaning up - msg_info "Cleaning Up" - rm -rf [TEMP_FILES] - msg_ok "Cleanup Completed" - - # Last Action - echo "${RELEASE}" >/opt/${APP}_version.txt - msg_ok "Update Successful" - else - msg_ok "No update required. ${APP} is already at v${RELEASE}" - fi + # Check if installation exists + if [[ ! -d /opt/[appname] ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + + # check_for_gh_release returns 0 (true) if update available, 1 (false) if not + if check_for_gh_release "[appname]" "[owner/repo]"; then + msg_info "Stopping Services" + systemctl stop [appname] + msg_ok "Stopped Services" + + # Optional: Backup important data before update + msg_info "Creating Backup" + mkdir -p /tmp/[appname]_backup + cp /opt/[appname]/.env /tmp/[appname]_backup/ 2>/dev/null || true + cp -r /opt/[appname]/data /tmp/[appname]_backup/ 2>/dev/null || true + msg_ok "Created Backup" + + # CLEAN_INSTALL=1 removes old directory before extracting new version + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "[appname]" "[owner/repo]" "tarball" "latest" "/opt/[appname]" + + # Restore configuration and data + msg_info "Restoring Data" + cp /tmp/[appname]_backup/.env /opt/[appname]/ 2>/dev/null || true + cp -r /tmp/[appname]_backup/data/* /opt/[appname]/data/ 2>/dev/null || true + rm -rf /tmp/[appname]_backup + msg_ok "Restored Data" + + # Optional: Run any post-update commands + msg_info "Running Post-Update Tasks" + cd /opt/[appname] + # Examples: + # $STD npm ci --production + # $STD php artisan migrate --force + # $STD composer install --no-dev + msg_ok "Ran Post-Update Tasks" + + msg_info "Starting Services" + systemctl start [appname] + msg_ok "Started Services" + + msg_ok "Updated Successfully" + fi + exit } start diff --git a/docs/contribution/templates_install/AppName-install.sh b/docs/contribution/templates_install/AppName-install.sh index 27e6b8f4e..ac861c2ec 100644 --- a/docs/contribution/templates_install/AppName-install.sh +++ b/docs/contribution/templates_install/AppName-install.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash # Copyright (c) 2021-2025 community-scripts ORG -# Author: [YourUserName] +# Author: [YourGitHubUsername] # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE -# Source: [SOURCE_URL] +# Source: [SOURCE_URL e.g. https://github.com/example/app] -# Import Functions und Setup +# Import Functions and Setup source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" color verb_ip6 @@ -14,70 +14,177 @@ setting_up_container network_check update_os -# Installing Dependencies with the 3 core dependencies (curl;sudo;mc) +# ============================================================================= +# DEPENDENCIES +# ============================================================================= +# Only install what's actually needed - curl/sudo/mc are already in the base image + msg_info "Installing Dependencies" -$STD apt-get install -y \ - curl \ - sudo \ - mc \ - [PACKAGE_1] \ - [PACKAGE_2] \ - [PACKAGE_3] +$STD apt install -y \ + nginx \ + build-essential msg_ok "Installed Dependencies" -# Template: MySQL Database -msg_info "Setting up Database" -DB_NAME=[DB_NAME] -DB_USER=[DB_USER] -DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13) -$STD mysql -u root -e "CREATE DATABASE $DB_NAME;" -$STD mysql -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED WITH mysql_native_password AS PASSWORD('$DB_PASS');" -$STD mysql -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;" -{ - echo "${APPLICATION} Credentials" - echo "Database User: $DB_USER" - echo "Database Password: $DB_PASS" - echo "Database Name: $DB_NAME" -} >>~/$APP_NAME.creds -msg_ok "Set up Database" - -# Temp - -# Setup App -msg_info "Setup ${APPLICATION}" -RELEASE=$(curl -s https://api.github.com/repos/[REPO]/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') -curl -fsSL "https://github.com/[REPO]/archive/refs/tags/${RELEASE}.zip" -unzip -q ${RELEASE}.zip -mv ${APPLICATION}-${RELEASE}/ /opt/${APPLICATION} +# ============================================================================= +# HELPER FUNCTIONS FROM tools.func +# ============================================================================= +# These functions are available via $FUNCTIONS_FILE_PATH (tools.func) +# Call them with optional environment variables for configuration # +# --- Runtime & Language Setup --- +# NODE_VERSION="22" setup_nodejs # Install Node.js (22, 24) +# NODE_VERSION="24" NODE_MODULE="pnpm" setup_nodejs # With pnpm +# PYTHON_VERSION="3.13" setup_uv # Python with uv package manager +# setup_go # Install Go (latest) +# setup_rust # Install Rust via rustup +# setup_ruby # Install Ruby +# PHP_VERSION="8.4" PHP_FPM="YES" PHP_MODULE="mysqli,gd" setup_php +# PHP_VERSION="8.3" PHP_FPM="YES" PHP_APACHE="YES" PHP_MODULE="bcmath,curl,gd,intl,mbstring,mysql,xml,zip" setup_php +# setup_composer # Install PHP Composer +# JAVA_VERSION="21" setup_java # Install Java (17, 21) # +# --- Database Setup --- +# setup_mariadb # Install MariaDB server +# MARIADB_DB_NAME="mydb" MARIADB_DB_USER="myuser" setup_mariadb_db +# setup_mysql # Install MySQL server +# PG_VERSION="17" setup_postgresql # Install PostgreSQL (16, 17) +# PG_VERSION="17" PG_MODULES="postgis" setup_postgresql # With extensions +# PG_DB_NAME="mydb" PG_DB_USER="myuser" setup_postgresql_db +# setup_mongodb # Install MongoDB # -echo "${RELEASE}" >/opt/${APPLICATION}_version.txt -msg_ok "Setup ${APPLICATION}" +# --- GitHub Release (PREFERRED METHOD) --- +# fetch_and_deploy_gh_release "appname" "owner/repo" # Downloads, extracts, tracks version +# fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" "latest" "/opt/appname" +# fetch_and_deploy_gh_release "appname" "owner/repo" "prebuild" "latest" "/opt/appname" "app-*.tar.gz" +# +# --- Tools & Utilities --- +# import_local_ip # Sets $LOCAL_IP variable (call early!) +# setup_ffmpeg # Install FFmpeg with codecs +# setup_hwaccel # Setup GPU hardware acceleration +# setup_imagemagick # Install ImageMagick 7 +# setup_docker # Install Docker Engine +# setup_adminer # Install Adminer for DB management +# create_self_signed_cert # Creates cert in /etc/ssl/[appname]/ + +# ============================================================================= +# EXAMPLE 1: Node.js Application with PostgreSQL +# ============================================================================= +# NODE_VERSION="22" setup_nodejs +# PG_VERSION="17" setup_postgresql +# PG_DB_NAME="myapp" PG_DB_USER="myapp" setup_postgresql_db +# import_local_ip +# fetch_and_deploy_gh_release "myapp" "owner/myapp" "tarball" "latest" "/opt/myapp" +# +# msg_info "Configuring MyApp" +# cd /opt/myapp +# $STD npm ci +# cat </opt/myapp/.env +# DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost/${PG_DB_NAME} +# HOST=${LOCAL_IP} +# PORT=3000 +# EOF +# msg_ok "Configured MyApp" + +# ============================================================================= +# EXAMPLE 2: Python Application with uv +# ============================================================================= +# PYTHON_VERSION="3.13" setup_uv +# import_local_ip +# fetch_and_deploy_gh_release "myapp" "owner/myapp" "tarball" "latest" "/opt/myapp" +# +# msg_info "Setting up MyApp" +# cd /opt/myapp +# $STD uv sync +# cat </opt/myapp/.env +# HOST=${LOCAL_IP} +# PORT=8000 +# EOF +# msg_ok "Setup MyApp" + +# ============================================================================= +# EXAMPLE 3: PHP Application with MariaDB + Nginx +# ============================================================================= +# PHP_VERSION="8.4" PHP_FPM="YES" PHP_MODULE="bcmath,curl,gd,intl,mbstring,mysql,xml,zip" setup_php +# setup_composer +# setup_mariadb +# MARIADB_DB_NAME="myapp" MARIADB_DB_USER="myapp" setup_mariadb_db +# import_local_ip +# fetch_and_deploy_gh_release "myapp" "owner/myapp" "prebuild" "latest" "/opt/myapp" "myapp-*.tar.gz" +# +# msg_info "Configuring MyApp" +# cd /opt/myapp +# cp .env.example .env +# sed -i "s|APP_URL=.*|APP_URL=http://${LOCAL_IP}|" .env +# sed -i "s|DB_DATABASE=.*|DB_DATABASE=${MARIADB_DB_NAME}|" .env +# sed -i "s|DB_USERNAME=.*|DB_USERNAME=${MARIADB_DB_USER}|" .env +# sed -i "s|DB_PASSWORD=.*|DB_PASSWORD=${MARIADB_DB_PASS}|" .env +# $STD composer install --no-dev --no-interaction +# chown -R www-data:www-data /opt/myapp +# msg_ok "Configured MyApp" + +# ============================================================================= +# YOUR APPLICATION INSTALLATION +# ============================================================================= +# 1. Setup runtimes and databases FIRST +# 2. Call import_local_ip if you need the container IP +# 3. Use fetch_and_deploy_gh_release to download the app (handles version tracking) +# 4. Configure the application +# 5. Create systemd service +# 6. Finalize with motd_ssh, customize, cleanup_lxc + +# --- Setup runtimes/databases --- +NODE_VERSION="22" setup_nodejs +import_local_ip + +# --- Download and install app --- +fetch_and_deploy_gh_release "[appname]" "[owner/repo]" "tarball" "latest" "/opt/[appname]" + +msg_info "Setting up [AppName]" +cd /opt/[appname] +$STD npm ci +msg_ok "Setup [AppName]" + +# ============================================================================= +# CONFIGURATION +# ============================================================================= + +msg_info "Configuring [AppName]" +cat </opt/[appname]/.env +HOST=${LOCAL_IP} +PORT=8080 +EOF +msg_ok "Configured [AppName]" + +# ============================================================================= +# SERVICE CREATION +# ============================================================================= -# Creating Service (if needed) msg_info "Creating Service" -cat </etc/systemd/system/${APPLICATION}.service +cat </etc/systemd/system/[appname].service [Unit] -Description=${APPLICATION} Service +Description=[AppName] Service After=network.target [Service] -ExecStart=[START_COMMAND] -Restart=always +Type=simple +User=root +WorkingDirectory=/opt/[appname] +ExecStart=/usr/bin/node /opt/[appname]/server.js +Restart=on-failure +RestartSec=5 [Install] WantedBy=multi-user.target EOF -systemctl enable -q --now ${APPLICATION}.service +systemctl enable -q --now [appname] msg_ok "Created Service" +# ============================================================================= +# CLEANUP & FINALIZATION +# ============================================================================= + motd_ssh customize -# Cleanup -msg_info "Cleaning up" -rm -f ${RELEASE}.zip -$STD apt-get -y autoremove -$STD apt-get -y autoclean -msg_ok "Cleaned" +# cleanup_lxc handles: apt autoremove, autoclean, temp files, bash history +cleanup_lxc diff --git a/docs/contribution/templates_json/AppName.json b/docs/contribution/templates_json/AppName.json index 746ebd916..8d621171c 100644 --- a/docs/contribution/templates_json/AppName.json +++ b/docs/contribution/templates_json/AppName.json @@ -1,34 +1,34 @@ { - "name": "AppName", - "slug": "appname", - "categories": [ - 0 - ], - "date_created": "DATE CREATED", - "type": "ct", - "updateable": true, - "privileged": false, - "interface_port": DEFAULT-PORT, - "documentation": null, - "website": "LINK TO WEBSITE", - "logo": "LINK TO LOGO", - "description": "Description of the app", - "install_methods": [ - { - "type": "default", - "script": "ct/AppName.sh", - "resources": { - "cpu": 2, - "ram": 2048, - "hdd": 4, - "os": "debian", - "version": "12" - } - } - ], - "default_credentials": { - "username": null, - "password": null - }, - "notes": [] -} \ No newline at end of file + "name": "AppName", + "slug": "appname", + "categories": [ + 0 + ], + "date_created": "DATE CREATED", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": "DEFAULT-PORT", + "documentation": null, + "website": "LINK TO WEBSITE", + "logo": "LINK TO LOGO", + "description": "Description of the app", + "install_methods": [ + { + "type": "default", + "script": "ct/AppName.sh", + "resources": { + "cpu": 2, + "ram": 2048, + "hdd": 4, + "os": "debian", + "version": "12" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [] +}