Skip to content

[core]: install.func

CanbiZ edited this page Dec 1, 2025 · 1 revision

Install.func Wiki

Container installation workflow orchestration module providing network setup, OS configuration, connectivity verification, and installation mechanics for applications deployed inside LXC containers.


📋 Table of Contents


Overview

Install.func provides container-internal installation mechanics:

  • ✅ Network connectivity verification (IPv4/IPv6)
  • ✅ OS updates and package management
  • ✅ DNS resolution validation
  • ✅ System optimization (disable wait-online service)
  • ✅ SSH and MOTD configuration
  • ✅ Container customization (auto-login, update script)
  • ✅ Comprehensive error handling with signal traps
  • ✅ Integration with core.func and error_handler.func

Execution Context

Proxmox Host                LXC Container
──────────────────────────────────────────
pct create CTID ...
    ↓
Boot container
    ↓
pct exec CTID bash /tmp/install.sh
    ↓
[Execution within container]
    └─→ install.func functions execute
        └─→ verb_ip6()
        └─→ setting_up_container()
        └─→ network_check()
        └─→ update_os()
        └─→ etc.

Initialization & Dependencies

Module Dependencies

# Install.func requires two prerequisites
if ! command -v curl >/dev/null 2>&1; then
  apt-get update >/dev/null 2>&1
  apt-get install -y curl >/dev/null 2>&1
fi

# Source core functions (colors, formatting, messages)
source <(curl -fsSL https://git.community-scripts.org/.../core.func)

# Source error handling (traps, signal handlers)
source <(curl -fsSL https://git.community-scripts.org/.../error_handler.func)

# Initialize both modules
load_functions      # Sets up colors, icons, defaults
catch_errors        # Configures ERR, EXIT, INT, TERM traps

Environment Variables Passed from Host

These variables are passed by build.func via pct set and environment:

Variable Source Purpose
VERBOSE Build config Show all output (yes/no)
PASSWORD User input Root password (blank = auto-login)
DISABLEIPV6 Advanced settings Disable IPv6 (yes/no)
SSH_ROOT Advanced settings Enable SSH root access
CACHER Config Use APT cache proxy (yes/no)
CACHER_IP Config APT cache IP address
APPLICATION App script App display name
app App script Normalized app name (lowercase)
RETRY_NUM core.func Retry attempts (default: 10)
RETRY_EVERY core.func Retry interval in seconds (default: 3)

Network & Connectivity Functions

verb_ip6()

Purpose: Configures IPv6 based on DISABLEIPV6 variable and sets verbose mode.

Signature:

verb_ip6()

Parameters: None

Returns: No explicit return value (configures system)

Environment Requirements:

  • DISABLEIPV6 - Set to "yes" to disable IPv6, "no" to keep enabled
  • VERBOSE - Controls output verbosity via set_std_mode()

Behavior:

# If DISABLEIPV6=yes:
echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
sysctl -p  # Apply immediately

# If DISABLEIPV6=no (default):
# No changes (IPv6 remains enabled)

Usage Examples:

# Example 1: Disable IPv6 (for security/simplicity)
DISABLEIPV6="yes"
VERBOSE="no"
verb_ip6
# Result: IPv6 disabled, change persisted

# Example 2: Keep IPv6 enabled (default)
DISABLEIPV6="no"
verb_ip6
# Result: IPv6 operational, no configuration

# Example 3: Verbose mode
VERBOSE="yes"
verb_ip6
# Output: Shows sysctl configuration commands

setting_up_container()

Purpose: Verifies network connectivity and performs initial OS configuration for Debian/Ubuntu containers.

Signature:

setting_up_container()

Parameters: None

Returns: 0 on success; exits with code 1 if network unavailable after retries

Environment Requirements:

  • RETRY_NUM - Max attempts (default: 10)
  • RETRY_EVERY - Seconds between retries (default: 3)

Operations:

  1. Verify network connectivity via hostname -I
  2. Retry up to RETRY_NUM times with RETRY_EVERY second delays
  3. Remove Python EXTERNALLY-MANAGED marker (allows pip)
  4. Disable systemd-networkd-wait-online.service (speeds up boot)
  5. Display network information

Implementation Pattern:

setting_up_container() {
  msg_info "Setting up Container OS"

  # Network availability loop
  for ((i = RETRY_NUM; i > 0; i--)); do
    if [ "$(hostname -I)" != "" ]; then
      break
    fi
    echo 1>&2 -en "${CROSS}${RD} No Network! "
    sleep $RETRY_EVERY
  done

  # Check final state
  if [ "$(hostname -I)" = "" ]; then
    echo 1>&2 -e "\n${CROSS}${RD} No Network After $RETRY_NUM Tries${CL}"
    exit 1
  fi

  # Python pip support
  rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED

  # Speed up boot (disable wait service)
  systemctl disable -q --now systemd-networkd-wait-online.service

  msg_ok "Set up Container OS"
  msg_ok "Network Connected: ${BL}$(hostname -I)${CL}"
}

Usage Examples:

# Example 1: Immediate network availability
RETRY_NUM=10
RETRY_EVERY=3
setting_up_container
# Output:
# ℹ️  Setting up Container OS
# ✔️  Set up Container OS
# ✔️  Network Connected: 10.0.3.50

# Example 2: Delayed network (waits 6 seconds)
# Script retries 2 times before succeeding
# (each retry waits 3 seconds)

# Example 3: No network
# Script waits 30 seconds total (10 x 3)
# Then exits with: "No Network After 10 Tries"

network_check()

Purpose: Comprehensive network diagnostics for both IPv4 and IPv6, including DNS validation for Git/GitHub.

Signature:

network_check()

Parameters: None

Returns: 0 on success; exits with code 1 on critical DNS failure

Checks Performed:

  1. IPv4 Connectivity (tests 3 public DNS servers):

    • 1.1.1.1 (Cloudflare)
    • 8.8.8.8 (Google)
    • 9.9.9.9 (Quad9)
  2. IPv6 Connectivity (tests 3 public DNS servers):

    • 2606:4700:4700::1111 (Cloudflare)
    • 2001:4860:4860::8888 (Google)
    • 2620:fe::fe (Quad9)
  3. DNS Resolution (validates Git-related domains):

    • github.com
    • raw.githubusercontent.com
    • api.github.com
    • git.community-scripts.org

Output Format:

✔️  IPv4 Internet Connected
✔️  IPv6 Internet Connected
✔️  Git DNS: github.com:✔️ raw.githubusercontent.com:✔️ ...

Error Handling:

# If both IPv4 and IPv6 fail:
# Prompts user: "No Internet detected, would you like to continue anyway?"
# If user says no: Exits
# If user says yes: Shows warning "Expect Issues Without Internet"

# If DNS fails for GitHub:
# Calls fatal() - exits immediately with error

Implementation Pattern:

network_check() {
  set +e
  trap - ERR

  ipv4_connected=false
  ipv6_connected=false

  # IPv4 test
  if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ...; then
    msg_ok "IPv4 Internet Connected"
    ipv4_connected=true
  else
    msg_error "IPv4 Internet Not Connected"
  fi

  # IPv6 test
  if ping6 -c 1 -W 1 2606:4700:4700::1111 &>/dev/null || ...; then
    msg_ok "IPv6 Internet Connected"
    ipv6_connected=true
  else
    msg_error "IPv6 Internet Not Connected"
  fi

  # DNS checks for GitHub domains
  GIT_HOSTS=("github.com" "raw.githubusercontent.com" "api.github.com" "git.community-scripts.org")
  for HOST in "${GIT_HOSTS[@]}"; do
    RESOLVEDIP=$(getent hosts "$HOST" | awk '{ print $1 }' | head -n1)
    if [[ -z "$RESOLVEDIP" ]]; then
      DNS_FAILED=true
    fi
  done

  if [[ "$DNS_FAILED" == true ]]; then
    fatal "$GIT_STATUS"  # Exit on critical DNS failure
  fi

  set -e
  trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
}

Usage Examples:

# Example 1: Good connectivity (all checks pass)
network_check
# Output:
# ✔️  IPv4 Internet Connected
# ✔️  IPv6 Internet Connected
# ✔️  Git DNS: github.com:✔️ ...

# Example 2: IPv6 unavailable but IPv4 OK
network_check
# Output:
# ✔️  IPv4 Internet Connected
# ✖️  IPv6 Internet Not Connected
# ✔️  Git DNS checks OK

# Example 3: No internet at all
network_check
# Prompts: "No Internet detected, would you like to continue anyway?"
# User: y
# Output: ⚠️  Expect Issues Without Internet

OS Configuration Functions

update_os()

Purpose: Updates Debian/Ubuntu OS packages and loads additional tools library.

Signature:

update_os()

Parameters: None

Returns: No explicit return value (updates system)

Operations:

  1. Display info message
  2. Optional: Configure APT caching proxy
  3. Run apt-get update (index refresh)
  4. Run apt-get dist-upgrade (system upgrade)
  5. Remove Python EXTERNALLY-MANAGED restrictions
  6. Source tools.func for additional setup
  7. Display success message

APT Caching Configuration (if CACHER=yes):

# Configure apt-proxy-detect.sh
/etc/apt/apt.conf.d/00aptproxy

# Script detects local APT cacher and routes through it
# Falls back to DIRECT if unavailable

Implementation Pattern:

update_os() {
  msg_info "Updating Container OS"

  # Optional: Setup APT cacher
  if [[ "$CACHER" == "yes" ]]; then
    echo "Acquire::http::Proxy-Auto-Detect \"/usr/local/bin/apt-proxy-detect.sh\";" > /etc/apt/apt.conf.d/00aptproxy

    cat > /usr/local/bin/apt-proxy-detect.sh <<'EOF'
#!/bin/bash
if nc -w1 -z "${CACHER_IP}" 3142; then
  echo -n "http://${CACHER_IP}:3142"
else
  echo -n "DIRECT"
fi
EOF
    chmod +x /usr/local/bin/apt-proxy-detect.sh
  fi

  # Update system
  $STD apt-get update
  $STD apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade

  # Python support
  rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED

  # Load additional tools library
  source <(curl -fsSL https://git.community-scripts.org/.../tools.func)

  msg_ok "Updated Container OS"
}

Usage Examples:

# Example 1: Standard update
update_os
# Output: Updates all packages silently (unless VERBOSE=yes)

# Example 2: With APT cacher
CACHER="yes"
CACHER_IP="192.168.1.100"
update_os
# Uses cache proxy for faster package downloads

# Example 3: Verbose output
VERBOSE="yes"
update_os
# Shows all apt-get operations in detail

SSH & MOTD Configuration

motd_ssh()

Purpose: Configures Message of the Day and enables SSH root access if configured.

Signature:

motd_ssh()

Parameters: None

Returns: No explicit return value (configures system)

Operations:

  1. Set TERM environment variable for better terminal support
  2. Gather OS information (name, version, IP)
  3. Create /etc/profile.d/00_lxc-details.sh with container details script
  4. Optionally enable root SSH access if SSH_ROOT=yes

MOTD Script Content:

echo -e ""
echo -e "${BOLD}${YW}${APPLICATION} LXC Container - DEV Repository${CL}"
echo -e "${RD}WARNING: This is a DEVELOPMENT version (ProxmoxVED). Do NOT use in production!${CL}"
echo -e "${YW} OS: ${GN}${OS_NAME} - Version: ${OS_VERSION}${CL}"
echo -e "${YW} Hostname: ${GN}$(hostname)${CL}"
echo -e "${YW} IP Address: ${GN}$(hostname -I | awk '{print $1}')${CL}"
echo -e "${YW} Repository: ${GN}https://github.com/community-scripts/ProxmoxVED${CL}"
echo ""

SSH Configuration (if SSH_ROOT=yes):

sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config
systemctl restart sshd

Installation Workflow

Typical Installation Sequence

#!/bin/bash
# Inside container during installation

source <(curl -fsSL .../core.func)
source <(curl -fsSL .../error_handler.func)
load_functions
catch_errors

# Step 1: Network setup
verb_ip6
setting_up_container
network_check

# Step 2: System update
update_os

# Step 3: SSH and MOTD
motd_ssh

# Step 4: Install application (app-specific)
# ... application installation steps ...

# Step 5: Create update script
customize

Best Practices

1. Always Initialize First

#!/bin/bash
set -Eeuo pipefail

if ! command -v curl >/dev/null 2>&1; then
  apt-get update >/dev/null 2>&1
  apt-get install -y curl >/dev/null 2>&1
fi

source <(curl -fsSL .../core.func)
source <(curl -fsSL .../error_handler.func)
load_functions
catch_errors

2. Check Network Early

setting_up_container    # Verify network available
network_check          # Validate connectivity and DNS
update_os              # Proceed with updates

# If network fails, exit immediately
# Don't waste time on installation

3. Use Retry Logic

# Built into setting_up_container():
for ((i = RETRY_NUM; i > 0; i--)); do
  if [ "$(hostname -I)" != "" ]; then
    break
  fi
  sleep $RETRY_EVERY
done

# Tolerates temporary network delay

4. Separate Concerns

# Network setup
verb_ip6
setting_up_container
network_check

# System updates
update_os

# Configuration
motd_ssh

# Application-specific
# ... app installation ...

5. Capture Environment

# Pass these from build.func:
VERBOSE="yes"              # Show all output
DISABLEIPV6="no"           # Keep IPv6
SSH_ROOT="yes"             # Enable SSH
APPLICATION="Jellyfin"     # App name
CACHER="no"                # No APT cache

Debugging

Enable Verbose Output

VERBOSE="yes" pct exec CTID bash /tmp/install.sh
# Shows all commands and output

Check Network Status Inside Container

pct exec CTID hostname -I
pct exec CTID ping -c 1 1.1.1.1
pct exec CTID getent hosts github.com

View Installation Log

# From container
cat /root/install-*.log

# Or from host (if logs mounted)
tail -100 /var/log/community-scripts/install-*.log

Contributing

Adding New Network Checks

network_check() {
  # ... existing checks ...

  # Add new check:
  if ! getent hosts newhost.example.com &>/dev/null; then
    msg_warn "Unable to resolve newhost.example.com"
  fi
}

Extending OS Configuration

# Add to update_os():
update_os() {
  # ... existing updates ...

  # Add new capability:
  $STD apt-get install -y some-package
  msg_ok "Additional package installed"
}

Notes

  • Install.func executes inside the container (not on Proxmox host)
  • Network connectivity is critical - checked early and thoroughly
  • OS updates are required before application installation
  • IPv6 is configurable but enabled by default
  • SSH and MOTD are informational - help with container management

Clone this wiki locally