ProxmoxVED/docs/install/DETAILED_GUIDE.md
CanbiZ 1e5627ea19 Restructure and relocate documentation files
Removed outdated documentation files from docs/. Added new detailed guides to ct/ and install/ directories. Updated README.md to reflect new navigation, learning paths, and documentation structure. Relocated system guides and technical references to settings/ and install/ subdirectories for improved organization.
2025-12-01 12:29:24 +01:00

13 KiB

🛠️ 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

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

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

# 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

File Structure

Minimal install/AppName-install.sh Template

#!/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

#!/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/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

msg_info "Installing Dependencies"
$STD apt-get install -y \
  curl \
  wget \
  git \
  nano \
  build-essential \
  libssl-dev \
  python3-dev
msg_ok "Installed Dependencies"

Phase 3: Tool Setup (Using tools.func)

# Setup specific tool versions
NODE_VERSION="22" setup_nodejs
PHP_VERSION="8.4" setup_php
PYTHON_VERSION="3.12" setup_uv

Phase 4: Application Download & Setup

# Download 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)}')

wget -q "https://github.com/user/repo/releases/download/v${RELEASE}/app-${RELEASE}.tar.gz"
cd /opt
tar -xzf app-${RELEASE}.tar.gz
rm -f app-${RELEASE}.tar.gz

Phase 5: Configuration Files

# 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;
}
EOF

# Using sed for replacements
sed -i -e "s|^DB_HOST=.*|DB_HOST=localhost|" \
       -e "s|^DB_USER=.*|DB_USER=appuser|" \
       /opt/appname/.env

Phase 6: Database Setup (If Needed)

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 <<EOF
CREATE DATABASE ${DB_NAME};
CREATE USER '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASS}';
GRANT ALL PRIVILEGES ON ${DB_NAME}.* TO '${DB_USER}'@'localhost';
FLUSH PRIVILEGES;
EOF

msg_ok "Database setup complete"

Phase 7: Permission & Ownership

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/*/.*

msg_ok "Permissions set"

Phase 8: Service Configuration

# 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

# Essential for update detection
echo "${RELEASE}" > /opt/${APP}_version.txt

# Or with additional metadata
cat > /opt/${APP}_version.txt <<EOF
Version: ${RELEASE}
InstallDate: $(date)
InstallMethod: ${METHOD}
EOF

Phase 10: Final Setup & Cleanup

# Display MOTD and enable autologin
motd_ssh

# Final customization
customize

# Clean up package manager cache
msg_info "Cleaning up"
apt-get -y autoremove
apt-get -y autoclean
msg_ok "Cleaned"

# Or for Alpine
apk cache clean
rm -rf /var/cache/apk/*

# System cleanup
cleanup_lxc

Installation Phases

Phase 1: Container OS Setup

  • Network interface brought up and configured
  • Internet connectivity verified
  • Package lists updated
  • All OS packages upgraded to latest versions

Phase 2: Base Dependencies

msg_info "Installing Base Dependencies"
$STD apt-get install -y \
  curl wget git nano build-essential
msg_ok "Installed Base Dependencies"

Phase 3: Tool Installation

NODE_VERSION="22" setup_nodejs
PHP_VERSION="8.4" setup_php

Phase 4: Application Setup

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.tar.gz"

Phase 5: Configuration

Application-specific configuration files and environment setup

Phase 6: Service Registration

Enable and verify systemd services are running


Function Reference

Core Messaging Functions

msg_info(message)

Displays an info message with spinner animation

msg_info "Installing application"
# Output: ⏳ Installing application (with spinning animation)

msg_ok(message)

Displays success message with checkmark

msg_ok "Installation completed"
# Output: ✔️ Installation completed

msg_error(message)

Displays error message and exits

msg_error "Installation failed"
# Output: ✖️ Installation failed

Package Management

$STD Variable

Controls output verbosity

# Silent mode (respects VERBOSE setting)
$STD apt-get install -y nginx

update_os()

Updates OS packages

update_os
# Runs: apt update && apt upgrade

Tool Installation Functions

setup_nodejs()

Installs Node.js with optional global modules

NODE_VERSION="22" setup_nodejs
NODE_VERSION="22" NODE_MODULE="yarn,@vue/cli" setup_nodejs

setup_php()

Installs PHP with optional extensions

PHP_VERSION="8.4" PHP_MODULE="bcmath,curl,gd,intl,redis" setup_php

Other Tools

setup_mariadb     # MariaDB database
setup_mysql       # MySQL database
setup_postgresql  # PostgreSQL
setup_docker      # Docker Engine
setup_composer    # PHP Composer
setup_python      # Python 3
setup_ruby        # Ruby
setup_rust        # Rust

Cleanup Functions

cleanup_lxc()

Comprehensive container cleanup

  • Removes package manager caches
  • Cleans temporary files
  • Clears language package caches
  • Removes systemd journal logs
cleanup_lxc
# Output: ⏳ Cleaning up
#         ✔️ Cleaned

Best Practices

DO:

  1. Always Use $STD for Commands
# ✅ Good: Respects VERBOSE setting
$STD apt-get install -y nginx
  1. Generate Random Passwords Safely
# ✅ Good: Alphanumeric only
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
  1. Check Command Success
# ✅ Good: Verify success
if ! wget -q "https://example.com/file.tar.gz"; then
  msg_error "Download failed"
  exit 1
fi
  1. Set Proper Permissions
# ✅ Good: Explicit permissions
chown -R www-data:www-data /opt/appname
chmod -R 755 /opt/appname
  1. Save Version for Update Checks
# ✅ Good: Version tracked
echo "${RELEASE}" > /opt/${APP}_version.txt
  1. Handle Alpine vs Debian Differences
# ✅ Good: Detect OS
if grep -qi 'alpine' /etc/os-release; then
  apk add package
else
  apt-get install -y package
fi

DON'T:

  1. Hardcode Versions
# ❌ Bad: Won't auto-update
wget https://example.com/app-1.2.3.tar.gz
  1. Use Root Without Password
# ❌ Bad: Security risk
mysql -u root
  1. Forget Error Handling
# ❌ Bad: Silent failures
wget https://example.com/file
tar -xzf file
  1. Leave Temporary Files
# ✅ Always cleanup
rm -rf /opt/app-${RELEASE}.tar.gz

Real Examples

Example 1: Node.js Application

#!/usr/bin/env bash
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"

color
catch_errors
setting_up_container
network_check
update_os

msg_info "Installing Node.js"
NODE_VERSION="22" setup_nodejs
msg_ok "Node.js installed"

msg_info "Installing Application"
cd /opt
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.tar.gz"
tar -xzf app.tar.gz
echo "${RELEASE}" > /opt/app_version.txt
msg_ok "Application installed"

systemctl enable --now app
cleanup_lxc

Example 2: PHP Application with Database

#!/usr/bin/env bash
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"

color
catch_errors
setting_up_container
network_check
update_os

PHP_VERSION="8.4" PHP_MODULE="bcmath,curl,pdo_mysql" setup_php
MARIADB_VERSION="11.4" setup_mariadb

# Database setup
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
mysql -u root <<EOF
CREATE DATABASE appdb;
CREATE USER 'appuser'@'localhost' IDENTIFIED BY '${DB_PASS}';
GRANT ALL ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;
EOF

# App installation
cd /opt
wget -q https://github.com/user/repo/releases/latest/download/app.tar.gz
tar -xzf app.tar.gz

# Configuration
cat > /opt/app/.env <<EOF
DB_HOST=localhost
DB_NAME=appdb
DB_USER=appuser
DB_PASS=${DB_PASS}
EOF

chown -R www-data:www-data /opt/app
systemctl enable --now php-fpm
cleanup_lxc

Troubleshooting

Installation Hangs

Check internet connectivity:

ping -c 1 8.8.8.8

Enable verbose mode:

# In ct/AppName.sh, before running
VERBOSE="yes" bash install/AppName-install.sh

Package Not Found

Update package lists:

apt update
apt-cache search package_name

Service Won't Start

Check logs:

journalctl -u appname -n 50
systemctl status appname

Contribution Checklist

Before submitting a PR:

Structure

  • Shebang is #!/usr/bin/env bash
  • Loads functions from $FUNCTIONS_FILE_PATH
  • Copyright header with author
  • Clear phase comments

Installation

  • setting_up_container called early
  • network_check before downloads
  • update_os before package installation
  • All errors checked properly

Functions

  • Uses msg_info/msg_ok/msg_error for status
  • Uses $STD for command output silencing
  • Version saved to /opt/${APP}_version.txt
  • Proper permissions set

Cleanup

  • motd_ssh called for final setup
  • customize called for options
  • cleanup_lxc called at end

Testing

  • Tested with default settings
  • Tested with advanced (19-step) mode
  • Service starts and runs correctly

Last Updated: December 2025 Compatibility: ProxmoxVED with install.func v3+