Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Script]: AppName.sh

CanbiZ edited this pageDec 1, 2025 ·1 revision

🚀Application Container Scripts (ct/AppName.sh)

Modern Guide to Creating LXC Container Installation Scripts

Updated: December 2025
Context: Fully integrated with build.func, advanced_settings wizard, and defaults system
Example Used:/ct/pihole.sh,/ct/docker.sh


📋 Table of Contents


Overview

Purpose

Container scripts (ct/AppName.sh) areentry points for creating LXC containers with specific applications pre-installed. They:

  1. Define container defaults (CPU, RAM, disk, OS)
  2. Call the main build orchestrator (build.func)
  3. Implement application-specific update mechanisms
  4. Provide user-facing success messages

Execution Context

Proxmox Host    ↓ct/AppName.sh sourced (runs as root on host)    ↓build.func: Creates LXC container + runs install script inside    ↓install/AppName-install.sh (runs inside container)    ↓Container ready with app installed

Key Integration Points

  • build.func - Main orchestrator (container creation, storage, variable management)
  • install.func - Container-specific setup (OS update, package management)
  • tools.func - Tool installation helpers (repositories, GitHub releases)
  • core.func - UI/messaging functions (colors, spinners, validation)
  • error_handler.func - Error handling and signal management

Architecture & Flow

Container Creation Flow

START: bash ct/pihole.sh  ↓[1] Set APP, var_*, defaults  ↓[2] header_info() → Display ASCII art  ↓[3] variables() → Parse arguments & load build.func  ↓[4] color() → Setup ANSI codes  ↓[5] catch_errors() → Setup trap handlers  ↓[6] install_script() → Show mode menu (5 options)  ↓  ├─ INSTALL_MODE="0" (Default)  ├─ INSTALL_MODE="1" (Advanced - 19-step wizard)  ├─ INSTALL_MODE="2" (User Defaults)  ├─ INSTALL_MODE="3" (App Defaults)  └─ INSTALL_MODE="4" (Settings Menu)  ↓[7] advanced_settings() → Collect user configuration (if mode=1)  ↓[8] start() → Confirm or re-edit settings  ↓[9] build_container() → Create LXC + execute install script  ↓[10] description() → Set container description  ↓[11] SUCCESS → Display access URL  ↓END

Default Values Precedence

Priority 1 (Highest): Environment Variables (var_cpu, var_ram, etc.)Priority 2: App-Specific Defaults (/defaults/AppName.vars)Priority 3: User Global Defaults (/default.vars)Priority 4 (Lowest): Built-in Defaults (in build.func)

File Structure

Minimal ct/AppName.sh Template

#!/usr/bin/env bash                          # [1] Shebang                                             # [2] Copyright/Licensesource <(curl -s .../misc/build.func)        # [3] Import functions                                             # [4] APP metadataAPP="AppName"                                # [5] Default valuesvar_tags="tag1;tag2"var_cpu="2"var_ram="2048"...header_info "$APP"                           # [6] Display headervariables                                    # [7] Process argumentscolor                                        # [8] Setup colorscatch_errors                                 # [9] Setup error handlingfunction update_script() { ... }             # [10] Update function (optional)start                                        # [11] Launch container creationbuild_containerdescriptionmsg_ok "Completed Successfully!\n"

Complete Script Template

1. File Header & Imports

#!/usr/bin/env bash# Copyright (c) 2021-2025 community-scripts ORG# Author: YourUsername# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE# Source: https://github.com/example/project# Import main orchestratorsource<(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)

⚠️ IMPORTANT: Before opening a PR, change URL tocommunity-scripts repo!

2. Application Metadata

# Application ConfigurationAPP="ApplicationName"var_tags="tag1;tag2;tag3"# Max 3-4 tags, no spaces, semicolon-separated# Container Resourcesvar_cpu="2"# CPU coresvar_ram="2048"# RAM in MBvar_disk="10"# Disk in GB# Container Type & OSvar_os="debian"# Options: alpine, debian, ubuntuvar_version="12"# Alpine: 3.20+, Debian: 11-13, Ubuntu: 20.04+var_unprivileged="1"# 1=unprivileged (secure), 0=privileged (rarely needed)

Variable Naming Convention:

  • Variables exposed to user:var_* (e.g.,var_cpu,var_hostname,var_ssh)
  • Internal variables: lowercase (e.g.,container_id,app_version)

3. Display & Initialization

# Display header ASCII artheader_info"$APP"# Process command-line arguments and load configurationvariables# Setup ANSI color codes and formattingcolor# Initialize error handling (trap ERR, EXIT, INT, TERM)catch_errors

4. Update Function (Highly Recommended)

functionupdate_script() {  header_info# Always start with these checks  check_container_storage  check_container_resources# Verify app is installedif [[!-d /opt/appname ]];then    msg_error"No${APP} Installation Found!"exitfi# Get latest version from GitHub  RELEASE=$(curl -fsSL https://api.github.com/repos/user/repo/releases/latest| \    grep"tag_name"| awk'{print substr($2, 2, length($2)-3)}')# Compare with saved versionif [[!-f /opt/${APP}_version.txt ]]|| [["${RELEASE}"!="$(cat /opt/${APP}_version.txt)" ]];then    msg_info"Updating${APP} to v${RELEASE}"# Backup user data    cp -r /opt/appname /opt/appname-backup# Perform updatecd /opt    wget -q"https://github.com/user/repo/releases/download/v${RELEASE}/app-${RELEASE}.tar.gz"    tar -xzf app-${RELEASE}.tar.gz# Restore user data    cp /opt/appname-backup/config/* /opt/appname/config/# Cleanup    rm -rf app-${RELEASE}.tar.gz /opt/appname-backup# Save new versionecho"${RELEASE}"> /opt/${APP}_version.txt        msg_ok"Updated${APP} to v${RELEASE}"else    msg_ok"No update required.${APP} is already at v${RELEASE}."fiexit}

5. Script Launch

# Start the container creation workflowstart# Build the container with selected configurationbuild_container# Set container description/notes in Proxmox UIdescription# Display success messagemsg_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}:8080${CL}"

Function Reference

Core Functions (From build.func)

variables()

Purpose: Initialize container variables, load user arguments, setup orchestration

Triggered by: Called automatically at script start

Behavior:

  1. Parse command-line arguments (if any)
  2. Generate random UUID for session tracking
  3. Load container storage from Proxmox
  4. Initialize application-specific defaults
  5. Setup SSH/environment configuration

Example Output:

Setting up variables...Container ID: 100Storage: local-lvmInstall method: Default

start()

Purpose: Launch the container creation menu with 5 installation modes

Triggered by: Called just beforebuild_container()

Menu Options:

1. Default Installation (Quick setup, predefined settings)2. Advanced Installation (19-step wizard with full control)3. User Defaults (Load ~/.community-scripts/default.vars)4. App Defaults (Load /defaults/AppName.vars)5. Settings Menu (Interactive mode selection)

User Flow:

Select installation mode:1) Default2) Advanced3) User Defaults4) App Defaults5) Settings MenuEnter choice: 2

build_container()

Purpose: Main orchestrator for LXC container creation

Operations:

  1. Validates all variables
  2. Creates LXC container viapct create
  3. Executesinstall/AppName-install.sh inside container
  4. Monitors installation progress
  5. Handles errors and rollback on failure

Exit Codes:

  • 0 - Success
  • 1-255 - Various error conditions (see error_handler.func)

description()

Purpose: Set container description/notes visible in Proxmox UI

Format:

AppNameIP: [IP]Version: [Version]Tags: [Tags]

header_info()

Purpose: Display ASCII art header for application

Sources:

  • Tries/usr/local/community-scripts/headers/ct/appname (cached)
  • Falls back to remote fetch from GitHub
  • Returns silently if not found

Advanced Features

1. Integration with Defaults System

Save App Defaults After Installation

# At end of install script, after successful setup:maybe_offer_save_app_defaults# Output:# "Save these settings as App Defaults for AppName? (Y/n)"# Yes → Saves to /defaults/appname.vars# No → Skips saving

Load Saved Defaults During Container Creation

# In ct/AppName.sh, user selects "App Defaults" mode# Automatically loads /defaults/appname.vars# Container uses previously saved configuration

2. Custom Configuration Menus

If your app has additional setup beyond standard vars:

# In ct/AppName.sh, after variables()custom_app_settings() {  CONFIGURE_DB=$(whiptail --title"Database Setup" \    --yesno"Would you like to configure a custom database?" 8 60)if [[$?-eq 0 ]];then    DB_HOST=$(whiptail --inputbox"Database Host:" 8 603>&11>&22>&3)    DB_PORT=$(whiptail --inputbox"Database Port:" 8 60"3306"3>&11>&22>&3)fi}custom_app_settings

3. Version Tracking

Save installed version for update checks:

# In install script, after successful app download:RELEASE="1.2.3"echo"${RELEASE}"> /opt/${APP}_version.txt# In update function, compare:CURRENT=$(cat /opt/${APP}_version.txt2>/dev/null)LATEST=$(curl -fsSL https://api.github.com/repos/user/repo/releases/latest| jq -r'.tag_name')if [["$LATEST"!="$CURRENT" ]];thenecho"Update available:$CURRENT$LATEST"fi

4. Health Check Functions

Add custom validation:

functionhealth_check() {  header_infoif [[!-d /opt/appname ]];then    msg_error"Application not found!"exit 1fiif! systemctl is-active --quiet appname;then    msg_error"Application service not running"exit 1fi    msg_ok"Health check passed"}# Called via: bash ct/appname.sh health_check

Real Examples

Example 1: Simple Web App (Debian-based)

#!/usr/bin/env bashsource<(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)APP="Homarr"var_tags="dashboard;homepage"var_cpu="2"var_ram="1024"var_disk="5"var_os="debian"var_version="12"var_unprivileged="1"header_info"$APP"variablescolorcatch_errorsfunctionupdate_script() {  header_info  check_container_storage  check_container_resourcesif [[!-d /opt/homarr ]];then    msg_error"No${APP} Installation Found!"exitfi    RELEASE=$(curl -fsSL https://api.github.com/repos/ajnart/homarr/releases/latest| grep"tag_name"| awk'{print substr($2, 3, length($2)-4)}')if [[!-f /opt/${APP}_version.txt ]]|| [["${RELEASE}"!="$(cat /opt/${APP}_version.txt)" ]];then    msg_info"Updating${APP} to v${RELEASE}"    systemctl stop homarrcd /opt/homarr    wget -q"https://github.com/ajnart/homarr/releases/download/v${RELEASE}/docker-compose.yml"    docker-compose up -decho"${RELEASE}"> /opt/${APP}_version.txt    msg_ok"Updated${APP} to v${RELEASE}"else    msg_ok"No update required.${APP} is already at v${RELEASE}."fiexit}startbuild_containerdescriptionmsg_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}:5100${CL}"

Example 2: Database App (Alpine-based)

#!/usr/bin/env bashsource<(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)APP="PostgreSQL"var_tags="database;sql"var_cpu="4"var_ram="4096"var_disk="20"var_os="alpine"var_version="3.20"var_unprivileged="1"header_info"$APP"variablescolorcatch_errorsfunctionupdate_script() {  header_info  check_container_storageif!command -v psql&>/dev/null;then    msg_error"PostgreSQL not installed!"exitfi    msg_info"Updating Alpine packages"  apk update  apk upgrade  msg_ok"Updated Alpine packages"exit}startbuild_containerdescriptionmsg_ok"Completed Successfully!\n"echo -e"${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"echo -e"${INFO}${YW} Connect using:${CL}"echo -e"${TAB}${GATEWAY}${BGN}psql -h${IP} -U postgres${CL}"

Troubleshooting

Container Creation Fails

Symptom:pct create exits with error code 209

Causes:

  1. CTID already exists:pct list shows duplicate
  2. Storage full: Check storage space
  3. Network template unavailable

Solution:

# Check existing containerspct list| grep CTID# Remove conflicting containerpct destroy CTID# Retry ct/AppName.sh

Update Function Doesn't Detect New Version

Symptom: Update available but script says "already at latest"

Causes:

  1. Version file missing:/opt/AppName_version.txt
  2. GitHub API rate limit exceeded
  3. Release tag format mismatch

Debug:

# Check version filecat /opt/AppName_version.txt# Test GitHub APIcurl -fsSL https://api.github.com/repos/user/repo/releases/latest| grep tag_name# Inside containerbash ct/appname.sh update_script

Header ASCII Art Not Displaying

Symptom: Container script runs but no header shown

Causes:

  1. Header file not in repository
  2. Caching issue

Solution:

# Create header file manuallymkdir -p /usr/local/community-scripts/headers/ctecho"Your ASCII art here"> /usr/local/community-scripts/headers/ct/appname# Or remove cache to force re-downloadrm -f /usr/local/community-scripts/headers/ct/appname

Contribution Checklist

Before submitting a PR:

Script Structure

  • Shebang is#!/usr/bin/env bash
  • Importsbuild.func from community-scripts repo (not personal fork)
  • Copyright header with author and source URL
  • APP variable matches filename
  • var_tags are semicolon-separated (no spaces)

Default Values

  • var_cpu set appropriately (2-4 for most apps)
  • var_ram set appropriately (1024-4096 MB minimum)
  • var_disk sufficient for app + data (5-20 GB)
  • var_os is realistic (Alpine if lightweight, Debian/Ubuntu otherwise)
  • var_unprivileged="1" unless app absolutely needs privileges

Functions

  • update_script() implemented (or marked as unavailable)
  • Update function checks if app installed
  • Update function checks for new version
  • Update function performs cleanup after update
  • Proper error handling withmsg_error on failure

Output

  • Success message displayed with access URL
  • URL format:http://IP:PORT/path (if web-based)
  • Usesmsg_ok,msg_info,msg_error for feedback

Testing

  • Script tested with default installation
  • Script tested with advanced (19-step) installation
  • Update function tested on existing installation
  • Error handling tested (invalid settings, network issues)

Best Practices

✅ DO:

  1. Use meaningful defaults

    var_cpu="2"# ✅ Good: Typical workloadvar_cpu="128"# ❌ Bad: Unrealistic
  2. Implement version tracking

    echo"${RELEASE}"> /opt/${APP}_version.txt# ✅ Good# ❌ Bad: No version tracking
  3. Handle edge cases

    if [[!-f /opt/${APP}_version.txt ]];then  msg_info"First installation detected"fi
  4. Use proper messaging

    msg_info"Updating..."# ✅ Good: Clear statusecho"Updating..."# ❌ Bad: No formatting

❌ DON'T:

  1. Hardcode versions

    RELEASE="1.2.3"# ❌ Bad: Won't auto-update
  2. Use custom color codes

    echo -e"\033[32mSuccess"# ❌ Bad: Use $GN instead
  3. Forget error handling

    wget file.zip# ❌ Bad: No error checkif! wget -q file.zip;then# ✅ Good  msg_error"Download failed"fi
  4. Leave temporary files

    rm -rf /opt/file.zip# ✅ Always cleanup

Related Documentation


Last Updated: December 2025
Compatibility: ProxmoxVED with build.func v3+
Questions? Open an issue in the repository

Clone this wiki locally


[8]ページ先頭

©2009-2025 Movatter.jp