diff --git a/ct/channels.sh b/ct/channels.sh index 4860fe90b9..fd5159d08a 100644 --- a/ct/channels.sh +++ b/ct/channels.sh @@ -13,6 +13,7 @@ var_disk="${var_disk:-8}" var_os="${var_os:-debian}" var_version="${var_version:-12}" var_unprivileged="${var_unprivileged:-0}" +var_gpu="${var_gpu:-yes}" header_info "$APP" variables @@ -38,4 +39,4 @@ 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}:8089${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8089${CL}" diff --git a/ct/emby.sh b/ct/emby.sh index 7c6dc0b988..8ce580f7fc 100644 --- a/ct/emby.sh +++ b/ct/emby.sh @@ -13,6 +13,7 @@ var_disk="${var_disk:-8}" var_os="${var_os:-ubuntu}" var_version="${var_version:-24.04}" var_unprivileged="${var_unprivileged:-1}" +var_gpu="${var_gpu:-yes}" header_info "$APP" variables diff --git a/ct/ersatztv.sh b/ct/ersatztv.sh index 8169063ac9..db6e414a5b 100644 --- a/ct/ersatztv.sh +++ b/ct/ersatztv.sh @@ -13,6 +13,7 @@ var_disk="${var_disk:-5}" var_os="${var_os:-debian}" var_version="${var_version:-12}" var_unprivileged="${var_unprivileged:-1}" +var_gpu="${var_gpu:-yes}" header_info "$APP" variables diff --git a/ct/fileflows.sh b/ct/fileflows.sh index 51dcd905e7..6fb8d972d0 100644 --- a/ct/fileflows.sh +++ b/ct/fileflows.sh @@ -13,6 +13,7 @@ var_disk="${var_disk:-8}" var_os="${var_os:-debian}" var_version="${var_version:-12}" var_unprivileged="${var_unprivileged:-1}" +var_gpu="${var_gpu:-yes}" header_info "$APP" variables diff --git a/ct/frigate.sh b/ct/frigate.sh index 32ac699540..b72d9d8488 100644 --- a/ct/frigate.sh +++ b/ct/frigate.sh @@ -13,6 +13,7 @@ var_disk="${var_disk:-20}" var_os="${var_os:-debian}" var_version="${var_version:-11}" var_unprivileged="${var_unprivileged:-0}" +var_gpu="${var_gpu:-yes}" header_info "$APP" variables @@ -38,4 +39,4 @@ 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}:5000${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5000${CL}" diff --git a/ct/immich.sh b/ct/immich.sh index 15fba2bbf0..64cefd5dce 100644 --- a/ct/immich.sh +++ b/ct/immich.sh @@ -13,6 +13,7 @@ var_ram="${var_ram:-4096}" var_os="${var_os:-debian}" var_version="${var_version:-13}" var_unprivileged="${var_unprivileged:-1}" +var_gpu="${var_gpu:-yes}" header_info "$APP" variables diff --git a/ct/jellyfin.sh b/ct/jellyfin.sh index 64c48919b7..d17639bea1 100644 --- a/ct/jellyfin.sh +++ b/ct/jellyfin.sh @@ -13,6 +13,7 @@ var_disk="${var_disk:-16}" var_os="${var_os:-ubuntu}" var_version="${var_version:-24.04}" var_unprivileged="${var_unprivileged:-1}" +var_gpu="${var_gpu:-yes}" header_info "$APP" variables diff --git a/ct/ollama.sh b/ct/ollama.sh index 3677be1311..f87faa7992 100644 --- a/ct/ollama.sh +++ b/ct/ollama.sh @@ -12,6 +12,7 @@ var_ram="${var_ram:-4096}" var_disk="${var_disk:-35}" var_os="${var_os:-ubuntu}" var_version="${var_version:-24.04}" +var_gpu="${var_gpu:-yes}" header_info "$APP" variables diff --git a/ct/openwebui.sh b/ct/openwebui.sh index 47fd3a9e2f..3b2ca3a303 100644 --- a/ct/openwebui.sh +++ b/ct/openwebui.sh @@ -13,6 +13,7 @@ var_disk="${var_disk:-25}" var_os="${var_os:-debian}" var_version="${var_version:-13}" var_unprivileged="${var_unprivileged:-1}" +var_gpu="${var_gpu:-yes}" header_info "$APP" variables diff --git a/ct/plex.sh b/ct/plex.sh index 43bbff1574..8ffc9475d8 100644 --- a/ct/plex.sh +++ b/ct/plex.sh @@ -13,6 +13,7 @@ var_disk="${var_disk:-8}" var_os="${var_os:-ubuntu}" var_version="${var_version:-24.04}" var_unprivileged="${var_unprivileged:-1}" +var_gpu="${var_gpu:-yes}" header_info "$APP" variables @@ -23,8 +24,8 @@ function update_script() { header_info check_container_storage check_container_resources - if [[ ! -f /etc/apt/sources.list.d/plexmediaserver.list ]] \ - && [[ ! -f /etc/apt/sources.list.d/plexmediaserver.sources ]]; then + if [[ ! -f /etc/apt/sources.list.d/plexmediaserver.list ]] && + [[ ! -f /etc/apt/sources.list.d/plexmediaserver.sources ]]; then msg_error "No ${APP} Installation Found!" exit fi diff --git a/ct/tdarr.sh b/ct/tdarr.sh index 299bd2f3f8..81e4c2250c 100644 --- a/ct/tdarr.sh +++ b/ct/tdarr.sh @@ -13,6 +13,7 @@ var_disk="${var_disk:-4}" var_os="${var_os:-debian}" var_version="${var_version:-13}" var_unprivileged="${var_unprivileged:-1}" +var_gpu="${var_gpu:-yes}" header_info "$APP" variables diff --git a/ct/tunarr.sh b/ct/tunarr.sh index 9bdfe2147e..e706e604cc 100644 --- a/ct/tunarr.sh +++ b/ct/tunarr.sh @@ -13,6 +13,7 @@ var_disk="${var_disk:-5}" var_os="${var_os:-debian}" var_version="${var_version:-13}" var_unprivileged="${var_unprivileged:-1}" +var_gpu="${var_gpu:-yes}" header_info "$APP" variables diff --git a/ct/unmanic.sh b/ct/unmanic.sh index 3836c4f3b1..08469fab55 100644 --- a/ct/unmanic.sh +++ b/ct/unmanic.sh @@ -13,6 +13,7 @@ var_disk="${var_disk:-4}" var_os="${var_os:-debian}" var_version="${var_version:-13}" var_unprivileged="${var_unprivileged:-0}" +var_gpu="${var_gpu:-yes}" header_info "$APP" variables diff --git a/docs/TECHNICAL_REFERENCE.md b/docs/TECHNICAL_REFERENCE.md index aea5148c9d..ec4f21eb36 100644 --- a/docs/TECHNICAL_REFERENCE.md +++ b/docs/TECHNICAL_REFERENCE.md @@ -1,8 +1,8 @@ # Technical Reference: Configuration System Architecture > **For Developers and Advanced Users** -> -> *Deep dive into how the defaults and configuration system works* +> +> _Deep dive into how the defaults and configuration system works_ --- @@ -123,13 +123,13 @@ VAR_VALUE := [^\n]* # Any printable characters except newline **Constraints**: -| Constraint | Value | -|-----------|-------| -| Max file size | 64 KB | -| Max line length | 1024 bytes | -| Max variables | 100 | -| Allowed var names | `var_[a-z_]+` | -| Value validation | Whitelist + Sanitization | +| Constraint | Value | +| ----------------- | ------------------------ | +| Max file size | 64 KB | +| Max line length | 1024 bytes | +| Max variables | 100 | +| Allowed var names | `var_[a-z_]+` | +| Value validation | Whitelist + Sanitization | **Example Valid File**: @@ -206,21 +206,24 @@ var_tags=dns,pihole **Purpose**: Safely load variables from .vars files without using `source` or `eval` **Signature**: + ```bash load_vars_file(filepath) ``` **Parameters**: -| Param | Type | Required | Example | -|-------|------|----------|---------| -| filepath | String | Yes | `/usr/local/community-scripts/default.vars` | +| Param | Type | Required | Example | +| -------- | ------ | -------- | ------------------------------------------- | +| filepath | String | Yes | `/usr/local/community-scripts/default.vars` | **Returns**: + - `0` on success - `1` on error (file missing, parse error, etc.) **Environment Side Effects**: + - Sets all parsed `var_*` variables as shell variables - Does NOT unset variables if file missing (safe) - Does NOT affect other variables @@ -230,25 +233,25 @@ load_vars_file(filepath) ```bash load_vars_file() { local file="$1" - + # File must exist [ -f "$file" ] || return 0 - + # Parse line by line (not with source/eval) local line key val while IFS='=' read -r key val || [ -n "$key" ]; do # Skip comments and empty lines [[ "$key" =~ ^[[:space:]]*# ]] && continue [[ -z "$key" ]] && continue - + # Validate key is in whitelist _is_whitelisted_key "$key" || continue - + # Sanitize and export value val="$(_sanitize_value "$val")" [ $? -eq 0 ] && export "$key=$val" done < "$file" - + return 0 } ``` @@ -281,6 +284,7 @@ echo "Allocating ${var_ram} MB RAM" **Purpose**: Get the full path for app-specific defaults file **Signature**: + ```bash get_app_defaults_path() ``` @@ -288,6 +292,7 @@ get_app_defaults_path() **Parameters**: None **Returns**: + - String: Full path to app defaults file **Implementation**: @@ -322,6 +327,7 @@ load_vars_file "$(get_app_defaults_path)" **Purpose**: Load and display user global defaults **Signature**: + ```bash default_var_settings() ``` @@ -329,6 +335,7 @@ default_var_settings() **Parameters**: None **Returns**: + - `0` on success - `1` on error @@ -337,15 +344,15 @@ default_var_settings() ``` 1. Find default.vars location (usually /usr/local/community-scripts/default.vars) - + 2. Create if missing - + 3. Load variables from file - + 4. Map var_verbose → VERBOSE variable - + 5. Call base_settings (apply to container config) - + 6. Call echo_default (display summary) ``` @@ -354,20 +361,20 @@ default_var_settings() ```bash default_var_settings() { local VAR_WHITELIST=( - var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse + var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_gpu var_gateway var_hostname var_ipv6_method var_mac var_mtu var_net var_ns var_pw var_ram var_tags var_tun var_unprivileged var_verbose var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage ) - + # Ensure file exists _ensure_default_vars - + # Find and load local dv="$(_find_default_vars)" load_vars_file "$dv" - + # Map verbose flag if [[ -n "${var_verbose:-}" ]]; then case "${var_verbose,,}" in @@ -375,7 +382,7 @@ default_var_settings() { *) VERBOSE="${var_verbose}" ;; esac fi - + # Apply and display base_settings "$VERBOSE" echo_default @@ -389,6 +396,7 @@ default_var_settings() { **Purpose**: Offer to save current settings as app-specific defaults **Signature**: + ```bash maybe_offer_save_app_defaults() ``` @@ -413,10 +421,10 @@ maybe_offer_save_app_defaults() ```bash maybe_offer_save_app_defaults() { local app_vars_path="$(get_app_defaults_path)" - + # Build current settings from memory local new_tmp="$(_build_current_app_vars_tmp)" - + # Check if already exists if [ -f "$app_vars_path" ]; then # Show diff and ask: Update? Keep? View Diff? @@ -438,29 +446,31 @@ maybe_offer_save_app_defaults() { **Purpose**: Remove dangerous characters/patterns from configuration values **Signature**: + ```bash _sanitize_value(value) ``` **Parameters**: -| Param | Type | Required | -|-------|------|----------| -| value | String | Yes | +| Param | Type | Required | +| ----- | ------ | -------- | +| value | String | Yes | **Returns**: + - `0` (success) + sanitized value on stdout - `1` (failure) + nothing if dangerous **Dangerous Patterns**: -| Pattern | Threat | Example | -|---------|--------|---------| -| `$(...)` | Command substitution | `$(rm -rf /)` | -| `` ` ` `` | Command substitution | `` `whoami` `` | -| `;` | Command separator | `value; rm -rf /` | -| `&` | Background execution | `value & malicious` | -| `<(` | Process substitution | `<(cat /etc/passwd)` | +| Pattern | Threat | Example | +| --------- | -------------------- | -------------------- | +| `$(...)` | Command substitution | `$(rm -rf /)` | +| `` ` ` `` | Command substitution | `` `whoami` `` | +| `;` | Command separator | `value; rm -rf /` | +| `&` | Background execution | `value & malicious` | +| `<(` | Process substitution | `<(cat /etc/passwd)` | **Implementation**: @@ -501,17 +511,19 @@ fi **Purpose**: Check if variable name is in allowed whitelist **Signature**: + ```bash _is_whitelisted_key(key) ``` **Parameters**: -| Param | Type | Required | Example | -|-------|------|----------|---------| -| key | String | Yes | `var_cpu` | +| Param | Type | Required | Example | +| ----- | ------ | -------- | --------- | +| key | String | Yes | `var_cpu` | **Returns**: + - `0` if key is whitelisted - `1` if key is NOT whitelisted @@ -573,6 +585,7 @@ Step 4: Use BUILT-IN DEFAULTS ### Precedence Examples **Example 1: Environment Variable Wins** + ```bash # Shell environment has highest priority $ export var_cpu=16 @@ -583,6 +596,7 @@ $ bash pihole-install.sh ``` **Example 2: App Defaults Override User Defaults** + ```bash # User Defaults: var_cpu=4 # App Defaults: var_cpu=2 @@ -593,6 +607,7 @@ $ bash pihole-install.sh ``` **Example 3: All Defaults Missing (Built-ins Used)** + ```bash # No environment variables set # No app defaults file @@ -611,21 +626,21 @@ $ bash pihole-install.sh base_settings() { # Priority 1: Environment variables (already set if export used) CT_TYPE=${var_unprivileged:-"1"} # Use existing or default - + # Priority 2: Load app defaults (may override above) if [ -f "$(get_app_defaults_path)" ]; then load_vars_file "$(get_app_defaults_path)" fi - + # Priority 3: Load user defaults if [ -f "/usr/local/community-scripts/default.vars" ]; then load_vars_file "/usr/local/community-scripts/default.vars" fi - + # Priority 4: Apply built-in defaults (lowest) CORE_COUNT=${var_cpu:-"${APP_CPU_DEFAULT:-2}"} RAM_SIZE=${var_ram:-"${APP_RAM_DEFAULT:-1024}"} - + # Result: var_cpu has been set through precedence chain } ``` @@ -734,14 +749,14 @@ CONTAINER CREATION STARTED ### Threat Model -| Threat | Mitigation | -|--------|-----------| -| **Arbitrary Code Execution** | No `source` or `eval`; manual parsing only | -| **Variable Injection** | Whitelist of allowed variable names | -| **Command Substitution** | `_sanitize_value()` blocks `$()`, backticks, etc. | -| **Path Traversal** | Files locked to `/usr/local/community-scripts/` | -| **Permission Escalation** | Files created with restricted permissions | -| **Information Disclosure** | Sensitive variables not logged | +| Threat | Mitigation | +| ---------------------------- | ------------------------------------------------- | +| **Arbitrary Code Execution** | No `source` or `eval`; manual parsing only | +| **Variable Injection** | Whitelist of allowed variable names | +| **Command Substitution** | `_sanitize_value()` blocks `$()`, backticks, etc. | +| **Path Traversal** | Files locked to `/usr/local/community-scripts/` | +| **Permission Escalation** | Files created with restricted permissions | +| **Information Disclosure** | Sensitive variables not logged | ### Security Controls @@ -798,6 +813,7 @@ fi ### Module: `build.func` **Load Order** (in actual scripts): + 1. `#!/usr/bin/env bash` - Shebang 2. `source /dev/stdin <<<$(curl ... api.func)` - API functions 3. `source /dev/stdin <<<$(curl ... build.func)` - Build functions @@ -832,17 +848,17 @@ fi # Section 6: Installation Flow - install_script() # Main entry point -- advanced_settings() # 19-step wizard +- advanced_settings() # 20-step wizard ``` ### Regex Patterns Used -| Pattern | Purpose | Example Match | -|---------|---------|---| -| `^[0-9]+([.][0-9]+)?$` | Integer validation | `4`, `192.168` | -| `^var_[a-z_]+$` | Variable name | `var_cpu`, `var_ssh` | -| `*'$('*` | Command substitution | `$(whoami)` | -| `*\`*` | Backtick substitution | `` `cat /etc/passwd` `` | +| Pattern | Purpose | Example Match | +| ---------------------- | --------------------- | ----------------------- | +| `^[0-9]+([.][0-9]+)?$` | Integer validation | `4`, `192.168` | +| `^var_[a-z_]+$` | Variable name | `var_cpu`, `var_ssh` | +| `*'$('*` | Command substitution | `$(whoami)` | +| `*\`\*` | Backtick substitution | `` `cat /etc/passwd` `` | --- @@ -869,12 +885,12 @@ fi ### Function Mapping -| Old | New | Location | -|-----|-----|----------| -| `read_config()` | `load_vars_file()` | build.func | -| `write_config()` | `_build_current_app_vars_tmp()` | build.func | -| None | `maybe_offer_save_app_defaults()` | build.func | -| None | `get_app_defaults_path()` | build.func | +| Old | New | Location | +| ---------------- | --------------------------------- | ---------- | +| `read_config()` | `load_vars_file()` | build.func | +| `write_config()` | `_build_current_app_vars_tmp()` | build.func | +| None | `maybe_offer_save_app_defaults()` | build.func | +| None | `get_app_defaults_path()` | build.func | --- diff --git a/docs/misc/build.func/BUILD_FUNC_ENVIRONMENT_VARIABLES.md b/docs/misc/build.func/BUILD_FUNC_ENVIRONMENT_VARIABLES.md index b116d31063..11b9821857 100644 --- a/docs/misc/build.func/BUILD_FUNC_ENVIRONMENT_VARIABLES.md +++ b/docs/misc/build.func/BUILD_FUNC_ENVIRONMENT_VARIABLES.md @@ -8,103 +8,123 @@ This document provides a comprehensive reference of all environment variables us ### Core Container Variables -| Variable | Description | Default | Set In | Used In | -|----------|-------------|---------|---------|---------| -| `APP` | Application name (e.g., "plex", "nextcloud") | - | Environment | Throughout | -| `NSAPP` | Namespace application name | `$APP` | Environment | Throughout | -| `CTID` | Container ID | - | Environment | Container creation | -| `CT_TYPE` | Container type ("install" or "update") | "install" | Environment | Entry point | -| `CT_NAME` | Container name | `$APP` | Environment | Container creation | +| Variable | Description | Default | Set In | Used In | +| --------- | -------------------------------------------- | --------- | ----------- | ------------------ | +| `APP` | Application name (e.g., "plex", "nextcloud") | - | Environment | Throughout | +| `NSAPP` | Namespace application name | `$APP` | Environment | Throughout | +| `CTID` | Container ID | - | Environment | Container creation | +| `CT_TYPE` | Container type ("install" or "update") | "install" | Environment | Entry point | +| `CT_NAME` | Container name | `$APP` | Environment | Container creation | ### Operating System Variables -| Variable | Description | Default | Set In | Used In | -|----------|-------------|---------|---------|---------| -| `var_os` | Operating system selection | "debian" | base_settings() | OS selection | -| `var_version` | OS version | "12" | base_settings() | Template selection | -| `var_template` | Template name | Auto-generated | base_settings() | Template download | +| Variable | Description | Default | Set In | Used In | +| -------------- | -------------------------- | -------------- | --------------- | ------------------ | +| `var_os` | Operating system selection | "debian" | base_settings() | OS selection | +| `var_version` | OS version | "12" | base_settings() | Template selection | +| `var_template` | Template name | Auto-generated | base_settings() | Template download | ### Resource Configuration Variables -| Variable | Description | Default | Set In | Used In | -|----------|-------------|---------|---------|---------| -| `var_cpu` | CPU cores | "2" | base_settings() | Container creation | -| `var_ram` | RAM in MB | "2048" | base_settings() | Container creation | -| `var_disk` | Disk size in GB | "8" | base_settings() | Container creation | -| `DISK_SIZE` | Disk size (alternative) | `$var_disk` | Environment | Container creation | -| `CORE_COUNT` | CPU cores (alternative) | `$var_cpu` | Environment | Container creation | -| `RAM_SIZE` | RAM size (alternative) | `$var_ram` | Environment | Container creation | +| Variable | Description | Default | Set In | Used In | +| ------------ | ----------------------- | ----------- | --------------- | ------------------ | +| `var_cpu` | CPU cores | "2" | base_settings() | Container creation | +| `var_ram` | RAM in MB | "2048" | base_settings() | Container creation | +| `var_disk` | Disk size in GB | "8" | base_settings() | Container creation | +| `DISK_SIZE` | Disk size (alternative) | `$var_disk` | Environment | Container creation | +| `CORE_COUNT` | CPU cores (alternative) | `$var_cpu` | Environment | Container creation | +| `RAM_SIZE` | RAM size (alternative) | `$var_ram` | Environment | Container creation | ### Network Configuration Variables -| Variable | Description | Default | Set In | Used In | -|----------|-------------|---------|---------|---------| -| `var_net` | Network interface | "vmbr0" | base_settings() | Network config | -| `var_bridge` | Bridge interface | "vmbr0" | base_settings() | Network config | -| `var_gateway` | Gateway IP | "192.168.1.1" | base_settings() | Network config | -| `var_ip` | Container IP address | - | User input | Network config | -| `var_ipv6` | IPv6 address | - | User input | Network config | -| `var_vlan` | VLAN ID | - | User input | Network config | -| `var_mtu` | MTU size | "1500" | base_settings() | Network config | -| `var_mac` | MAC address | Auto-generated | base_settings() | Network config | -| `NET` | Network interface (alternative) | `$var_net` | Environment | Network config | -| `BRG` | Bridge interface (alternative) | `$var_bridge` | Environment | Network config | -| `GATE` | Gateway IP (alternative) | `$var_gateway` | Environment | Network config | -| `IPV6_METHOD` | IPv6 configuration method | "none" | Environment | Network config | -| `VLAN` | VLAN ID (alternative) | `$var_vlan` | Environment | Network config | -| `MTU` | MTU size (alternative) | `$var_mtu` | Environment | Network config | -| `MAC` | MAC address (alternative) | `$var_mac` | Environment | Network config | +| Variable | Description | Default | Set In | Used In | +| ------------- | ------------------------------- | -------------- | --------------- | -------------- | +| `var_net` | Network interface | "vmbr0" | base_settings() | Network config | +| `var_bridge` | Bridge interface | "vmbr0" | base_settings() | Network config | +| `var_gateway` | Gateway IP | "192.168.1.1" | base_settings() | Network config | +| `var_ip` | Container IP address | - | User input | Network config | +| `var_ipv6` | IPv6 address | - | User input | Network config | +| `var_vlan` | VLAN ID | - | User input | Network config | +| `var_mtu` | MTU size | "1500" | base_settings() | Network config | +| `var_mac` | MAC address | Auto-generated | base_settings() | Network config | +| `NET` | Network interface (alternative) | `$var_net` | Environment | Network config | +| `BRG` | Bridge interface (alternative) | `$var_bridge` | Environment | Network config | +| `GATE` | Gateway IP (alternative) | `$var_gateway` | Environment | Network config | +| `IPV6_METHOD` | IPv6 configuration method | "none" | Environment | Network config | +| `VLAN` | VLAN ID (alternative) | `$var_vlan` | Environment | Network config | +| `MTU` | MTU size (alternative) | `$var_mtu` | Environment | Network config | +| `MAC` | MAC address (alternative) | `$var_mac` | Environment | Network config | ### Storage Configuration Variables -| Variable | Description | Default | Set In | Used In | -|----------|-------------|---------|---------|---------| -| `var_template_storage` | Storage for templates | - | select_storage() | Template storage | -| `var_container_storage` | Storage for container disks | - | select_storage() | Container storage | -| `TEMPLATE_STORAGE` | Template storage (alternative) | `$var_template_storage` | Environment | Template storage | -| `CONTAINER_STORAGE` | Container storage (alternative) | `$var_container_storage` | Environment | Container storage | +| Variable | Description | Default | Set In | Used In | +| ----------------------- | ------------------------------- | ------------------------ | ---------------- | ----------------- | +| `var_template_storage` | Storage for templates | - | select_storage() | Template storage | +| `var_container_storage` | Storage for container disks | - | select_storage() | Container storage | +| `TEMPLATE_STORAGE` | Template storage (alternative) | `$var_template_storage` | Environment | Template storage | +| `CONTAINER_STORAGE` | Container storage (alternative) | `$var_container_storage` | Environment | Container storage | ### Feature Flags -| Variable | Description | Default | Set In | Used In | -|----------|-------------|---------|---------|---------| -| `ENABLE_FUSE` | Enable FUSE support | "true" | base_settings() | Container features | -| `ENABLE_TUN` | Enable TUN/TAP support | "true" | base_settings() | Container features | -| `ENABLE_KEYCTL` | Enable keyctl support | "true" | base_settings() | Container features | -| `ENABLE_MOUNT` | Enable mount support | "true" | base_settings() | Container features | -| `ENABLE_NESTING` | Enable nesting support | "false" | base_settings() | Container features | -| `ENABLE_PRIVILEGED` | Enable privileged mode | "false" | base_settings() | Container features | -| `ENABLE_UNPRIVILEGED` | Enable unprivileged mode | "true" | base_settings() | Container features | -| `VERBOSE` | Enable verbose output | "false" | Environment | Logging | -| `SSH` | Enable SSH key provisioning | "true" | base_settings() | SSH setup | +| Variable | Description | Default | Set In | Used In | +| --------------------- | --------------------------- | ------- | --------------- | ------------------ | +| `ENABLE_FUSE` | Enable FUSE support | "true" | base_settings() | Container features | +| `ENABLE_TUN` | Enable TUN/TAP support | "true" | base_settings() | Container features | +| `ENABLE_KEYCTL` | Enable keyctl support | "true" | base_settings() | Container features | +| `ENABLE_MOUNT` | Enable mount support | "true" | base_settings() | Container features | +| `ENABLE_NESTING` | Enable nesting support | "false" | base_settings() | Container features | +| `ENABLE_PRIVILEGED` | Enable privileged mode | "false" | base_settings() | Container features | +| `ENABLE_UNPRIVILEGED` | Enable unprivileged mode | "true" | base_settings() | Container features | +| `VERBOSE` | Enable verbose output | "false" | Environment | Logging | +| `SSH` | Enable SSH key provisioning | "true" | base_settings() | SSH setup | ### GPU Passthrough Variables -| Variable | Description | Default | Set In | Used In | -|----------|-------------|---------|---------|---------| -| `GPU_APPS` | List of apps that support GPU | - | Environment | GPU detection | -| `var_gpu` | GPU selection | - | User input | GPU passthrough | -| `var_gpu_type` | GPU type (intel/amd/nvidia) | - | detect_gpu_devices() | GPU passthrough | -| `var_gpu_devices` | GPU device list | - | detect_gpu_devices() | GPU passthrough | +| Variable | Description | Default | Set In | Used In | +| ------------ | ------------------------------- | ------- | ------------------------------------------- | ------------------ | +| `var_gpu` | Enable GPU passthrough | "no" | CT script / Environment / Advanced Settings | GPU passthrough | +| `ENABLE_GPU` | GPU passthrough flag (internal) | "no" | Advanced Settings | Container creation | + +**Note**: GPU passthrough is controlled via `var_gpu`. Apps that benefit from GPU acceleration (media servers, AI/ML, transcoding) have `var_gpu=yes` as default in their CT scripts. + +**Apps with GPU enabled by default**: + +- Media: jellyfin, plex, emby, channels, ersatztv, tunarr, immich +- Transcoding: tdarr, unmanic, fileflows +- AI/ML: ollama, openwebui +- NVR: frigate + +**Usage Examples**: + +```bash +# Disable GPU for a specific installation +var_gpu=no bash -c "$(curl -fsSL https://...jellyfin.sh)" + +# Enable GPU for apps without default GPU support +var_gpu=yes bash -c "$(curl -fsSL https://...debian.sh)" + +# Set in default.vars for all apps +echo "var_gpu=yes" >> /usr/local/community-scripts/default.vars +``` ### API and Diagnostics Variables -| Variable | Description | Default | Set In | Used In | -|----------|-------------|---------|---------|---------| -| `DIAGNOSTICS` | Enable diagnostics mode | "false" | Environment | Diagnostics | -| `METHOD` | Installation method | "install" | Environment | Installation flow | -| `RANDOM_UUID` | Random UUID for tracking | - | Environment | Logging | -| `API_TOKEN` | Proxmox API token | - | Environment | API calls | -| `API_USER` | Proxmox API user | - | Environment | API calls | +| Variable | Description | Default | Set In | Used In | +| ------------- | ------------------------ | --------- | ----------- | ----------------- | +| `DIAGNOSTICS` | Enable diagnostics mode | "false" | Environment | Diagnostics | +| `METHOD` | Installation method | "install" | Environment | Installation flow | +| `RANDOM_UUID` | Random UUID for tracking | - | Environment | Logging | +| `API_TOKEN` | Proxmox API token | - | Environment | API calls | +| `API_USER` | Proxmox API user | - | Environment | API calls | ### Settings Persistence Variables -| Variable | Description | Default | Set In | Used In | -|----------|-------------|---------|---------|---------| -| `SAVE_DEFAULTS` | Save settings as defaults | "false" | User input | Settings persistence | -| `SAVE_APP_DEFAULTS` | Save app-specific defaults | "false" | User input | Settings persistence | -| `DEFAULT_VARS_FILE` | Path to default.vars | "/usr/local/community-scripts/default.vars" | Environment | Settings persistence | -| `APP_DEFAULTS_FILE` | Path to app.vars | "/usr/local/community-scripts/defaults/$APP.vars" | Environment | Settings persistence | +| Variable | Description | Default | Set In | Used In | +| ------------------- | -------------------------- | ------------------------------------------------- | ----------- | -------------------- | +| `SAVE_DEFAULTS` | Save settings as defaults | "false" | User input | Settings persistence | +| `SAVE_APP_DEFAULTS` | Save app-specific defaults | "false" | User input | Settings persistence | +| `DEFAULT_VARS_FILE` | Path to default.vars | "/usr/local/community-scripts/default.vars" | Environment | Settings persistence | +| `APP_DEFAULTS_FILE` | Path to app.vars | "/usr/local/community-scripts/defaults/$APP.vars" | Environment | Settings persistence | ## Variable Precedence Chain @@ -152,6 +172,7 @@ export SSH="true" ## Environment Variable Usage Patterns ### 1. Container Creation + ```bash # Basic container creation export APP="nextcloud" @@ -170,6 +191,7 @@ export var_container_storage="local" ``` ### 2. GPU Passthrough + ```bash # Enable GPU passthrough export GPU_APPS="plex,jellyfin,emby" @@ -178,6 +200,7 @@ export ENABLE_PRIVILEGED="true" ``` ### 3. Advanced Network Configuration + ```bash # VLAN and IPv6 configuration export var_vlan="100" @@ -187,6 +210,7 @@ export var_mtu="9000" ``` ### 4. Storage Configuration + ```bash # Custom storage locations export var_template_storage="nfs-storage" @@ -206,6 +230,7 @@ The script validates variables at several points: ## Common Variable Combinations ### Development Container + ```bash export APP="dev-container" export CTID="200" @@ -220,6 +245,7 @@ export ENABLE_PRIVILEGED="true" ``` ### Media Server with GPU + ```bash export APP="plex" export CTID="300" @@ -235,6 +261,7 @@ export ENABLE_PRIVILEGED="true" ``` ### Lightweight Service + ```bash export APP="nginx" export CTID="400" diff --git a/misc/build.func b/misc/build.func index 654d94111e..2b7bf0d898 100644 --- a/misc/build.func +++ b/misc/build.func @@ -453,7 +453,7 @@ load_vars_file() { # Allowed var_* keys local VAR_WHITELIST=( - var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_keyctl + var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_gpu var_keyctl var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu var_net var_nesting var_ns var_protection var_pw var_ram var_tags var_timezone var_tun var_unprivileged var_verbose var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage @@ -505,7 +505,7 @@ default_var_settings() { # Allowed var_* keys (alphabetically sorted) # Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique) local VAR_WHITELIST=( - var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_keyctl + var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_gpu var_keyctl var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu var_net var_nesting var_ns var_protection var_pw var_ram var_tags var_timezone var_tun var_unprivileged var_verbose var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage @@ -667,7 +667,7 @@ get_app_defaults_path() { if ! declare -p VAR_WHITELIST >/dev/null 2>&1; then # Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique) declare -ag VAR_WHITELIST=( - var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse + var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_gpu var_gateway var_hostname var_ipv6_method var_mac var_mtu var_net var_ns var_pw var_ram var_tags var_tun var_unprivileged var_verbose var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage @@ -1011,7 +1011,7 @@ advanced_settings() { # Initialize defaults TAGS="community-script;${var_tags:-}" local STEP=1 - local MAX_STEP=19 + local MAX_STEP=20 # Store values for back navigation local _ct_type="${CT_TYPE:-1}" @@ -1036,6 +1036,7 @@ advanced_settings() { local _vlan="" local _tags="$TAGS" local _enable_fuse="no" + local _enable_gpu="${var_gpu:-no}" local _verbose="no" local _enable_keyctl="0" local _enable_mknod="0" @@ -1527,9 +1528,33 @@ advanced_settings() { ;; # ═══════════════════════════════════════════════════════════════════════════ - # STEP 19: Confirmation + # STEP 19: GPU Passthrough # ═══════════════════════════════════════════════════════════════════════════ 19) + local gpu_default="OFF" + [[ "$_enable_gpu" == "yes" ]] && gpu_default="ON" + + if whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \ + --title "GPU PASSTHROUGH" \ + --ok-button "Next" --cancel-button "Back" \ + --defaultno \ + --yesno "\nEnable GPU Passthrough?\n\nAutomatically detects and passes through available GPUs\n(Intel/AMD/NVIDIA) for hardware acceleration.\n\nRecommended for: Media servers, AI/ML, Transcoding" 14 62; then + _enable_gpu="yes" + else + if [ $? -eq 1 ]; then + _enable_gpu="no" + else + ((STEP--)) + continue + fi + fi + ((STEP++)) + ;; + + # ═══════════════════════════════════════════════════════════════════════════ + # STEP 20: Confirmation + # ═══════════════════════════════════════════════════════════════════════════ + 20) # Build summary local ct_type_desc="Unprivileged" [[ "$_ct_type" == "0" ]] && ct_type_desc="Privileged" @@ -1550,12 +1575,13 @@ Network: Options: FUSE: $_enable_fuse + GPU Passthrough: $_enable_gpu Verbose: $_verbose" if whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \ --title "CONFIRM SETTINGS" \ --ok-button "Create LXC" --cancel-button "Back" \ - --yesno "$summary\n\nCreate ${APP} LXC with these settings?" 26 58; then + --yesno "$summary\n\nCreate ${APP} LXC with these settings?" 28 58; then ((STEP++)) else ((STEP--)) @@ -1582,8 +1608,12 @@ Options: IPV6_GATE="$_ipv6_gate" TAGS="$_tags" ENABLE_FUSE="$_enable_fuse" + ENABLE_GPU="$_enable_gpu" VERBOSE="$_verbose" + # Update var_gpu based on user choice (for is_gpu_app function) + var_gpu="$_enable_gpu" + # Format optional values [[ -n "$_mtu" ]] && MTU=",mtu=$_mtu" || MTU="" [[ -n "$_sd" ]] && SD="-searchdomain=$_sd" || SD="" @@ -1600,6 +1630,10 @@ Options: export UDHCPC_FIX export SSH_KEYS_FILE + # Exit alternate screen buffer before showing summary (so output remains visible) + tput rmcup 2>/dev/null || true + trap - RETURN + # Display final summary echo -e "\n${INFO}${BOLD}${DGN}PVE Version ${PVEVERSION} (Kernel: ${KERNEL_VERSION})${CL}" echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}" @@ -1614,6 +1648,7 @@ Options: echo -e "${NETWORK}${BOLD}${DGN}IPv4: ${BGN}$NET${CL}" echo -e "${NETWORK}${BOLD}${DGN}IPv6: ${BGN}$IPV6_METHOD${CL}" echo -e "${FUSE}${BOLD}${DGN}FUSE Support: ${BGN}$ENABLE_FUSE${CL}" + echo -e "${GPU}${BOLD}${DGN}GPU Passthrough: ${BGN}$ENABLE_GPU${CL}" echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}$VERBOSE${CL}" echo -e "${CREATING}${BOLD}${RD}Creating a ${APP} LXC using the above advanced settings${CL}" } @@ -1736,6 +1771,9 @@ echo_default() { echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}" echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}" echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}" + if [[ -n "${var_gpu:-}" && "${var_gpu}" == "yes" ]]; then + echo -e "${GPU}${BOLD}${DGN}GPU Passthrough: ${BGN}Enabled${CL}" + fi if [ "$VERBOSE" == "yes" ]; then echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}Enabled${CL}" fi @@ -2387,21 +2425,15 @@ build_container() { # GPU/USB PASSTHROUGH CONFIGURATION # ============================================================================ - # List of applications that benefit from GPU acceleration - GPU_APPS=( - "immich" "channels" "emby" "ersatztv" "frigate" - "jellyfin" "plex" "scrypted" "tdarr" "unmanic" - "ollama" "fileflows" "open-webui" "tunarr" - "handbrake" "sunshine" "moonlight" "kodi" "stremio" - "viseron" - ) - - # Check if app needs GPU + # Check if GPU passthrough is enabled + # Returns true only if var_gpu is explicitly set to "yes" + # Can be set via: + # - Environment variable: var_gpu=yes bash -c "..." + # - CT script default: var_gpu="${var_gpu:-no}" + # - Advanced settings wizard + # - App defaults file: /usr/local/community-scripts/defaults/.vars is_gpu_app() { - local app="${1,,}" - for gpu_app in "${GPU_APPS[@]}"; do - [[ "$app" == "${gpu_app,,}" ]] && return 0 - done + [[ "${var_gpu:-no}" == "yes" ]] && return 0 return 1 } @@ -2491,8 +2523,13 @@ EOF # Configure GPU passthrough configure_gpu_passthrough() { - # Skip if not a GPU app and not privileged - if [[ "$CT_TYPE" != "0" ]] && ! is_gpu_app "$APP"; then + # Skip if: + # GPU passthrough is enabled when var_gpu="yes": + # - Set via environment variable: var_gpu=yes bash -c "..." + # - Set in CT script: var_gpu="${var_gpu:-no}" + # - Enabled in advanced_settings wizard + # - Configured in app defaults file + if ! is_gpu_app "$APP"; then return 0 fi diff --git a/misc/core.func b/misc/core.func index fb5c088564..9d3ac79dfb 100644 --- a/misc/core.func +++ b/misc/core.func @@ -123,6 +123,7 @@ icons() { CREATING="${TAB}🚀${TAB}${CL}" ADVANCED="${TAB}🧩${TAB}${CL}" FUSE="${TAB}🗂️${TAB}${CL}" + GPU="${TAB}🎮${TAB}${CL}" HOURGLASS="${TAB}⏳${TAB}" }