diff --git a/AppName‐install.sh-Scripts.md b/AppName‐install.sh-Scripts.md deleted file mode 100644 index 241cd99..0000000 --- a/AppName‐install.sh-Scripts.md +++ /dev/null @@ -1,353 +0,0 @@ - -# **AppName-install.sh Scripts** - - `AppName-install.sh` scripts found in the `/install` directory. These scripts are responsible for the installation of the application. For this guide we take `/install/snipeit-install.sh` as example. - -## Table of Contents - -- [**AppName-install.sh Scripts**](#appname-installsh-scripts) - - [Table of Contents](#table-of-contents) - - [1. **File header**](#1-file-header) - - [1.1 **Shebang**](#11-shebang) - - [1.2 **Comments**](#12-comments) - - [1.3 **Variables and function import**](#13-variables-and-function-import) - - [2. **Variable naming and management**](#2-variable-naming-and-management) - - [2.1 **Naming conventions**](#21-naming-conventions) - - [3. **Dependencies**](#3-dependencies) - - [3.1 **Install all at once**](#31-install-all-at-once) - - [3.2 **Collapse dependencies**](#32-collapse-dependencies) - - [4. **Paths to application files**](#4-paths-to-application-files) - - [5. **Version management**](#5-version-management) - - [5.1 **Install the latest release**](#51-install-the-latest-release) - - [5.2 **Save the version for update checks**](#52-save-the-version-for-update-checks) - - [6. **Input and output management**](#6-input-and-output-management) - - [6.1 **User feedback**](#61-user-feedback) - - [6.2 **Verbosity**](#62-verbosity) - - [7. **String/File Manipulation**](#7-stringfile-manipulation) - - [7.1 **File Manipulation**](#71-file-manipulation) - - [8. **Security practices**](#8-security-practices) - - [8.1 **Password generation**](#81-password-generation) - - [8.2 **File permissions**](#82-file-permissions) - - [9. **Service Configuration**](#9-service-configuration) - - [9.1 **Configuration files**](#91-configuration-files) - - [9.2 **Credential management**](#92-credential-management) - - [9.3 **Enviroment files**](#93-enviroment-files) - - [9.4 **Services**](#94-services) - - [10. **Cleanup**](#10-cleanup) - - [10.1 **Remove temporary files**](#101-remove-temporary-files) - - [10.2 **Autoremove and autoclean**](#102-autoremove-and-autoclean) - - [11. **Best Practices Checklist**](#11-best-practices-checklist) - - [Example: High-Level Script Flow](#example-high-level-script-flow) - -## 1. **File header** - -### 1.1 **Shebang** - -- Use `#!/usr/bin/env bash` as the shebang. - -```bash -#!/usr/bin/env bash -``` - -### 1.2 **Comments** - -- Add clear comments for script metadata, including author, copyright, and license information. -- Use meaningful inline comments to explain complex commands or logic. - -Example: - -```bash -# Copyright (c) 2021-2025 community-scripts ORG -# Author: [YourUserName] -# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE -# Source: [SOURCE_URL] -``` - -> [!NOTE]: -> -> - Add your username -> - When updating/reworking scripts, add "| Co-Author [YourUserName]" - -### 1.3 **Variables and function import** - -- This sections adds the support for all needed functions and variables. - -```bash -source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" -color -verb_ip6 -catch_errors -setting_up_container -network_check -update_os -``` - ---- - -## 2. **Variable naming and management** - -### 2.1 **Naming conventions** - -- Use uppercase names for constants and environment variables. -- Use lowercase names for local script variables. - -Example: - -```bash -DB_NAME=snipeit_db # Environment-like variable (constant) -db_user="snipeit" # Local variable -``` - ---- - -## 3. **Dependencies** - -### 3.1 **Install all at once** - -- Install all dependencies with a single command if possible - -Example: - -```bash -$STD apt-get install -y \ - curl \ - composer \ - git \ - sudo \ - mc \ - nginx -``` - -### 3.2 **Collapse dependencies** - -Collapse dependencies to keep the code readable. - -Example: -Use - -```bash -php8.2-{bcmath,common,ctype} -``` - -instead of - -```bash -php8.2-bcmath php8.2-common php8.2-ctype -``` - ---- - -## 4. **Paths to application files** - -If possible install the app and all necessary files in `/opt/` - ---- - -## 5. **Version management** - -### 5.1 **Install the latest release** - -- Always try and install the latest release -- Do not hardcode any version if not absolutely necessary - -Example for a git release: - -```bash -RELEASE=$(curl -fsSL https://api.github.com/repos/snipe/snipe-it/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') -wget -q "https://github.com/snipe/snipe-it/archive/refs/tags/v${RELEASE}.zip" -``` - -### 5.2 **Save the version for update checks** - -- Write the installed version into a file. -- This is used for the update function in **AppName.sh** to check for if a Update is needed. - -Example: - -```bash -echo "${RELEASE}" >"/opt/AppName_version.txt" -``` - ---- - -## 6. **Input and output management** - -### 6.1 **User feedback** - -- Use standard functions like `msg_info`, `msg_ok` or `msg_error` to print status messages. -- Each `msg_info` must be followed with a `msg_ok` before any other output is made. -- Display meaningful progress messages at key stages. - -Example: - -```bash -msg_info "Installing Dependencies" -$STD apt-get install -y ... -msg_ok "Installed Dependencies" -``` - -### 6.2 **Verbosity** - -- Use the appropiate flag (**-q** in the examples) for a command to suppres its output -Example: - -```bash -wget -q -unzip -q -``` - -- If a command dose not come with such a functionality use `$STD` (a custom standard redirection variable) for managing output verbosity. - -Example: - -```bash -$STD apt-get install -y nginx -``` - ---- - -## 7. **String/File Manipulation** - -### 7.1 **File Manipulation** - -- Use `sed` to replace placeholder values in configuration files. - -Example: - -```bash -sed -i -e "s|^DB_DATABASE=.*|DB_DATABASE=$DB_NAME|" \ - -e "s|^DB_USERNAME=.*|DB_USERNAME=$DB_USER|" \ - -e "s|^DB_PASSWORD=.*|DB_PASSWORD=$DB_PASS|" .env -``` - ---- - -## 8. **Security practices** - -### 8.1 **Password generation** - -- Use `openssl` to generate random passwords. -- Use only alphanumeric values to not introduce unknown behaviour. - -Example: - -```bash -DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13) -``` - -### 8.2 **File permissions** - -Explicitly set secure ownership and permissions for sensitive files. - -Example: - -```bash -chown -R www-data: /opt/snipe-it -chmod -R 755 /opt/snipe-it -``` - ---- - -## 9. **Service Configuration** - -### 9.1 **Configuration files** - -Use `cat </etc/nginx/conf.d/snipeit.conf -server { - listen 80; - root /opt/snipe-it/public; - index index.php; -} -EOF -``` - -### 9.2 **Credential management** - -Store the generated credentials in a file. - -Example: - -```bash -USERNAME=username -PASSWORD=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13) -{ - echo "Application-Credentials" - echo "Username: $USERNAME" - echo "Password: $PASSWORD" -} >> ~/application.creds -``` - -### 9.3 **Enviroment files** - -Use `cat </path/to/.env -VARIABLE="value" -PORT=3000 -DB_NAME="${DB_NAME}" -EOF -``` - -### 9.4 **Services** - -Enable affected services after configuration changes and start them right away. - -Example: - -```bash -systemctl enable -q --now nginx -``` - ---- - -## 10. **Cleanup** - -### 10.1 **Remove temporary files** - -Remove temporary files and downloads after use. - -Example: - -```bash -rm -rf /opt/v${RELEASE}.zip -``` - -### 10.2 **Autoremove and autoclean** - -Remove unused dependencies to reduce disk space usage. - -Example: - -```bash -apt-get -y autoremove -apt-get -y autoclean -``` - ---- - -## 11. **Best Practices Checklist** - -- [ ] Shebang is correctly set (`#!/usr/bin/env bash`). -- [ ] Metadata (author, license) is included at the top. -- [ ] Variables follow naming conventions. -- [ ] Sensitive values are dynamically generated. -- [ ] Files and services have proper permissions. -- [ ] Script cleans up temporary files. - ---- - -### Example: High-Level Script Flow - -1. Dependencies installation -2. Database setup -3. Download and configure application -4. Service configuration -5. Final cleanup diff --git a/[Script]:-AppName‐install.sh.md b/[Script]:-AppName‐install.sh.md new file mode 100644 index 0000000..c012aba --- /dev/null +++ b/[Script]:-AppName‐install.sh.md @@ -0,0 +1,1121 @@ +# 🛠️ **Application Installation Scripts (install/AppName-install.sh)** + +**Modern Guide to Writing In-Container Installation Scripts** + +> **Updated**: December 2025 +> **Context**: Integrated with tools.func, error_handler.func, and install.func +> **Examples Used**: `/install/pihole-install.sh`, `/install/mealie-install.sh` + +--- + +## 📋 Table of Contents + +- [Overview](#overview) +- [Execution Context](#execution-context) +- [File Structure](#file-structure) +- [Complete Script Template](#complete-script-template) +- [Installation Phases](#installation-phases) +- [Function Reference](#function-reference) +- [Best Practices](#best-practices) +- [Real Examples](#real-examples) +- [Troubleshooting](#troubleshooting) +- [Contribution Checklist](#contribution-checklist) + +--- + +## Overview + +### Purpose + +Installation scripts (`install/AppName-install.sh`) **run inside the LXC container** and are responsible for: + +1. Setting up the container OS (updates, packages) +2. Installing application dependencies +3. Downloading and configuring the application +4. Setting up services and systemd units +5. Creating version tracking files for updates +6. Generating credentials/configurations +7. Final cleanup and validation + +### Key Characteristics + +- Runs as **root inside container** (not on Proxmox host) +- Executed automatically by `build_container()` from ct/AppName.sh +- Uses `$FUNCTIONS_FILE_PATH` for function library access +- Interactive elements via **whiptail** (GUI menus) +- Version-aware for update tracking + +### Execution Flow + +``` +ct/AppName.sh (Proxmox Host) + ↓ +build_container() + ↓ +pct exec CTID bash -c "$(cat install/AppName-install.sh)" + ↓ +install/AppName-install.sh (Inside Container) + ↓ +Container Ready with App Installed +``` + +--- + +## Execution Context + +### Environment Variables Available + +```bash +# From Proxmox/Container +CTID # Container ID (100, 101, etc.) +PCT_OSTYPE # OS type (alpine, debian, ubuntu) +HOSTNAME # Container hostname + +# From build.func +FUNCTIONS_FILE_PATH # Bash functions library (core.func + tools.func) +VERBOSE # Verbose mode (yes/no) +STD # Standard redirection variable (silent/empty) + +# From install.func +APP # Application name +NSAPP # Normalized app name (lowercase, no spaces) +METHOD # Installation method (ct/install) +RANDOM_UUID # Session UUID for telemetry +``` + +### Access to Functions + +```bash +# All functions from core.func available: +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color # ANSI colors +catch_errors # Error handling +msg_info # Display messages +msg_ok +msg_error + +# All functions from tools.func available: +setup_nodejs # Tool installation +setup_php +setup_python +setup_docker +# ... many more + +# All functions from install.func available: +motd_ssh # Final setup +customize +cleanup_lxc +``` + +--- + +## File Structure + +### Minimal install/AppName-install.sh Template + +```bash +#!/usr/bin/env bash # [1] Shebang + +# [2] Copyright/Metadata +# Copyright (c) 2021-2025 community-scripts ORG +# Author: YourUsername +# License: MIT +# Source: https://example.com + +# [3] Load functions +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +# [4] Installation steps +msg_info "Installing Dependencies" +$STD apt-get install -y package1 package2 +msg_ok "Installed Dependencies" + +# [5] Final setup +motd_ssh +customize +cleanup_lxc +``` + +--- + +## Complete Script Template + +### Phase 1: Header & Initialization + +```bash +#!/usr/bin/env bash +# Copyright (c) 2021-2025 community-scripts ORG +# Author: YourUsername +# Co-Author: AnotherAuthor (for updates) +# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE +# Source: https://github.com/application/repo + +# Load all available functions (from core.func + tools.func) +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" + +# Initialize environment +color # Setup ANSI colors and icons +verb_ip6 # Configure IPv6 (if needed) +catch_errors # Setup error traps +setting_up_container # Verify OS is ready +network_check # Verify internet connectivity +update_os # Update packages (apk/apt) +``` + +### Phase 2: Dependency Installation + +```bash +msg_info "Installing Dependencies" +$STD apt-get install -y \ + curl \ + wget \ + git \ + nano \ + build-essential \ + libssl-dev \ + python3-dev +msg_ok "Installed Dependencies" +``` + +**Guidelines**: +- Use `\` for line continuation (readability) +- Group related packages together +- Collapse repeated prefixes: `php8.4-{bcmath,curl,gd,intl,mbstring}` +- Use `-y` flag for non-interactive installation +- Silence output with `$STD` unless debugging + +### Phase 3: Tool Setup (Using tools.func) + +```bash +# Setup specific tool versions +NODE_VERSION="22" setup_nodejs + +# Or for databases +MYSQL_VERSION="8.0" setup_mysql + +# Or for languages +PHP_VERSION="8.4" PHP_MODULE="redis,imagick" setup_php + +# Or for version control +setup_composer +``` + +**Available Tool Functions**: +```bash +setup_nodejs # Node.js from official repo +setup_php # PHP with optional modules +setup_python # Python 3 +setup_mariadb # MariaDB database +setup_mysql # MySQL database +setup_postgresql # PostgreSQL database +setup_mongodb # MongoDB database +setup_docker # Docker Engine +setup_nodejs # Node.js runtime +setup_composer # PHP Composer +setup_ruby # Ruby runtime +setup_rust # Rust toolchain +setup_go # Go language +setup_java # Java/Temurin +# ... many more in tools.func.md +``` + +### Phase 4: Application Download & Setup + +```bash +# Method A: Download from GitHub releases +msg_info "Downloading ${APP}" +RELEASE=$(curl -fsSL https://api.github.com/repos/user/repo/releases/latest | \ + grep "tag_name" | awk '{print substr($2, 2, length($2)-3)}') + +wget -q "https://github.com/user/repo/releases/download/v${RELEASE}/app-${RELEASE}.tar.gz" \ + -O /opt/app-${RELEASE}.tar.gz + +cd /opt +tar -xzf app-${RELEASE}.tar.gz +rm -f app-${RELEASE}.tar.gz +msg_ok "Downloaded and extracted ${APP}" + +# Method B: Clone from Git +git clone https://github.com/user/repo /opt/appname + +# Method C: Download single file +fetch_and_deploy_gh_release "AppName" "user/repo" "tarball" +``` + +### Phase 5: Configuration Files + +```bash +# Method A: Using cat << EOF (multiline) +cat <<'EOF' >/etc/nginx/sites-available/appname +server { + listen 80; + server_name _; + root /opt/appname/public; + index index.php index.html; + + location ~ \.php$ { + fastcgi_pass unix:/run/php-fpm.sock; + include fastcgi_params; + } +} +EOF + +# Method B: Using sed for replacements +sed -i -e "s|^DB_HOST=.*|DB_HOST=localhost|" \ + -e "s|^DB_USER=.*|DB_USER=appuser|" \ + /opt/appname/.env + +# Method C: Using echo for simple configs +echo "APP_KEY=base64:$(openssl rand -base64 32)" >> /opt/appname/.env +``` + +### Phase 6: Database Setup (If Needed) + +```bash +msg_info "Setting up Database" + +DB_NAME="appname_db" +DB_USER="appuser" +DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13) + +# For MySQL/MariaDB +mysql -u root <> ~/appname.creds +Database Credentials +Database: ${DB_NAME} +Username: ${DB_USER} +Password: ${DB_PASS} +EOF + +msg_ok "Database setup complete" +``` + +### Phase 7: Permission & Ownership + +```bash +msg_info "Setting permissions" + +# Web applications typically run as www-data +chown -R www-data:www-data /opt/appname +chmod -R 755 /opt/appname +chmod -R 644 /opt/appname/* +chmod 755 /opt/appname/*/.* + +# For apps with specific requirements +find /opt/appname/storage -type f -exec chmod 644 {} \; +find /opt/appname/storage -type d -exec chmod 755 {} \; + +msg_ok "Permissions set" +``` + +### Phase 8: Service Configuration + +```bash +# Enable systemd service +systemctl enable -q --now appname + +# Or for OpenRC (Alpine) +rc-service appname start +rc-update add appname default + +# Verify service is running +if systemctl is-active --quiet appname; then + msg_ok "Service running successfully" +else + msg_error "Service failed to start" + journalctl -u appname -n 20 + exit 1 +fi +``` + +### Phase 9: Version Tracking + +```bash +# Essential for update detection +echo "${RELEASE}" > /opt/${APP}_version.txt + +# Or with additional metadata +cat > /opt/${APP}_version.txt < /opt/${APP}_version.txt +``` + +### Phase 5: Configuration + +```bash +# Application-specific configuration +cat > /opt/appname/.env < /opt/appname/config.yml < /opt/${APP}_version.txt + +# ❌ Bad: No version file +# (Update function won't work) +``` + +#### 6. Handle Alpine vs Debian Differences + +```bash +# ✅ Good: Detect OS +if grep -qi 'alpine' /etc/os-release; then + apk add package +else + apt-get install -y package +fi + +# ❌ Bad: Assumes Debian +apt-get install -y package +``` + +#### 7. Use Proper Messaging + +```bash +# ✅ Good: Clear status progression +msg_info "Installing Dependencies" +$STD apt-get install -y package +msg_ok "Installed Dependencies" + +msg_info "Configuring Application" +# ... configuration ... +msg_ok "Application configured" + +# ❌ Bad: No status messages +apt-get install -y package +# ... configuration ... +``` + +### ❌ DON'T: + +#### 1. Hardcode Versions + +```bash +# ❌ Bad: Won't auto-update +VERSION="1.2.3" +wget https://example.com/app-1.2.3.tar.gz + +# ✅ Good: Fetch latest +RELEASE=$(curl -fsSL https://api.github.com/repos/user/repo/releases/latest | jq -r '.tag_name') +wget https://example.com/app-${RELEASE}.tar.gz +``` + +#### 2. Use Root Without Password + +```bash +# ❌ Bad: Allows unprompted root access +mysql -u root < /etc/systemd/system/appname.service < /opt/${APP}_version.txt + +motd_ssh +customize +cleanup_lxc +``` + +### Example 2: Database Application (PHP + MySQL) + +```bash +#!/usr/bin/env bash +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt-get install -y git curl nginx supervisor +msg_ok "Installed Dependencies" + +msg_info "Setting up PHP" +PHP_VERSION="8.4" PHP_MODULE="bcmath,curl,gd,intl,mbstring,pdo_mysql,redis" setup_php +msg_ok "PHP installed" + +msg_info "Setting up Database" +MARIADB_VERSION="11.4" setup_mariadb +msg_ok "MariaDB installed" + +DB_NAME="appname_db" +DB_USER="appuser" +DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13) + +mysql -u root < /opt/${APP}_version.txt + +motd_ssh +customize +cleanup_lxc +``` + +--- + +## Troubleshooting + +### Installation Hangs + +**Symptom**: Script appears to freeze at particular step + +**Causes**: +1. Network connectivity lost +2. Repository server timing out +3. Interactive prompt waiting for input + +**Debug**: +```bash +# Check if process still running +ps aux | grep -i appname + +# Check network +ping -c 1 8.8.8.8 + +# Check apt lock +lsof /var/lib/apt/lists/lock +``` + +### Package Installation Fails + +**Symptom**: `E: Unable to locate package xyz` + +**Causes**: +1. Repository not updated +2. Package name incorrect for OS version +3. Conflicting repository configuration + +**Solution**: +```bash +# Force update +apt-get update --allow-releaseinfo-change +apt-cache search package | grep exact_name +``` + +### Permission Denied on Files + +**Symptom**: Application can't write to `/opt/appname` + +**Causes**: +1. Wrong owner +2. Wrong permissions (644 for files, 755 for directories) + +**Fix**: +```bash +chown -R www-data:www-data /opt/appname +chmod -R 755 /opt/appname +find /opt/appname -type f -exec chmod 644 {} \; +find /opt/appname -type d -exec chmod 755 {} \; +``` + +### Service Won't Start + +**Symptom**: `systemctl status appname` shows failed + +**Debug**: +```bash +# Check service status +systemctl status appname + +# View logs +journalctl -u appname -n 50 + +# Check configuration +systemctl cat appname +``` + +--- + +## Contribution Checklist + +Before submitting a PR: + +### Script Structure +- [ ] Shebang is `#!/usr/bin/env bash` +- [ ] Copyright header with author and source URL +- [ ] Functions loaded via `$FUNCTIONS_FILE_PATH` +- [ ] Initial setup: `color`, `catch_errors`, `setting_up_container`, `network_check`, `update_os` + +### Installation Flow +- [ ] Dependencies installed with `$STD apt-get install -y \` +- [ ] Package names collapsed (`php-{bcmath,curl}`) +- [ ] Tool setup uses functions from tools.func (not manual installation) +- [ ] Application version fetched dynamically (not hardcoded) +- [ ] Version saved to `/opt/${APP}_version.txt` + +### Configuration +- [ ] Configuration files created properly (heredoc or sed) +- [ ] Credentials generated randomly (`openssl rand`) +- [ ] Credentials stored in creds file +- [ ] Passwords use alphanumeric only (no special chars) +- [ ] Proper file permissions set + +### Messaging +- [ ] `msg_info` followed by action then `msg_ok` +- [ ] Error cases use `msg_error` and exit +- [ ] No bare `echo` statements for status (use msg_* functions) + +### Cleanup +- [ ] Temporary files removed +- [ ] Package manager cache cleaned (`autoremove`, `autoclean`) +- [ ] `cleanup_lxc` called at end +- [ ] `motd_ssh` called before `customize` +- [ ] `customize` called before exit + +### Testing +- [ ] Script tested with default OS (Debian 12/Ubuntu 22.04) +- [ ] Script tested with Alpine (if applicable) +- [ ] Script tested with verbose mode (`VERBOSE=yes`) +- [ ] Error handling tested (network interruption, missing packages) +- [ ] Cleanup verified (disk space reduced, temp files removed) + +--- + +## Related Documentation + +- [ct/AppName.sh Guide](UPDATED_APP-ct.md) +- [tools.func Wiki](../misc/tools.func.md) +- [install.func Wiki](../misc/install.func.md) +- [error_handler.func Wiki](../misc/error_handler.func.md) + +--- + +**Last Updated**: December 2025 +**Compatibility**: ProxmoxVED with tools.func v2+ +**Questions?** Open an issue in the repository