# 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](#overview) - [Initialization & Dependencies](#initialization--dependencies) - [Network & Connectivity Functions](#network--connectivity-functions) - [OS Configuration Functions](#os-configuration-functions) - [Installation Workflow](#installation-workflow) - [Best Practices](#best-practices) - [Debugging](#debugging) - [Contributing](#contributing) --- ## 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 ```bash # 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**: ```bash 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**: ```bash # 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**: ```bash # 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**: ```bash 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**: ```bash 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**: ```bash # 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**: ```bash 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**: ```bash # 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**: ```bash 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**: ```bash # 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**: ```bash 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): ```bash # 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**: ```bash 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**: ```bash # 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**: ```bash 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**: ```bash 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): ```bash sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config systemctl restart sshd ``` --- ## Installation Workflow ### Typical Installation Sequence ```bash #!/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** ```bash #!/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** ```bash 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** ```bash # 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** ```bash # Network setup verb_ip6 setting_up_container network_check # System updates update_os # Configuration motd_ssh # Application-specific # ... app installation ... ``` ### 5. **Capture Environment** ```bash # 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 ```bash VERBOSE="yes" pct exec CTID bash /tmp/install.sh # Shows all commands and output ``` ### Check Network Status Inside Container ```bash 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 ```bash # 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 ```bash 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 ```bash # 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