Table of Contents
- Install.func Wiki
- 📋 Table of Contents
- Overview
- Initialization & Dependencies
- Network & Connectivity Functions
- OS Configuration Functions
- SSH & MOTD Configuration
- Installation Workflow
- Best Practices
- 1. Always Initialize First
- 2. Check Network Early
- 3. Use Retry Logic
- 4. Separate Concerns
- 5. Capture Environment
- Debugging
- Contributing
- Notes
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
- Initialization & Dependencies
- Network & Connectivity Functions
- OS Configuration Functions
- Installation Workflow
- Best Practices
- Debugging
- 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
# 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 enabledVERBOSE- 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:
- Verify network connectivity via
hostname -I - Retry up to RETRY_NUM times with RETRY_EVERY second delays
- Remove Python EXTERNALLY-MANAGED marker (allows pip)
- Disable systemd-networkd-wait-online.service (speeds up boot)
- 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:
-
IPv4 Connectivity (tests 3 public DNS servers):
- 1.1.1.1 (Cloudflare)
- 8.8.8.8 (Google)
- 9.9.9.9 (Quad9)
-
IPv6 Connectivity (tests 3 public DNS servers):
- 2606:4700:4700::1111 (Cloudflare)
- 2001:4860:4860::8888 (Google)
- 2620:fe::fe (Quad9)
-
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:
- Display info message
- Optional: Configure APT caching proxy
- Run
apt-get update(index refresh) - Run
apt-get dist-upgrade(system upgrade) - Remove Python EXTERNALLY-MANAGED restrictions
- Source tools.func for additional setup
- 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:
- Set TERM environment variable for better terminal support
- Gather OS information (name, version, IP)
- Create
/etc/profile.d/00_lxc-details.shwith container details script - 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