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.
This commit is contained in:
CanbiZ 2025-12-01 12:29:24 +01:00
parent 3998b80194
commit 1e5627ea19
19 changed files with 714 additions and 8933 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,346 +0,0 @@
# 📚 ProxmoxVED Documentation Index
Complete guide to all ProxmoxVED documentation - quickly find what you need.
---
## 🎯 **Quick Navigation by Goal**
### 👤 **I want to...**
**Contribute a new application**
→ Start with: [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md)
→ Then: [UPDATED_APP-ct.md](UPDATED_APP-ct.md) + [UPDATED_APP-install.md](UPDATED_APP-install.md)
**Understand the architecture**
→ Read: [TECHNICAL_REFERENCE.md](TECHNICAL_REFERENCE.md)
→ Then: [misc/README.md](misc/README.md)
**Debug a failed installation**
→ Check: [EXIT_CODES.md](EXIT_CODES.md)
→ Then: [DEV_MODE.md](DEV_MODE.md)
→ See also: [misc/error_handler.func/](misc/error_handler.func/)
**Configure system defaults**
→ Read: [DEFAULTS_SYSTEM_GUIDE.md](DEFAULTS_SYSTEM_GUIDE.md)
**Learn about recent changes**
→ Check: [CHANGELOG_MISC.md](CHANGELOG_MISC.md)
**Develop a function library**
→ Study: [misc/](misc/) documentation
---
## 📂 **Documentation by Category**
### 🏗️ **Project Structure Documentation**
| Directory | Documentation |
|-----------|---|
| **[/ct](ct/)** | Container creation scripts documentation |
| **[/install](install/)** | Installation scripts documentation |
| **[/vm](vm/)** | Virtual machine creation scripts documentation |
| **[/tools](tools/)** | Tools and utilities documentation |
| **[/api](api/)** | API integration documentation |
| **[/misc](misc/)** | Function libraries (9 total) |
### 🚀 **For Contributors**
| Document | Purpose |
|----------|---------|
| [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md) | Complete contribution workflow |
| [UPDATED_APP-ct.md](UPDATED_APP-ct.md) | How to write ct/AppName.sh scripts |
| [UPDATED_APP-install.md](UPDATED_APP-install.md) | How to write install/appname-install.sh scripts |
| [TECHNICAL_REFERENCE.md](TECHNICAL_REFERENCE.md) | System architecture deep-dive |
### 🔧 **For Operators & Developers**
| Document | Purpose |
|----------|---------|
| [EXIT_CODES.md](EXIT_CODES.md) | Complete exit code reference |
| [DEV_MODE.md](DEV_MODE.md) | Debugging and development modes |
| [DEFAULTS_SYSTEM_GUIDE.md](DEFAULTS_SYSTEM_GUIDE.md) | Configuration and defaults system |
| [CHANGELOG_MISC.md](CHANGELOG_MISC.md) | Recent changes and updates |
### 📚 **Function Library Documentation** (9 libraries)
**Core Functions**:
- [build.func/](misc/build.func/) - Container creation orchestrator (7 files)
- [core.func/](misc/core.func/) - Utility functions (5 files)
- [error_handler.func/](misc/error_handler.func/) - Error handling (5 files)
- [api.func/](misc/api.func/) - Proxmox API integration (5 files)
**Installation Functions**:
- [install.func/](misc/install.func/) - Container setup (5 files)
- [tools.func/](misc/tools.func/) - Package and tool installation (6 files)
**Alpine Linux Functions**:
- [alpine-install.func/](misc/alpine-install.func/) - Alpine setup (5 files)
- [alpine-tools.func/](misc/alpine-tools.func/) - Alpine tools (5 files)
**VM Functions**:
- [cloud-init.func/](misc/cloud-init.func/) - VM provisioning (5 files)
---
## 📋 **All Documentation Files**
### Root Level (13 main files + 6 directory structures)
```
/docs/
├─ CONTRIBUTION_GUIDE.md (2800+ lines) Contributing guide
├─ UPDATED_APP-ct.md (900+ lines) ct script guide
├─ UPDATED_APP-install.md (1000+ lines) install script guide
├─ TECHNICAL_REFERENCE.md (600+ lines) Architecture reference
├─ DEFAULTS_SYSTEM_GUIDE.md (700+ lines) Configuration guide
├─ CHANGELOG_MISC.md (450+ lines) Change history
├─ EXIT_CODES.md (400+ lines) Exit codes reference
├─ DEV_MODE.md (400+ lines) Dev mode guide
├─ INDEX.md (This file) Documentation index
├─ ct/ README for container scripts ★ NEW
├─ install/ README for installation scripts ★ NEW
├─ vm/ README for VM scripts ★ NEW
├─ tools/ README for tools & utilities ★ NEW
├─ api/ README for API integration ★ NEW
└─ misc/ Function libraries (detailed below)
```
### Project Structure Mirror with Docs (48 files in misc/)
Each top-level project directory (`/ct`, `/install`, `/vm`, `/tools`, `/api`) has a documentation companion in `/docs/` with a README explaining that section.
### misc/ Subdirectories (48 files)
```
/docs/misc/
├─ README.md (comprehensive overview)
├─ build.func/ (7 files)
│ ├─ README.md
│ ├─ BUILD_FUNC_FLOWCHART.md
│ ├─ BUILD_FUNC_ARCHITECTURE.md
│ ├─ BUILD_FUNC_ENVIRONMENT_VARIABLES.md
│ ├─ BUILD_FUNC_FUNCTIONS_REFERENCE.md
│ ├─ BUILD_FUNC_EXECUTION_FLOWS.md
│ └─ BUILD_FUNC_USAGE_EXAMPLES.md
├─ core.func/ (5 files)
│ ├─ README.md
│ ├─ CORE_FLOWCHART.md
│ ├─ CORE_FUNCTIONS_REFERENCE.md
│ ├─ CORE_INTEGRATION.md
│ └─ CORE_USAGE_EXAMPLES.md
├─ error_handler.func/ (5 files)
│ ├─ README.md
│ ├─ ERROR_HANDLER_FLOWCHART.md
│ ├─ ERROR_HANDLER_FUNCTIONS_REFERENCE.md
│ ├─ ERROR_HANDLER_INTEGRATION.md
│ └─ ERROR_HANDLER_USAGE_EXAMPLES.md
├─ api.func/ (5 files)
│ ├─ README.md
│ ├─ API_FLOWCHART.md
│ ├─ API_FUNCTIONS_REFERENCE.md
│ ├─ API_INTEGRATION.md
│ └─ API_USAGE_EXAMPLES.md
├─ install.func/ (5 files)
│ ├─ README.md
│ ├─ INSTALL_FUNC_FLOWCHART.md
│ ├─ INSTALL_FUNC_FUNCTIONS_REFERENCE.md
│ ├─ INSTALL_FUNC_INTEGRATION.md
│ └─ INSTALL_FUNC_USAGE_EXAMPLES.md
├─ tools.func/ (6 files) ★ NEW
│ ├─ README.md
│ ├─ TOOLS_FUNC_FLOWCHART.md
│ ├─ TOOLS_FUNC_FUNCTIONS_REFERENCE.md
│ ├─ TOOLS_FUNC_INTEGRATION.md
│ ├─ TOOLS_FUNC_USAGE_EXAMPLES.md
│ └─ TOOLS_FUNC_ENVIRONMENT_VARIABLES.md
├─ alpine-install.func/ (5 files) ★ NEW
│ ├─ README.md
│ ├─ ALPINE_INSTALL_FUNC_FLOWCHART.md
│ ├─ ALPINE_INSTALL_FUNC_FUNCTIONS_REFERENCE.md
│ ├─ ALPINE_INSTALL_FUNC_INTEGRATION.md
│ └─ ALPINE_INSTALL_FUNC_USAGE_EXAMPLES.md
├─ alpine-tools.func/ (5 files) ★ NEW
│ ├─ README.md
│ ├─ ALPINE_TOOLS_FUNC_FLOWCHART.md
│ ├─ ALPINE_TOOLS_FUNC_FUNCTIONS_REFERENCE.md
│ ├─ ALPINE_TOOLS_FUNC_INTEGRATION.md
│ └─ ALPINE_TOOLS_FUNC_USAGE_EXAMPLES.md
└─ cloud-init.func/ (5 files) ★ NEW
├─ README.md
├─ CLOUD_INIT_FUNC_FLOWCHART.md
├─ CLOUD_INIT_FUNC_FUNCTIONS_REFERENCE.md
├─ CLOUD_INIT_FUNC_INTEGRATION.md
└─ CLOUD_INIT_FUNC_USAGE_EXAMPLES.md
## 📊 **Documentation Statistics**
| Metric | Count |
|--------|:---:|
| Total Documentation Files | 67 |
| Project Directories Documented | 6 (ct, install, vm, tools, api, misc) |
| Function Libraries Documented | 9 |
| Total Functions Referenced | 150+ |
| Total Lines of Documentation | 15,000+ |
| Code Examples | 50+ |
| Visual Flowcharts | 15+ |
**New in this update (★ NEW)**: 6 new section directories (ct/, install/, vm/, tools/, api/) mirroring project structure
| Code Examples | 50+ |
| Visual Flowcharts | 15+ |
**New in this update (★ NEW)**: 5 new function library subdirectories with 25 files
---
## 🎓 **Learning Paths**
### Path 1: Beginner - First Time Contributing (2-3 hours)
1. Read: [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md) - Quick Start section
2. Read: [UPDATED_APP-ct.md](UPDATED_APP-ct.md) - Overview
3. Read: [UPDATED_APP-install.md](UPDATED_APP-install.md) - Overview
4. Study: One real example from each guide
5. Create your first ct/app.sh and install/app-install.sh
6. Submit PR!
### Path 2: Intermediate - Deep Understanding (4-6 hours)
1. Read: [TECHNICAL_REFERENCE.md](TECHNICAL_REFERENCE.md)
2. Study: [misc/build.func/README.md](misc/build.func/README.md)
3. Study: [misc/tools.func/README.md](misc/tools.func/README.md)
4. Study: [misc/install.func/README.md](misc/install.func/README.md)
5. Review: EXIT_CODES and error handling
6. Create an advanced application with custom setup
### Path 3: Advanced - Architecture Mastery (8+ hours)
1. Read all TECHNICAL_REFERENCE.md
2. Study all 9 function libraries in depth:
- Flowchart
- Functions Reference
- Integration Guide
- Usage Examples
3. Review: [CHANGELOG_MISC.md](CHANGELOG_MISC.md) for recent changes
4. Review: [DEFAULTS_SYSTEM_GUIDE.md](DEFAULTS_SYSTEM_GUIDE.md)
5. Study: [DEV_MODE.md](DEV_MODE.md) for debugging
6. Contribute to function libraries or complex applications
### Path 4: Operator/User - Configuration Focus (1-2 hours)
1. Read: [DEFAULTS_SYSTEM_GUIDE.md](DEFAULTS_SYSTEM_GUIDE.md)
2. Read: [EXIT_CODES.md](EXIT_CODES.md) - for troubleshooting
3. Read: [DEV_MODE.md](DEV_MODE.md) - for debugging
---
## 🔍 **Search Guide**
### Looking for...
**How do I create a ct script?**
→ [UPDATED_APP-ct.md](UPDATED_APP-ct.md)
**How do I create an install script?**
→ [UPDATED_APP-install.md](UPDATED_APP-install.md)
**What does exit code 206 mean?**
→ [EXIT_CODES.md](EXIT_CODES.md#container-creation-errors-200-209)
**How do I debug a failed installation?**
→ [DEV_MODE.md](DEV_MODE.md)
**What are the default configuration options?**
→ [DEFAULTS_SYSTEM_GUIDE.md](DEFAULTS_SYSTEM_GUIDE.md)
**What's a function in build.func?**
→ [misc/build.func/BUILD_FUNC_FUNCTIONS_REFERENCE.md](misc/build.func/BUILD_FUNC_FUNCTIONS_REFERENCE.md)
**How do I install Node.js in a container?**
→ [misc/tools.func/TOOLS_FUNC_FUNCTIONS_REFERENCE.md](misc/tools.func/TOOLS_FUNC_FUNCTIONS_REFERENCE.md#setup_nodejsversion)
**How do Alpine containers differ from Debian?**
→ [misc/alpine-install.func/README.md](misc/alpine-install.func/README.md)
**What changed recently in /misc?**
→ [CHANGELOG_MISC.md](CHANGELOG_MISC.md)
---
## ✅ **Documentation Completeness**
- ✅ All 9 function libraries have dedicated subdirectories
- ✅ Each library has 5-6 detailed documentation files
- ✅ Complete flowcharts for complex processes
- ✅ Alphabetical function references with signatures
- ✅ Real-world usage examples for every pattern
- ✅ Integration guides showing component relationships
- ✅ Best practices documented with DO/DON'T sections
- ✅ Troubleshooting guides for common issues
- ✅ Exit codes fully mapped and explained
- ✅ Architecture documentation with diagrams
---
## 🚀 **Standardized Documentation Pattern**
Each function library follows this consistent pattern:
```
function-library/
├─ README.md # Quick reference
├─ FUNCTION_LIBRARY_FLOWCHART.md # Visual flows
├─ FUNCTION_LIBRARY_FUNCTIONS_REFERENCE.md # Complete reference
├─ FUNCTION_LIBRARY_INTEGRATION.md # How it connects
├─ FUNCTION_LIBRARY_USAGE_EXAMPLES.md # Real examples
└─ [FUNCTION_LIBRARY_ENVIRONMENT_VARIABLES.md] # (if needed)
```
This makes it easy to:
- Find information quickly
- Navigate between related docs
- Understand component relationships
- Learn from examples
- Reference complete function signatures
---
## 📝 **Last Updated**
- **Date**: December 2025
- **Version**: 2.0 (Comprehensive Restructure)
- **Status**: ✅ All 9 function libraries fully documented and standardized
- **New This Update**: tools.func/, alpine-install.func/, alpine-tools.func/, cloud-init.func/ subdirectories with complete documentation
---
## 🤝 **Contributing Documentation**
Found an error or want to improve documentation?
1. Open an issue: https://github.com/community-scripts/ProxmoxVED/issues
2. Or submit a PR improving documentation
3. See: [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md) for details
---
## 📚 **Related Resources**
- **GitHub Repository**: https://github.com/community-scripts/ProxmoxVED
- **Proxmox Documentation**: https://pve.proxmox.com/wiki/
- **Community Discussions**: https://github.com/community-scripts/ProxmoxVED/discussions
---
**Ready to get started?** Choose a learning path above or use the quick navigation. 🚀

View File

@ -1,12 +1,40 @@
# 📚 ProxmoxVED Documentation # 📚 ProxmoxVED Documentation
Complete documentation for the ProxmoxVED project - mirroring the project structure with comprehensive guides for every component. Complete guide to all ProxmoxVED documentation - quickly find what you need.
--- ---
## 🎯 **Quick Start by Role** ## 🎯 **Quick Navigation by Goal**
### 👤 **I'm a...** ### 👤 **I want to...**
**Contribute a new application**
→ Start with: [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md)
→ Then: [ct/DETAILED_GUIDE.md](ct/DETAILED_GUIDE.md) + [install/DETAILED_GUIDE.md](install/DETAILED_GUIDE.md)
**Understand the architecture**
→ Read: [TECHNICAL_REFERENCE.md](TECHNICAL_REFERENCE.md)
→ Then: [misc/README.md](misc/README.md)
**Debug a failed installation**
→ Check: [EXIT_CODES.md](EXIT_CODES.md)
→ Then: [DEV_MODE.md](DEV_MODE.md)
→ See also: [misc/error_handler.func/](misc/error_handler.func/)
**Configure system defaults**
→ Read: [DEFAULTS_SYSTEM_GUIDE.md](DEFAULTS_SYSTEM_GUIDE.md)
**Learn about recent changes**
→ Check: [CHANGELOG_MISC.md](CHANGELOG_MISC.md)
**Develop a function library**
→ Study: [misc/](misc/) documentation
---
## 👤 **Quick Start by Role**
### **I'm a...**
**New Contributor** **New Contributor**
→ Start: [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md) → Start: [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md)
@ -14,12 +42,12 @@ Complete documentation for the ProxmoxVED project - mirroring the project struct
**Container Creator** **Container Creator**
→ Read: [ct/README.md](ct/README.md) → Read: [ct/README.md](ct/README.md)
Guide: [UPDATED_APP-ct.md](UPDATED_APP-ct.md) Deep Dive: [ct/DETAILED_GUIDE.md](ct/DETAILED_GUIDE.md)
→ Reference: [misc/build.func/](misc/build.func/) → Reference: [misc/build.func/](misc/build.func/)
**Installation Script Developer** **Installation Script Developer**
→ Read: [install/README.md](install/README.md) → Read: [install/README.md](install/README.md)
Guide: [UPDATED_APP-install.md](UPDATED_APP-install.md) Deep Dive: [install/DETAILED_GUIDE.md](install/DETAILED_GUIDE.md)
→ Reference: [misc/tools.func/](misc/tools.func/) → Reference: [misc/tools.func/](misc/tools.func/)
**VM Provisioner** **VM Provisioner**
@ -45,7 +73,7 @@ Complete documentation for the ProxmoxVED project - mirroring the project struct
--- ---
## 📁 **Documentation Structure** ## 📂 **Documentation Structure**
### Project-Mirrored Directories ### Project-Mirrored Directories
@ -53,11 +81,11 @@ Each major project directory has documentation:
``` ```
ProxmoxVED/ ProxmoxVED/
├─ ct/ ↔ docs/ct/README.md ├─ ct/ ↔ docs/ct/ (README.md + DETAILED_GUIDE.md)
├─ install/ ↔ docs/install/README.md ├─ install/ ↔ docs/install/ (README.md + DETAILED_GUIDE.md)
├─ vm/ ↔ docs/vm/README.md ├─ vm/ ↔ docs/vm/ (README.md)
├─ tools/ ↔ docs/tools/README.md ├─ tools/ ↔ docs/tools/ (README.md)
├─ api/ ↔ docs/api/README.md ├─ api/ ↔ docs/api/ (README.md)
└─ misc/ ↔ docs/misc/ (9 function libraries) └─ misc/ ↔ docs/misc/ (9 function libraries)
``` ```
@ -66,8 +94,8 @@ ProxmoxVED/
| Document | Purpose | Audience | | Document | Purpose | Audience |
|----------|---------|----------| |----------|---------|----------|
| [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md) | How to contribute | Contributors | | [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md) | How to contribute | Contributors |
| [UPDATED_APP-ct.md](UPDATED_APP-ct.md) | Create ct scripts | Container developers | | [ct/DETAILED_GUIDE.md](ct/DETAILED_GUIDE.md) | Create ct scripts | Container developers |
| [UPDATED_APP-install.md](UPDATED_APP-install.md) | Create install scripts | Installation developers | | [install/DETAILED_GUIDE.md](install/DETAILED_GUIDE.md) | Create install scripts | Installation developers |
| [TECHNICAL_REFERENCE.md](TECHNICAL_REFERENCE.md) | Architecture deep-dive | Architects, advanced users | | [TECHNICAL_REFERENCE.md](TECHNICAL_REFERENCE.md) | Architecture deep-dive | Architects, advanced users |
| [DEFAULTS_SYSTEM_GUIDE.md](DEFAULTS_SYSTEM_GUIDE.md) | Configuration system | Operators, power users | | [DEFAULTS_SYSTEM_GUIDE.md](DEFAULTS_SYSTEM_GUIDE.md) | Configuration system | Operators, power users |
| [EXIT_CODES.md](EXIT_CODES.md) | Exit code reference | Troubleshooters | | [EXIT_CODES.md](EXIT_CODES.md) | Exit code reference | Troubleshooters |
@ -83,7 +111,7 @@ Documentation for `/ct` - Container creation scripts that run on the Proxmox hos
**Includes**: **Includes**:
- Overview of container creation process - Overview of container creation process
- Link to [UPDATED_APP-ct.md](UPDATED_APP-ct.md) guide - Deep dive: [DETAILED_GUIDE.md](ct/DETAILED_GUIDE.md) - Complete reference with examples
- Reference to [misc/build.func/](misc/build.func/) - Reference to [misc/build.func/](misc/build.func/)
- Quick start for creating new containers - Quick start for creating new containers
@ -92,7 +120,7 @@ Documentation for `/install` - Scripts that run inside containers to install app
**Includes**: **Includes**:
- Overview of 10-phase installation pattern - Overview of 10-phase installation pattern
- Link to [UPDATED_APP-install.md](UPDATED_APP-install.md) guide - Deep dive: [DETAILED_GUIDE.md](install/DETAILED_GUIDE.md) - Complete reference with examples
- Reference to [misc/tools.func/](misc/tools.func/) - Reference to [misc/tools.func/](misc/tools.func/)
- Alpine vs Debian differences - Alpine vs Debian differences
@ -145,13 +173,12 @@ Documentation for `/misc` - 9 core function libraries with complete references.
1. [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md) - Quick Start 1. [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md) - Quick Start
2. Pick your area: 2. Pick your area:
- Containers → [ct/README.md](ct/README.md) - Containers → [ct/README.md](ct/README.md) + [ct/DETAILED_GUIDE.md](ct/DETAILED_GUIDE.md)
- Installation → [install/README.md](install/README.md) - Installation → [install/README.md](install/README.md) + [install/DETAILED_GUIDE.md](install/DETAILED_GUIDE.md)
- VMs → [vm/README.md](vm/README.md) - VMs → [vm/README.md](vm/README.md)
3. Read the corresponding UPDATED_APP guide 3. Study existing similar script
4. Study existing similar script 4. Create your contribution
5. Create your contribution 5. Submit PR
6. Submit PR
### Path 2: Intermediate Developer (4-6 hours) ### Path 2: Intermediate Developer (4-6 hours)
@ -167,8 +194,7 @@ Documentation for `/misc` - 9 core function libraries with complete references.
### Path 3: Advanced Architect (8+ hours) ### Path 3: Advanced Architect (8+ hours)
1. All of Intermediate Path 1. All of Intermediate Path
2. Study all 9 function libraries: 2. Study all 9 function libraries in depth
- Each with FLOWCHART, FUNCTIONS_REFERENCE, INTEGRATION, USAGE_EXAMPLES
3. [DEFAULTS_SYSTEM_GUIDE.md](DEFAULTS_SYSTEM_GUIDE.md) - Configuration system 3. [DEFAULTS_SYSTEM_GUIDE.md](DEFAULTS_SYSTEM_GUIDE.md) - Configuration system
4. [DEV_MODE.md](DEV_MODE.md) - Debugging and development 4. [DEV_MODE.md](DEV_MODE.md) - Debugging and development
5. Design new features or function libraries 5. Design new features or function libraries
@ -186,7 +212,7 @@ Documentation for `/misc` - 9 core function libraries with complete references.
| Metric | Count | | Metric | Count |
|--------|:---:| |--------|:---:|
| **Documentation Files** | 67 | | **Documentation Files** | 63 |
| **Total Lines** | 15,000+ | | **Total Lines** | 15,000+ |
| **Function Libraries** | 9 | | **Function Libraries** | 9 |
| **Functions Documented** | 150+ | | **Functions Documented** | 150+ |
@ -200,8 +226,8 @@ Documentation for `/misc` - 9 core function libraries with complete references.
## 🔍 **Find It Fast** ## 🔍 **Find It Fast**
### By Feature ### By Feature
- **How do I create a container?** → [UPDATED_APP-ct.md](UPDATED_APP-ct.md) - **How do I create a container?** → [ct/DETAILED_GUIDE.md](ct/DETAILED_GUIDE.md)
- **How do I create an install script?** → [UPDATED_APP-install.md](UPDATED_APP-install.md) - **How do I create an install script?** → [install/DETAILED_GUIDE.md](install/DETAILED_GUIDE.md)
- **How do I create a VM?** → [vm/README.md](vm/README.md) - **How do I create a VM?** → [vm/README.md](vm/README.md)
- **How do I install Node.js?** → [misc/tools.func/](misc/tools.func/) - **How do I install Node.js?** → [misc/tools.func/](misc/tools.func/)
- **How do I debug?** → [DEV_MODE.md](DEV_MODE.md) - **How do I debug?** → [DEV_MODE.md](DEV_MODE.md)
@ -230,7 +256,7 @@ Documentation for `/misc` - 9 core function libraries with complete references.
- ✅ **Best practices** - DO/DON'T sections throughout - ✅ **Best practices** - DO/DON'T sections throughout
- ✅ **Learning paths** - Structured curriculum by role - ✅ **Learning paths** - Structured curriculum by role
- ✅ **Quick references** - Fast lookup by error code - ✅ **Quick references** - Fast lookup by error code
- ✅ **Comprehensive index** → [INDEX.md](INDEX.md) - ✅ **Comprehensive navigation** - This page
--- ---
@ -238,7 +264,7 @@ Documentation for `/misc` - 9 core function libraries with complete references.
**New to ProxmoxVED?** → [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md) **New to ProxmoxVED?** → [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md)
**Looking for something specific?** → [INDEX.md](INDEX.md) **Looking for something specific?** → Choose your role above or browse by directory
**Need to debug?** → [EXIT_CODES.md](EXIT_CODES.md) **Need to debug?** → [EXIT_CODES.md](EXIT_CODES.md)
@ -250,7 +276,7 @@ Documentation for `/misc` - 9 core function libraries with complete references.
Found an error? Want to improve docs? Found an error? Want to improve docs?
1. Open issue: https://github.com/community-scripts/ProxmoxVED/issues 1. Open issue: [GitHub Issues](https://github.com/community-scripts/ProxmoxVED/issues)
2. Or submit PR with improvements 2. Or submit PR with improvements
3. See [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md) for details 3. See [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md) for details
@ -259,10 +285,10 @@ Found an error? Want to improve docs?
## 📝 **Status** ## 📝 **Status**
- **Last Updated**: December 2025 - **Last Updated**: December 2025
- **Version**: 2.1 (Project Structure Mirror) - **Version**: 2.3 (Consolidated & Reorganized)
- **Completeness**: ✅ 100% - All components documented - **Completeness**: ✅ 100% - All components documented
- **Quality**: ✅ Production-ready - **Quality**: ✅ Production-ready
- **Examples**: ✅ 50+ tested examples - **Structure**: ✅ Clean and organized
--- ---

View File

@ -1,651 +0,0 @@
# Alpine-Install.func Wiki
A specialized module for Alpine Linux LXC container setup and configuration, providing functions for IPv6 management, network verification, OS updates, SSH configuration, timezone validation, and passwordless auto-login customization.
---
## 📋 Table of Contents
- [Overview](#overview)
- [Initialization & Signal Handling](#initialization--signal-handling)
- [Network & Connectivity Functions](#network--connectivity-functions)
- [OS Configuration Functions](#os-configuration-functions)
- [SSH & MOTD Configuration](#ssh--motd-configuration)
- [Container Customization](#container-customization)
- [Best Practices](#best-practices)
- [Error Handling](#error-handling)
- [Contributing](#contributing)
---
## Overview
This module provides Alpine Linux-specific installation and configuration functions used inside LXC containers during the setup phase. Key capabilities include:
- ✅ IPv6 enablement/disablement with persistent configuration
- ✅ Network connectivity verification with retry logic
- ✅ Alpine Linux OS updates via apk package manager
- ✅ SSH daemon and MOTD configuration
- ✅ Passwordless root auto-login setup
- ✅ Timezone validation for Alpine containers
- ✅ Comprehensive error handling with signal traps
### Integration Pattern
```bash
# Alpine container scripts load this module via curl
source <(curl -fsSL https://git.community-scripts.org/.../alpine-install.func)
load_functions # Initialize core utilities
catch_errors # Setup error handling and signal traps
```
---
## Initialization & Signal Handling
### Module Dependencies
The module automatically sources two required dependencies:
```bash
source <(curl -fsSL .../core.func) # Color codes, icons, message functions
source <(curl -fsSL .../error_handler.func) # Error handling and exit codes
load_functions # Initialize color/formatting
catch_errors # Setup trap handlers
```
### Signal Trap Configuration
```bash
set -Eeuo pipefail # Strict error mode
trap 'error_handler $? $LINENO "$BASH_COMMAND"' ERR
trap on_exit EXIT # Cleanup on exit
trap on_interrupt INT # Handle Ctrl+C (SIGINT)
trap on_terminate TERM # Handle SIGTERM
```
---
## Network & Connectivity Functions
### `verb_ip6()`
**Purpose**: Configures IPv6 settings and sets verbose mode based on environment variables.
**Signature**:
```bash
verb_ip6()
```
**Parameters**: None
**Returns**: No explicit return value (configures system state)
**Environment Effects**:
- Sets `STD` variable to control output verbosity (via `set_std_mode()`)
- If `DISABLEIPV6=yes`: disables IPv6 system-wide via sysctl
- Modifies `/etc/sysctl.conf` for persistent IPv6 disabled state
**Implementation Pattern**:
```bash
verb_ip6() {
set_std_mode # Initialize STD="" or STD="silent"
if [ "$DISABLEIPV6" == "yes" ]; then
$STD sysctl -w net.ipv6.conf.all.disable_ipv6=1
echo "net.ipv6.conf.all.disable_ipv6 = 1" >>/etc/sysctl.conf
$STD rc-update add sysctl default
fi
}
```
**Usage Examples**:
```bash
# Example 1: With IPv6 disabled
DISABLEIPV6="yes"
VERBOSE="no"
verb_ip6
# Result: IPv6 disabled, changes persisted to sysctl.conf
# Example 2: Keep IPv6 enabled (default)
DISABLEIPV6="no"
verb_ip6
# Result: IPv6 remains enabled, no configuration changes
```
---
### `setting_up_container()`
**Purpose**: Verifies network connectivity by checking for assigned IP addresses and retrying if necessary.
**Signature**:
```bash
setting_up_container()
```
**Parameters**: None (uses global `RETRY_NUM` and `RETRY_EVERY`)
**Returns**: 0 on success; exits with code 1 if network unavailable after retries
**Environment Side Effects**:
- Requires: `RETRY_NUM` (max attempts, default: 10), `RETRY_EVERY` (seconds between retries, default: 3)
- Uses: `CROSS`, `RD`, `CL`, `GN`, `BL` color variables from core.func
- Calls: `msg_info()`, `msg_ok()` message functions
**Implementation Pattern**:
```bash
setting_up_container() {
msg_info "Setting up Container OS"
i=$RETRY_NUM # Use global counter
while [ $i -gt 0 ]; do
# Check for non-loopback IPv4 address
if [ "$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | ...)" != "" ]; then
break
fi
echo 1>&2 -en "${CROSS}${RD} No Network! "
sleep $RETRY_EVERY
i=$((i - 1))
done
# If still no network after retries, exit with error
if [ "$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | ...)" = "" ]; then
exit 1
fi
msg_ok "Network Connected: ${BL}$(ip addr show | grep 'inet ' | awk '{print $2}' | ...)${CL}"
}
```
**Usage Examples**:
```bash
# Example 1: Network available immediately
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: Network delayed by 6 seconds (2 retries)
# Script waits 3 seconds x 2, then succeeds
# Output shows retry messages, then success
```
---
### `network_check()`
**Purpose**: Comprehensive network connectivity verification for both IPv4 and IPv6, including DNS resolution checks for Git-related domains.
**Signature**:
```bash
network_check()
```
**Parameters**: None
**Returns**: 0 on success; exits with code 1 if DNS critical failure
**Environment Side Effects**:
- Temporarily disables error trap (`set +e`, `trap - ERR`)
- Modifies error handling to allow graceful failure detection
- Re-enables error trap at end of function
- Calls: `msg_ok()`, `msg_error()`, `fatal()` message functions
**Implementation Pattern**:
```bash
network_check() {
set +e
trap - ERR
# Test IPv4 via multiple DNS servers
if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ...; then
ipv4_status="${GN}✔${CL} IPv4"
else
ipv4_status="${RD}✖${CL} IPv4"
# Prompt user to continue without internet
fi
# Verify DNS resolution for GitHub domains
RESOLVEDIP=$(getent hosts github.com | awk '{ print $1 }')
if [[ -z "$RESOLVEDIP" ]]; then
msg_error "Internet: ${ipv4_status} DNS Failed"
else
msg_ok "Internet: ${ipv4_status} DNS: ${BL}${RESOLVEDIP}${CL}"
fi
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
}
```
**Usage Examples**:
```bash
# Example 1: Good connectivity
network_check
# Output:
# ✔️ Network Connected: IPv4
# ✔️ Internet: ✔ IPv4 DNS: 140.82.113.3
# Example 2: No internet, user continues anyway
# Output prompts: "Internet NOT connected. Continue anyway? <y/N>"
# If user enters 'y':
# ⚠️ Expect Issues Without Internet
```
---
## OS Configuration Functions
### `update_os()`
**Purpose**: Updates Alpine Linux OS packages and installs Alpine-specific tools library for additional setup functions.
**Signature**:
```bash
update_os()
```
**Parameters**: None
**Returns**: No explicit return value (updates system)
**Environment Side Effects**:
- Runs `apk update && apk upgrade`
- Sources alpine-tools.func for Alpine-specific package installation helpers
- Uses `$STD` wrapper to suppress output unless `VERBOSE=yes`
- Calls: `msg_info()`, `msg_ok()` message functions
**Implementation Pattern**:
```bash
update_os() {
msg_info "Updating Container OS"
$STD apk update && $STD apk upgrade
source <(curl -fsSL https://git.community-scripts.org/.../alpine-tools.func)
msg_ok "Updated Container OS"
}
```
**Usage Examples**:
```bash
# Example 1: Standard update
VERBOSE="no"
update_os
# Output:
# Updating Container OS
# ✔️ Updated Container OS
# (Output suppressed via $STD)
# Example 2: Verbose mode
VERBOSE="yes"
update_os
# Output shows all apk operations plus success message
```
---
## SSH & MOTD Configuration
### `motd_ssh()`
**Purpose**: Configures Message of the Day (MOTD) with container information and enables SSH root access if required.
**Signature**:
```bash
motd_ssh()
```
**Parameters**: None
**Returns**: No explicit return value (configures system)
**Environment Side Effects**:
- Modifies `/root/.bashrc` to set TERM environment variable
- Creates `/etc/profile.d/00_lxc-details.sh` with container information script
- If `SSH_ROOT=yes`: modifies `/etc/ssh/sshd_config` and starts SSH daemon
- Uses: `APPLICATION`, `SSH_ROOT` variables from environment
- Requires: color variables (`BOLD`, `YW`, `RD`, `GN`, `CL`) from core.func
**Implementation Pattern**:
```bash
motd_ssh() {
# Configure TERM for better terminal support
echo "export TERM='xterm-256color'" >>/root/.bashrc
# Gather OS information
OS_NAME=$(grep ^NAME /etc/os-release | cut -d= -f2 | tr -d '"')
OS_VERSION=$(grep ^VERSION_ID /etc/os-release | cut -d= -f2 | tr -d '"')
IP=$(ip -4 addr show eth0 | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
# Create MOTD script with container details
PROFILE_FILE="/etc/profile.d/00_lxc-details.sh"
cat > "$PROFILE_FILE" <<'EOF'
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}${IP}${CL}"
echo -e "${YW} Repository: ${GN}https://github.com/community-scripts/ProxmoxVED${CL}"
echo ""
EOF
# Enable SSH root access if configured
if [[ "${SSH_ROOT}" == "yes" ]]; then
sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config
rc-update add sshd
/etc/init.d/sshd start
fi
}
```
**Usage Examples**:
```bash
# Example 1: MOTD configuration with SSH enabled
APPLICATION="MyApp"
SSH_ROOT="yes"
motd_ssh
# Result: SSH daemon started and set to auto-start, MOTD shows app info
# Example 2: MOTD only (SSH disabled)
APPLICATION="MyApp"
SSH_ROOT="no"
motd_ssh
# Result: MOTD configured but SSH remains disabled
```
---
## Container Customization
### `validate_tz()`
**Purpose**: Validates that a timezone string exists in the Alpine Linux timezone database.
**Signature**:
```bash
validate_tz()
```
**Parameters**:
- `$1` - Timezone string (e.g., "America/New_York", "UTC", "Europe/London")
**Returns**: 0 if timezone file exists, 1 if invalid
**Implementation Pattern**:
```bash
validate_tz() {
[[ -f "/usr/share/zoneinfo/$1" ]] # Bash test operator returns success/failure
}
```
**Usage Examples**:
```bash
# Example 1: Valid timezone
validate_tz "America/New_York"
echo $? # Output: 0
# Example 2: Invalid timezone
validate_tz "Invalid/Timezone"
echo $? # Output: 1
# Example 3: UTC (always valid)
validate_tz "UTC"
echo $? # Output: 0
```
---
### `customize()`
**Purpose**: Configures container for passwordless root auto-login and creates update script for easy application re-deployment.
**Signature**:
```bash
customize()
```
**Parameters**: None (uses global `PASSWORD` and `app` variables)
**Returns**: No explicit return value (configures system)
**Environment Side Effects**:
- If `PASSWORD=""` (empty):
* Removes password prompt from root login
* Drops user into shell automatically
* Creates autologin boot script at `/etc/local.d/autologin.start`
* Creates `.hushlogin` to suppress login banners
* Registers script with rc-update
- Creates `/usr/bin/update` script for application updates
- Requires: `app` variable (application name in lowercase)
- Calls: `msg_info()`, `msg_ok()` message functions
**Implementation Pattern**:
```bash
customize() {
if [[ "$PASSWORD" == "" ]]; then
msg_info "Customizing Container"
# Remove password requirement
passwd -d root >/dev/null 2>&1
# Install util-linux if needed
apk add --no-cache --force-broken-world util-linux >/dev/null 2>&1
# Create autologin startup script
mkdir -p /etc/local.d
cat > /etc/local.d/autologin.start <<'EOF'
#!/bin/sh
sed -i 's|^tty1::respawn:.*|tty1::respawn:/sbin/agetty --autologin root --noclear tty1 38400 linux|' /etc/inittab
kill -HUP 1
EOF
chmod +x /etc/local.d/autologin.start
touch /root/.hushlogin
rc-update add local >/dev/null 2>&1
/etc/local.d/autologin.start
msg_ok "Customized Container"
fi
# Create update script
echo "bash -c \"\$(curl -fsSL https://github.com/community-scripts/ProxmoxVED/raw/main/ct/${app}.sh)\"" >/usr/bin/update
chmod +x /usr/bin/update
}
```
**Usage Examples**:
```bash
# Example 1: Passwordless auto-login
PASSWORD=""
app="myapp"
customize
# Result: Root login without password, auto-login configured
# User can type: /usr/bin/update to re-run application setup
# Example 2: Password-protected login
PASSWORD="MySecurePassword"
customize
# Result: Auto-login skipped, password remains active
# Update script still created for re-deployment
```
---
## Best Practices
### 1. **Initialization Order**
Always follow this sequence in Alpine install scripts:
```bash
#!/bin/sh
set -Eeuo pipefail
# 1. Ensure curl is available for sourcing functions
if ! command -v curl >/dev/null 2>&1; then
apk update && apk add curl >/dev/null 2>&1
fi
# 2. Source dependencies in correct order
source <(curl -fsSL .../core.func)
source <(curl -fsSL .../error_handler.func)
# 3. Initialize function libraries
load_functions # Sets up colors, formatting, icons
catch_errors # Configures error traps and signal handlers
# 4. Now safe to call alpine-install.func functions
verb_ip6
setting_up_container
network_check
update_os
```
### 2. **Signal Handling**
Alpine-install.func provides comprehensive signal trap setup:
```bash
# ERR trap: Catches all command failures
trap 'error_handler $? $LINENO "$BASH_COMMAND"' ERR
# EXIT trap: Cleanup on normal or abnormal termination
trap on_exit EXIT
# INT trap: Handle Ctrl+C gracefully
trap on_interrupt INT
# TERM trap: Handle SIGTERM signal
trap on_terminate TERM
```
### 3. **Network Configuration**
Use retry logic when network may not be immediately available:
```bash
setting_up_container # Retries up to RETRY_NUM times
network_check # Validates DNS and Internet
```
### 4. **IPv6 Considerations**
For production Alpine containers:
```bash
# Disable IPv6 if not needed (reduces attack surface)
DISABLEIPV6="yes"
verb_ip6
# Or keep enabled (default):
DISABLEIPV6="no"
# No configuration needed
```
### 5. **Error Handling with Color Output**
Functions use color-coded message output:
```bash
msg_info # Informational messages (yellow)
msg_ok # Success messages (green)
msg_error # Error messages (red)
msg_warn # Warning messages (orange)
```
---
## Error Handling
The module implements comprehensive error handling:
### Exit Codes
| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | General error (network unavailable, DNS failed, etc.) |
| 130 | Interrupted by user (SIGINT) |
| 143 | Terminated by signal (SIGTERM) |
### Error Handler Function
The error_handler receives three parameters:
```bash
error_handler() {
local exit_code="$1" # Exit code from failed command
local line_number="$2" # Line where error occurred
local command="$3" # Command that failed
# Errors are reported with line number and command details
# Stack trace available for debugging
}
```
### Debug Variables
Available for troubleshooting:
```bash
$VERBOSE # Set to "yes" to show all output
$DEV_MODE_TRACE # Set to "true" for bash -x tracing
$DEV_MODE_LOGS # Set to "true" to persist logs
```
---
## Contributing
### Adding New Functions
When adding Alpine-specific functions:
1. Follow the established naming convention: `function_purpose()`
2. Include comprehensive docstring with signature, parameters, returns
3. Use color variables from core.func for output consistency
4. Handle errors via error_handler trap
5. Document all environment variable dependencies
### Testing New Functions
```bash
# Test function in isolation with error traps:
set -Eeuo pipefail
trap 'error_handler $? $LINENO "$BASH_COMMAND"' ERR
source <(curl -fsSL .../core.func)
source <(curl -fsSL .../error_handler.func)
load_functions
catch_errors
# Now test your function:
your_function
```
### Compatibility
- Alpine Linux 3.16+ (uses ash shell compatible syntax)
- OpenRC init system (rc-update, rc-service)
- Requires: core.func, error_handler.func
- Optional: alpine-tools.func (for extended package management)
---
## Notes
- Functions are designed for execution **inside** LXC containers (not on Proxmox host)
- Alpine uses `apk` package manager (not `apt`)
- Alpine uses OpenRC (not systemd) - use `rc-update` and `/etc/init.d/` commands
- IPv6 can be disabled for security/performance but is enabled by default
- Auto-login configuration persists across container reboots via rc-update

View File

@ -1,588 +0,0 @@
# Alpine-Tools.func Wiki
Alpine Linux-specific tool setup and package management module providing helper functions optimized for Alpine's apk package manager and minimal container environment.
---
## 📋 Table of Contents
- [Overview](#overview)
- [Helper Functions](#helper-functions)
- [GitHub Release Functions](#github-release-functions)
- [Tool Installation Patterns](#tool-installation-patterns)
- [Package Management](#package-management)
- [Best Practices](#best-practices)
- [Debugging](#debugging)
- [Contributing](#contributing)
---
## Overview
Alpine-tools.func provides **Alpine Linux-specific utilities**:
- ✅ Alpine apk package manager wrapper
- ✅ GitHub release version checking and installation
- ✅ Tool caching and version tracking
- ✅ Progress reporting with pv (pipe viewer)
- ✅ Network resolution helpers for Alpine
- ✅ PATH persistence across sessions
- ✅ Retry logic for failed downloads
- ✅ Minimal dependencies philosophy (Alpine ~5MB containers)
### Key Differences from Debian/Ubuntu
| Feature | Alpine | Debian/Ubuntu |
|---------|--------|---------------|
| Package Manager | apk | apt-get, dpkg |
| Shell | ash (dash variant) | bash |
| Init System | OpenRC | systemd |
| Size | ~5MB base | ~100MB+ base |
| Libc | musl | glibc |
| Find getent | Not installed | Installed |
### Integration Pattern
```bash
#!/bin/sh # Alpine uses ash, not bash
source <(curl -fsSL .../core.func)
source <(curl -fsSL .../alpine-tools.func)
load_functions
# Now Alpine-specific tool functions available
need_tool curl jq # Install if missing
check_for_gh_release "myapp" "owner/repo"
```
---
## Helper Functions
### `lower()`
**Purpose**: Converts string to lowercase (portable ash function).
**Signature**:
```bash
lower()
```
**Parameters**:
- `$1` - String to convert
**Returns**: Lowercase string on stdout
**Behavior**:
```bash
# Alpine's tr works with character classes
printf '%s' "$1" | tr '[:upper:]' '[:lower:]'
```
**Usage Examples**:
```bash
# Example 1: App name normalization
result=$(lower "MyApp")
echo "$result" # Output: myapp
# Example 2: In variable assignment
app_dir=$(lower "$APPLICATION")
mkdir -p /opt/$app_dir
```
---
### `has()`
**Purpose**: Checks if command is available in PATH.
**Signature**:
```bash
has()
```
**Parameters**:
- `$1` - Command name
**Returns**: 0 if available, 1 if not
**Implementation**:
```bash
has() {
command -v "$1" >/dev/null 2>&1
}
```
**Usage Examples**:
```bash
# Example 1: Check availability
if has jq; then
echo "jq is installed"
else
echo "jq is not installed"
fi
# Example 2: In conditionals
has docker && docker ps || echo "Docker not installed"
```
---
### `need_tool()`
**Purpose**: Ensures specified tools are installed, installs missing ones via apk.
**Signature**:
```bash
need_tool()
```
**Parameters**:
- `$@` - Tool names (space-separated)
**Returns**: 0 on success, 1 if installation failed
**Behavior**:
```bash
# Checks each tool
# If any missing: runs apk add for all
# Displays message before and after
```
**Error Handling**:
- Returns 1 if apk add fails
- Shows which tools failed
- Suggests checking package names
**Usage Examples**:
```bash
# Example 1: Ensure common tools available
need_tool curl jq unzip git
# Installs any missing packages
# Example 2: Optional tool check
if need_tool myapp-cli; then
myapp-cli --version
else
echo "myapp-cli not available in apk"
fi
# Example 3: With error handling
need_tool docker || {
echo "Failed to install docker"
exit 1
}
```
---
### `net_resolves()`
**Purpose**: Checks if hostname resolves and responds (Alpine-friendly DNS test).
**Signature**:
```bash
net_resolves()
```
**Parameters**:
- `$1` - Hostname to test
**Returns**: 0 if resolves and responds, 1 if fails
**Behavior**:
```bash
# Alpine doesn't have getent by default
# Falls back to nslookup if ping fails
# Returns success if either works
ping -c1 -W1 "$host" >/dev/null 2>&1 || nslookup "$host" >/dev/null 2>&1
```
**Usage Examples**:
```bash
# Example 1: Test GitHub connectivity
if net_resolves api.github.com; then
echo "Can reach GitHub API"
else
echo "GitHub API unreachable"
fi
# Example 2: In download function
net_resolves download.example.com || {
echo "Download server not reachable"
exit 1
}
```
---
### `ensure_usr_local_bin_persist()`
**Purpose**: Ensures `/usr/local/bin` is in PATH across all shell sessions.
**Signature**:
```bash
ensure_usr_local_bin_persist()
```
**Parameters**: None
**Returns**: No explicit return value (modifies system)
**Behavior**:
```bash
# Creates /etc/profile.d/10-localbin.sh
# Script adds /usr/local/bin to PATH if not already present
# Runs on every shell startup
# Alpine uses /etc/profile for login shells
# profile.d scripts sourced automatically
```
**Implementation**:
```bash
PROFILE_FILE="/etc/profile.d/10-localbin.sh"
if [ ! -f "$PROFILE_FILE" ]; then
echo 'case ":$PATH:" in *:/usr/local/bin:*) ;; *) export PATH="/usr/local/bin:$PATH";; esac' > "$PROFILE_FILE"
chmod +x "$PROFILE_FILE"
fi
```
**Usage Examples**:
```bash
# Example 1: Make sure local tools available
ensure_usr_local_bin_persist
# Now /usr/local/bin binaries always in PATH
# Example 2: After installing custom tool
cp ./my-tool /usr/local/bin/
ensure_usr_local_bin_persist
# Tool immediately accessible in PATH
```
---
### `download_with_progress()`
**Purpose**: Downloads file with progress bar (if pv available) or simple # progress.
**Signature**:
```bash
download_with_progress()
```
**Parameters**:
- `$1` - URL to download
- `$2` - Destination file path
**Returns**: 0 on success, 1 on failure
**Behavior**:
```bash
# Attempts to get content-length header
# If available: pipes through pv for progress bar
# If not: uses curl's built-in # progress
# Shows errors clearly
```
**Requirements**:
- `curl` - For downloading
- `pv` - Optional, for progress bar
- Destination directory must exist
**Usage Examples**:
```bash
# Example 1: Simple download
download_with_progress "https://example.com/file.tar.gz" "/tmp/file.tar.gz"
# Shows progress bar if pv available
# Example 2: With error handling
if download_with_progress "$URL" "$DEST"; then
echo "Downloaded successfully"
tar -xzf "$DEST"
else
echo "Download failed"
exit 1
fi
```
---
## GitHub Release Functions
### `check_for_gh_release()`
**Purpose**: Checks GitHub releases for available updates and compares with currently installed version.
**Signature**:
```bash
check_for_gh_release()
```
**Parameters**:
- `$1` - Application name (e.g., "nodejs")
- `$2` - GitHub repository (e.g., "nodejs/node")
- `$3` - Pinned version (optional, e.g., "20.0.0")
**Returns**: 0 if update needed, 1 if current or pinned
**Environment Variables Set**:
- `CHECK_UPDATE_RELEASE` - Latest available version (without v prefix)
**Behavior**:
```bash
# 1. Check network to api.github.com
# 2. Fetch latest release tag via GitHub API
# 3. Compare with installed version (stored in ~/.appname)
# 4. Show appropriate message:
# - "app pinned to vX.X.X (no update)"
# - "app pinned vX.X.X (upstream vY.Y.Y) → update/downgrade"
# - "Update available: vA.A.A → vB.B.B"
# - "Already up to date"
```
**File Storage**:
```bash
~/.${app_lc} # File contains current version string
# Example: ~/.nodejs contains "20.10.0"
```
**Usage Examples**:
```bash
# Example 1: Check for update
check_for_gh_release "nodejs" "nodejs/node"
# Output: "Update available: v18.0.0 → v20.10.0"
# Sets: CHECK_UPDATE_RELEASE="20.10.0"
# Example 2: Pinned version (no update)
check_for_gh_release "nodejs" "nodejs/node" "20.0.0"
# Output: "app pinned to v20.0.0 (no update)"
# Returns 1 (no update available)
# Example 3: With error handling
if check_for_gh_release "myapp" "owner/myapp"; then
echo "Update available: $CHECK_UPDATE_RELEASE"
download_and_install
fi
```
---
## Tool Installation Patterns
### Pattern 1: Simple Package Installation
```bash
#!/bin/sh
need_tool curl jq # Ensure tools available
# Continue with script
```
### Pattern 2: GitHub Release Installation
```bash
#!/bin/sh
source <(curl -fsSL .../alpine-tools.func)
load_functions
# Check for updates
check_for_gh_release "myapp" "owner/myapp"
# Download from GitHub releases
RELEASE="$CHECK_UPDATE_RELEASE"
URL="https://github.com/owner/myapp/releases/download/v${RELEASE}/myapp-alpine.tar.gz"
download_with_progress "$URL" "/tmp/myapp-${RELEASE}.tar.gz"
tar -xzf "/tmp/myapp-${RELEASE}.tar.gz" -C /usr/local/bin/
```
### Pattern 3: Version Pinning
```bash
#!/bin/sh
# For specific use case, pin to known good version
check_for_gh_release "nodejs" "nodejs/node" "20.10.0"
# Will use 20.10.0 even if 21.0.0 available
```
---
## Package Management
### Alpine Package Naming
Alpine packages often have different names than Debian:
| Tool | Alpine | Debian |
|------|--------|--------|
| curl | curl | curl |
| Git | git | git |
| Docker | docker | docker.io |
| PostgreSQL | postgresql-client | postgresql-client |
| Build tools | build-base | build-essential |
| Development headers | -dev packages | -dev packages |
### Finding Alpine Packages
```bash
# Search for package
apk search myapp
# Show package info
apk info -d myapp
# List available versions
apk search myapp --all
```
### Installing Alpine Packages
```bash
# Basic install (not cached)
apk add curl git
# Install with --no-cache (for containers)
apk add --no-cache curl git
# Force broken packages (last resort)
apk add --no-cache --force-broken-world util-linux
```
---
## Best Practices
### 1. **Use `--no-cache` in Containers**
```bash
# Good: Saves space in container
apk add --no-cache curl git
# Avoid: Wastes space
apk update && apk add curl git
```
### 2. **Check Tools Before Using**
```bash
# Good: Graceful error
if ! has jq; then
need_tool jq || exit 1
fi
# Using jq safely
jq . < input.json
```
### 3. **Use need_tool() for Multiple**
```bash
# Good: Install all at once
need_tool curl jq git unzip
# Less efficient: Individual checks
has curl || apk add curl
has jq || apk add jq
```
### 4. **Ensure Persistence**
```bash
# For custom tools in /usr/local/bin
ensure_usr_local_bin_persist
# Now available in all future shells
/usr/local/bin/my-custom-tool
```
### 5. **Handle Network Failures**
```bash
# Alpine often in isolated environments
if ! net_resolves api.github.com; then
echo "GitHub API unreachable"
# Fallback to local package or error
exit 1
fi
```
---
## Debugging
### Check Package Availability
```bash
# List all available packages
apk search --all
# Find package by keyword
apk search curl
# Get specific package info
apk info postgresql-client
```
### Verify Installation
```bash
# Check if tool installed
apk info | grep myapp
# Verify PATH
which curl
echo $PATH
```
### Network Testing
```bash
# Test DNS
nslookup api.github.com
# Test connectivity
ping -c1 1.1.1.1
# Test download
curl -I https://api.github.com
```
---
## Contributing
### Adding New Helper Functions
When adding Alpine-specific helpers:
1. Use POSIX shell (ash-compatible)
2. Avoid bash-isms
3. Include error handling
4. Document with examples
5. Test on actual Alpine container
### Improving Package Installation
New patterns could support:
- Automatic Alpine version detection
- Package version pinning
- Dependency resolution
- Conflict detection
---
## Notes
- Alpine uses **ash shell** (POSIX-compatible, not bash)
- Alpine **apk is fast** and has minimal overhead
- Alpine containers **~5MB base image** (vs 100MB+ for Debian)
- **No getent available** by default (use nslookup fallback)
- GitHub releases can be **pre-compiled for Alpine musl**

View File

@ -1,670 +0,0 @@
# API.func Wiki
A telemetry and diagnostics module providing anonymous statistics collection and API integration with the Community-Scripts infrastructure for tracking container/VM creation metrics and installation success/failure data.
---
## 📋 Table of Contents
- [Overview](#overview)
- [Exit Code Reference](#exit-code-reference)
- [Telemetry Functions](#telemetry-functions)
- [API Payload Structure](#api-payload-structure)
- [Privacy & Opt-Out](#privacy--opt-out)
- [Error Mapping](#error-mapping)
- [Best Practices](#best-practices)
- [API Integration](#api-integration)
- [Contributing](#contributing)
---
## Overview
The API.func module provides anonymous telemetry reporting to Community-Scripts infrastructure, enabling:
- ✅ Container/VM creation statistics collection
- ✅ Installation success/failure tracking
- ✅ Comprehensive exit code mapping and explanation
- ✅ Anonymous session-based tracking (UUID)
- ✅ Privacy-respecting data collection (no personal data)
- ✅ Opt-out capability via DIAGNOSTICS setting
- ✅ Consistent error reporting across all scripts
### Integration Points
```bash
# In container build scripts (on Proxmox host):
source <(curl -fsSL .../api.func)
post_to_api # Report container creation
post_update_to_api # Report installation completion
# Error handling (in all scripts):
source <(curl -fsSL .../error_handler.func)
# explain_exit_code shared for consistent mappings
```
### Data Flow
```
Container/VM Creation
post_to_api()
Community-Scripts API
Anonymous Statistics
(No personal data)
```
---
## Exit Code Reference
### Category 1: Generic / Shell Errors
| Code | Meaning | Recovery |
|------|---------|----------|
| 1 | General error / Operation not permitted | Check permissions, re-run command |
| 2 | Misuse of shell builtins (syntax error) | Fix shell syntax, validate script |
| 126 | Command invoked cannot execute | Fix file permissions (chmod +x) |
| 127 | Command not found | Install missing package or tool |
| 128 | Invalid argument to exit | Check exit code parameter (0-255) |
| 130 | Terminated by Ctrl+C (SIGINT) | User interrupted - retry manually |
| 137 | Killed (SIGKILL / Out of memory) | Insufficient RAM - increase allocation |
| 139 | Segmentation fault (core dumped) | Serious application bug - contact support |
| 143 | Terminated (SIGTERM) | System shutdown or manual termination |
### Category 2: Package Manager Errors
| Code | Meaning | Recovery |
|------|---------|----------|
| 100 | APT: Package manager error (broken packages) | Run `apt --fix-broken install` |
| 101 | APT: Configuration error (bad sources.list) | Fix /etc/apt/sources.list, re-run apt update |
| 255 | DPKG: Fatal internal error | Run `dpkg --configure -a` |
### Category 3: Node.js / npm Errors
| Code | Meaning | Recovery |
|------|---------|----------|
| 243 | Node.js: Out of memory (heap out of memory) | Increase container RAM, reduce workload |
| 245 | Node.js: Invalid command-line option | Check node/npm arguments |
| 246 | Node.js: Internal JavaScript Parse Error | Update Node.js version |
| 247 | Node.js: Fatal internal error | Check Node.js installation integrity |
| 248 | Node.js: Invalid C++ addon / N-API failure | Rebuild native modules |
| 249 | Node.js: Inspector error | Disable debugger, retry |
| 254 | npm/pnpm/yarn: Unknown fatal error | Check package.json, clear cache |
### Category 4: Python Errors
| Code | Meaning | Recovery |
|------|---------|----------|
| 210 | Python: Virtualenv / uv environment missing | Recreate virtual environment |
| 211 | Python: Dependency resolution failed | Check package versions, fix conflicts |
| 212 | Python: Installation aborted (EXTERNALLY-MANAGED) | Use venv or remove marker file |
### Category 5: Database Errors
#### PostgreSQL
| Code | Meaning | Recovery |
|------|---------|----------|
| 231 | Connection failed (server not running) | Start PostgreSQL service |
| 232 | Authentication failed (bad user/password) | Verify credentials |
| 233 | Database does not exist | Create database: `createdb dbname` |
| 234 | Fatal error in query / syntax error | Fix SQL syntax |
#### MySQL / MariaDB
| Code | Meaning | Recovery |
|------|---------|----------|
| 241 | Connection failed (server not running) | Start MySQL/MariaDB service |
| 242 | Authentication failed (bad user/password) | Reset password, verify credentials |
| 243 | Database does not exist | Create database: `CREATE DATABASE dbname;` |
| 244 | Fatal error in query / syntax error | Fix SQL syntax |
#### MongoDB
| Code | Meaning | Recovery |
|------|---------|----------|
| 251 | Connection failed (server not running) | Start MongoDB daemon |
| 252 | Authentication failed (bad user/password) | Verify credentials, reset if needed |
| 253 | Database not found | Create database in MongoDB shell |
| 254 | Fatal query error | Check query syntax |
### Category 6: Proxmox Custom Codes
| Code | Meaning | Recovery |
|------|---------|----------|
| 200 | Failed to create lock file | Check /tmp permissions |
| 203 | Missing CTID variable | CTID must be provided to script |
| 204 | Missing PCT_OSTYPE variable | OS type not detected |
| 205 | Invalid CTID (<100) | Container ID must be >= 100 |
| 206 | CTID already in use | Check `pct list`, remove conflicting container |
| 207 | Password contains special characters | Use alphanumeric only for passwords |
| 208 | Invalid configuration format | Check DNS/MAC/Network format |
| 209 | Container creation failed | Check pct create output for details |
| 210 | Cluster not quorate | Ensure cluster nodes are online |
| 211 | Timeout waiting for template lock | Wait for concurrent downloads to finish |
| 214 | Not enough storage space | Free up disk space or expand storage |
| 215 | Container created but not listed | Check /etc/pve/lxc/ for config files |
| 216 | RootFS entry missing in config | Incomplete container creation |
| 217 | Storage does not support rootdir | Use compatible storage backend |
| 218 | Template corrupted or incomplete | Re-download template |
| 220 | Unable to resolve template path | Verify template availability |
| 221 | Template not readable | Fix file permissions |
| 222 | Template download failed (3 attempts) | Check network/storage |
| 223 | Template not available after download | Storage sync issue |
| 225 | No template for OS/Version | Run `pveam available` to see options |
| 231 | LXC stack upgrade/retry failed | Update pve-container package |
---
## Telemetry Functions
### `explain_exit_code()`
**Purpose**: Maps numeric exit codes to human-readable error descriptions. Shared between api.func and error_handler.func for consistency.
**Signature**:
```bash
explain_exit_code()
```
**Parameters**:
- `$1` - Numeric exit code (0-255)
**Returns**: Human-readable description string
**Supported Codes**:
- 1-2, 126-128, 130, 137, 139, 143 (Shell)
- 100-101, 255 (Package managers)
- 210-212 (Python)
- 231-234 (PostgreSQL)
- 241-244 (MySQL/MariaDB)
- 243-249, 254 (Node.js/npm)
- 251-254 (MongoDB)
- 200-231 (Proxmox custom)
**Default**: Returns "Unknown error" for unmapped codes
**Usage Examples**:
```bash
# Example 1: Common error
explain_exit_code 127
# Output: "Command not found"
# Example 2: Database error
explain_exit_code 241
# Output: "MySQL/MariaDB: Connection failed (server not running / wrong socket)"
# Example 3: Custom Proxmox error
explain_exit_code 206
# Output: "Custom: CTID already in use (check 'pct list' and /etc/pve/lxc/)"
# Example 4: Unknown code
explain_exit_code 999
# Output: "Unknown error"
```
---
### `post_to_api()`
**Purpose**: Sends LXC container creation statistics to Community-Scripts telemetry API.
**Signature**:
```bash
post_to_api()
```
**Parameters**: None (uses global environment variables)
**Returns**: No explicit return value (curl result stored in RESPONSE if diagnostics enabled)
**Requirements** (Silent fail if not met):
- `curl` command available
- `DIAGNOSTICS="yes"`
- `RANDOM_UUID` is set
- Executed on Proxmox host (has access to `pveversion`)
**Environment Variables Used**:
- `CT_TYPE` - Container type (privileged=1, unprivileged=0)
- `DISK_SIZE` - Allocated disk in GB
- `CORE_COUNT` - CPU core count
- `RAM_SIZE` - RAM allocated in MB
- `var_os` - Operating system name
- `var_version` - OS version
- `NSAPP` - Normalized application name
- `METHOD` - Installation method (default, template, etc.)
- `DIAGNOSTICS` - Enable telemetry (yes/no)
- `RANDOM_UUID` - Session UUID for tracking
**API Endpoint**: `http://api.community-scripts.org/dev/upload`
**Payload Structure**:
```json
{
"ct_type": 1, // Privileged (1) or Unprivileged (0)
"type": "lxc", // Always "lxc" for containers
"disk_size": 8, // GB
"core_count": 2, // CPU cores
"ram_size": 2048, // MB
"os_type": "debian", // OS name
"os_version": "12", // OS version
"nsapp": "myapp", // Application name
"method": "default", // Setup method
"pve_version": "8.2.2", // Proxmox VE version
"status": "installing", // Current status
"random_id": "550e8400-e29b" // Session UUID (anonymous)
}
```
**Usage Examples**:
```bash
# Example 1: Successful API post
CT_TYPE=1
DISK_SIZE=20
CORE_COUNT=4
RAM_SIZE=4096
var_os="ubuntu"
var_version="22.04"
NSAPP="jellyfin"
METHOD="default"
DIAGNOSTICS="yes"
RANDOM_UUID="550e8400-e29b-41d4-a716-446655440000"
post_to_api
# Result: Statistics sent to API (silently, no output)
# Example 2: Diagnostics disabled (opt-out)
DIAGNOSTICS="no"
post_to_api
# Result: Function returns immediately, no API call
# Example 3: Missing curl
DIAGNOSTICS="yes"
# curl not available in PATH
post_to_api
# Result: Function returns silently (curl requirement not met)
```
---
### `post_to_api_vm()`
**Purpose**: Sends VM creation statistics to Community-Scripts API (similar to post_to_api but for virtual machines).
**Signature**:
```bash
post_to_api_vm()
```
**Parameters**: None (uses global environment variables)
**Returns**: No explicit return value
**Requirements**: Same as `post_to_api()`
**Environment Variables Used**:
- `VMID` - Virtual machine ID
- `VM_TYPE` - VM type (kvm, etc.)
- `VM_CORES` - CPU core count
- `VM_RAM` - RAM in MB
- `VM_DISK` - Disk in GB
- `VM_OS` - Operating system
- `VM_VERSION` - OS version
- `VM_APP` - Application name
- `DIAGNOSTICS` - Enable telemetry
- `RANDOM_UUID` - Session UUID
**Payload Structure** (similar to containers but for VMs):
```json
{
"vm_id": 100,
"type": "qemu",
"vm_cores": 4,
"vm_ram": 4096,
"vm_disk": 20,
"vm_os": "ubuntu",
"vm_version": "22.04",
"vm_app": "jellyfin",
"pve_version": "8.2.2",
"status": "installing",
"random_id": "550e8400-e29b"
}
```
---
### `post_update_to_api()`
**Purpose**: Reports installation completion status (success/failure) for container or VM.
**Signature**:
```bash
post_update_to_api()
```
**Parameters**: None (uses global environment variables)
**Returns**: No explicit return value
**Requirements**: Same as `post_to_api()`
**Environment Variables Used**:
- `RANDOM_UUID` - Session UUID (must match initial post_to_api call)
- `DIAGNOSTICS` - Enable telemetry
- Installation status parameters
**Payload Structure**:
```json
{
"status": "completed", // "completed" or "failed"
"random_id": "550e8400-e29b", // Session UUID
"exit_code": 0, // 0 for success, error code for failure
"error_explanation": "" // Error description if failed
}
```
---
## API Payload Structure
### Container Creation Payload
```json
{
"ct_type": 1, // 1=Privileged, 0=Unprivileged
"type": "lxc", // Always "lxc"
"disk_size": 20, // GB
"core_count": 4, // CPU cores
"ram_size": 4096, // MB
"os_type": "debian", // Distribution name
"os_version": "12", // Version number
"nsapp": "jellyfin", // Application name
"method": "default", // Setup method
"pve_version": "8.2.2", // Proxmox VE version
"status": "installing", // Current phase
"random_id": "550e8400" // Unique session ID
}
```
### VM Creation Payload
```json
{
"vm_id": 100,
"type": "qemu",
"vm_cores": 4,
"vm_ram": 4096,
"vm_disk": 20,
"vm_os": "ubuntu",
"vm_version": "22.04",
"vm_app": "jellyfin",
"pve_version": "8.2.2",
"status": "installing",
"random_id": "550e8400"
}
```
### Update/Completion Payload
```json
{
"status": "completed",
"random_id": "550e8400",
"exit_code": 0,
"error_explanation": ""
}
```
---
## Privacy & Opt-Out
### Privacy Policy
Community-Scripts telemetry is designed to be **privacy-respecting**:
- ✅ **Anonymous**: No personal data collected
- ✅ **Session-based**: UUID allows correlation without identification
- ✅ **Aggregated**: Only statistics are stored, never raw logs
- ✅ **Opt-out capable**: Single environment variable disables all telemetry
- ✅ **No tracking**: UUID cannot be linked to user identity
- ✅ **No credentials**: Passwords, SSH keys never transmitted
### Opt-Out Methods
**Method 1: Environment Variable (Single Script)**
```bash
DIAGNOSTICS="no" bash ct/myapp.sh
```
**Method 2: Script Header (Persistent)**
```bash
#!/bin/bash
export DIAGNOSTICS="no"
# Rest of script continues without telemetry
```
**Method 3: System-wide Configuration**
```bash
# In /etc/environment or ~/.bashrc
export DIAGNOSTICS="no"
```
### What Data Is Collected
| Data | Why | Shared? |
|------|-----|---------|
| Container/VM specs (cores, RAM, disk) | Understand deployment patterns | Yes, aggregated |
| OS type/version | Track popular distributions | Yes, aggregated |
| Application name | Understand popular apps | Yes, aggregated |
| Method (standard vs. custom) | Measure feature usage | Yes, aggregated |
| Success/failure status | Identify issues | Yes, aggregated |
| Exit codes | Debug failures | Yes, anonymized |
### What Data Is NOT Collected
- ❌ Container/VM hostnames
- ❌ IP addresses
- ❌ User credentials
- ❌ SSH keys or secrets
- ❌ Application data
- ❌ System logs
- ❌ Any personal information
---
## Error Mapping
### Mapping Strategy
Exit codes are categorized by source:
```
Exit Code Range | Source | Handling
0 | Success | Not reported to API
1-2 | Shell/Script | Generic error
100-101, 255 | Package managers | APT/DPKG specific
126-128 | Command execution | Permission/not found
130, 143 | Signals | User interrupt/termination
137, 139 | Kernel | OOM/segfault
200-231 | Proxmox custom | Container creation issues
210-212 | Python | Python environment issues
231-234 | PostgreSQL | Database connection issues
241-244 | MySQL/MariaDB | Database connection issues
243-249, 254 | Node.js/npm | Runtime errors
251-254 | MongoDB | Database connection issues
```
### Custom Exit Code Usage
Scripts can define custom exit codes:
```bash
# Example: Custom validation failure
if [[ "$CTID" -lt 100 ]]; then
echo "Container ID must be >= 100"
exit 205 # Custom Proxmox code
fi
```
---
## Best Practices
### 1. **Always Initialize RANDOM_UUID**
```bash
# Generate unique session ID for tracking
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)"
# Use first 8 chars for short session ID (logs)
SESSION_ID="${RANDOM_UUID:0:8}"
BUILD_LOG="/tmp/create-lxc-${SESSION_ID}.log"
```
### 2. **Call post_to_api Early**
```bash
# Call post_to_api right after container creation starts
# This tracks attempt, even if installation fails
variables() {
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)"
# ... other variables ...
}
# Later, in main script:
post_to_api # Report container creation started
# ... perform installation ...
post_update_to_api # Report completion
```
### 3. **Handle Graceful Failures**
```bash
# Wrap API calls to handle network issues
if command -v curl &>/dev/null; then
post_to_api || true # Don't fail if API unavailable
else
msg_warn "curl not available, telemetry skipped"
fi
```
### 4. **Respect User Opt-Out**
```bash
# Check DIAGNOSTICS early and skip all API calls if disabled
if [[ "${DIAGNOSTICS}" != "yes" ]]; then
msg_info "Anonymous diagnostics disabled"
return 0 # Skip telemetry
fi
```
### 5. **Maintain Session Consistency**
```bash
# Use same RANDOM_UUID throughout lifecycle
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)"
post_to_api # Initial report
# ... installation ...
post_update_to_api # Final report (same UUID links them)
```
---
## API Integration
### Connecting to API
The API endpoint is:
```
http://api.community-scripts.org/dev/upload
```
### API Response Handling
```bash
# Capture HTTP response code
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD") || true
# Extract status code (last 3 digits)
HTTP_CODE="${RESPONSE: -3}"
if [[ "$HTTP_CODE" == "200" ]]; then
msg_ok "Telemetry submitted successfully"
elif [[ "$HTTP_CODE" == "429" ]]; then
msg_warn "API rate limited, skipping telemetry"
else
msg_info "Telemetry API unreachable (this is OK)"
fi
```
### Network Resilience
API calls are **best-effort** and never block installation:
```bash
# Telemetry should never cause container creation to fail
if post_to_api 2>/dev/null; then
msg_info "Diagnostics transmitted"
fi
# If API unavailable, continue anyway
```
---
## Contributing
### Adding New Exit Codes
1. Document in the appropriate category section
2. Update `explain_exit_code()` in both api.func and error_handler.func
3. Add recovery suggestions
4. Test mapping with scripts that use the new code
### Testing API Integration
```bash
# Test with mock curl (local testing)
DIAGNOSTICS="yes"
RANDOM_UUID="test-uuid-12345678"
curl -X POST http://localhost:8000/dev/upload \
-H "Content-Type: application/json" \
-d '{"test": "payload"}'
# Verify payload structure
post_to_api 2>&1 | head -20
```
### Telemetry Reporting Improvements
Suggestions for improvement:
1. Installation duration tracking
2. Package version compatibility data
3. Feature usage analytics
4. Performance metrics
5. Custom error codes
---
## Notes
- API calls are **silent by default** and never display sensitive information
- Telemetry can be **completely disabled** via `DIAGNOSTICS="no"`
- **RANDOM_UUID must be generated** before calling any post functions
- Exit code mappings are **shared** between api.func and error_handler.func for consistency
- API is **optional** - containers work perfectly without telemetry

View File

@ -1,584 +0,0 @@
# Build.func Wiki
Central LXC container build and configuration orchestration engine providing the main creation workflow, 19-step advanced wizard, defaults system, variable management, and state machine for container lifecycle.
---
## 📋 Table of Contents
- [Overview](#overview)
- [Core Functions](#core-functions)
- [Variable Management](#variable-management)
- [Build Workflow](#build-workflow)
- [Advanced Settings Wizard](#advanced-settings-wizard)
- [Defaults System](#defaults-system)
- [Best Practices](#best-practices)
- [Development Mode](#development-mode)
- [Contributing](#contributing)
---
## Overview
Build.func is the **3800+ line orchestration engine** for LXC container creation:
- ✅ 19-step interactive advanced settings wizard
- ✅ 3-tier defaults precedence system (app → user → global)
- ✅ Variable whitelisting for security
- ✅ State machine workflow management
- ✅ Container resource allocation (CPU, RAM, disk)
- ✅ Storage selection and validation
- ✅ Network configuration (bridge, MAC, VLAN, IPv6)
- ✅ Session tracking and logging
- ✅ Comprehensive pre-flight validation checks
### Execution Flow
```
Script Invocation
variables() → Initialize core variables, SESSION_ID, UUID
build.func functions sourced
Pre-flight checks (maxkeys, template availability)
Create container (pct create ...)
Network configuration
Storage tuning
Installation script execution
Completion & cleanup
```
---
## Core Functions
### `variables()`
**Purpose**: Initializes all core variables, generates unique session ID, and captures application defaults for precedence logic.
**Signature**:
```bash
variables()
```
**Parameters**: None
**Returns**: No explicit return value (sets global variables)
**Variables Initialized**:
| Variable | Source | Purpose |
|----------|--------|---------|
| `NSAPP` | `APP` converted to lowercase | Normalized app name |
| `var_install` | `${NSAPP}-install` | Installation script name |
| `PVEHOST_NAME` | `hostname` | Proxmox hostname |
| `DIAGNOSTICS` | Set to "yes" | Enable telemetry |
| `METHOD` | Set to "default" | Setup method |
| `RANDOM_UUID` | `/proc/sys/kernel/random/uuid` | Session UUID |
| `SESSION_ID` | First 8 chars of UUID | Short session ID |
| `BUILD_LOG` | `/tmp/create-lxc-${SESSION_ID}.log` | Host-side log file |
| `PVEVERSION` | `pveversion` | Proxmox VE version |
| `KERNEL_VERSION` | `uname -r` | System kernel version |
**App Default Capture** (3-tier precedence):
```bash
# Tier 1: App-declared defaults (highest priority)
APP_DEFAULT_CPU=${var_cpu:-}
APP_DEFAULT_RAM=${var_ram:-}
APP_DEFAULT_DISK=${var_disk:-}
# Tier 2: User configuration (~/.community-scripts/defaults)
# Tier 3: Global defaults (built-in)
```
**Dev Mode Setup**:
```bash
# Parse dev_mode early for special behaviors
parse_dev_mode
# If dev_mode=logs, use persistent logging location
if [[ "${DEV_MODE_LOGS}" == "true" ]]; then
mkdir -p /var/log/community-scripts
BUILD_LOG="/var/log/community-scripts/create-lxc-${SESSION_ID}-$(date +%Y%m%d_%H%M%S).log"
fi
```
**Usage Examples**:
```bash
# Example 1: Initialize with default app
APP="Jellyfin"
variables
# Result:
# NSAPP="jellyfin"
# SESSION_ID="550e8400"
# BUILD_LOG="/tmp/create-lxc-550e8400.log"
# Example 2: With dev mode
dev_mode="trace,logs"
APP="MyApp"
variables
# Result:
# Persistent logging enabled
# Bash tracing configured
# BUILD_LOG="/var/log/community-scripts/create-lxc-550e8400-20241201_103000.log"
```
---
### `maxkeys_check()`
**Purpose**: Validates kernel keyring limits don't prevent container creation (prevents "key quota exceeded" errors).
**Signature**:
```bash
maxkeys_check()
```
**Parameters**: None
**Returns**: 0 if limits acceptable; exits with error if exceeded
**Checks**:
- `/proc/sys/kernel/keys/maxkeys` - Maximum keys per user
- `/proc/sys/kernel/keys/maxbytes` - Maximum key bytes per user
- `/proc/key-users` - Current usage for UID 100000 (LXC user)
**Warning Thresholds**:
- Keys: Current >= (maxkeys - 100)
- Bytes: Current >= (maxbytes - 1000)
**Recovery Suggestions**:
```bash
# If warning triggered, suggests sysctl configuration
sysctl -w kernel.keys.maxkeys=200000
sysctl -w kernel.keys.maxbytes=40000000
# Add to persistent config
echo "kernel.keys.maxkeys=200000" >> /etc/sysctl.d/98-community-scripts.conf
sysctl -p
```
**Usage Examples**:
```bash
# Example 1: Healthy keyring usage
maxkeys_check
# Silent success: Usage is normal
# Example 2: Near limit
maxkeys_check
# Warning displayed with suggested sysctl values
# Allows continuation but recommends tuning
# Example 3: Exceeded limit
maxkeys_check
# Error: Exits with code 1
# Suggests increasing limits before retry
```
---
## Variable Management
### `default_var_settings()`
**Purpose**: Loads or creates default variable settings with 3-tier precedence.
**Signature**:
```bash
default_var_settings()
```
**Precedence Order**:
```
1. App-declared defaults (var_cpu, var_ram, var_disk from script)
2. User defaults (~/.community-scripts/defaults.sh)
3. Global built-in defaults
```
**User Defaults Location**:
```bash
~/.community-scripts/defaults.sh
```
**Example User Defaults File**:
```bash
# ~/.community-scripts/defaults.sh
CORE_COUNT=4 # Override default CPU
RAM_SIZE=4096 # Override default RAM (MB)
DISK_SIZE=32 # Override default disk (GB)
BRIDGE="vmbr0" # Preferred bridge
STORAGE="local-lvm" # Preferred storage
DISABLEIPV6="no" # Network preference
VERBOSE="no" # Output preference
```
---
### `load_vars_file()`
**Purpose**: Loads saved container variables from previous configuration.
**Signature**:
```bash
load_vars_file()
```
**Parameters**: None
**Returns**: 0 if loaded; 1 if no saved config found
**File Location**:
```bash
~/.community-scripts/${NSAPP}.vars
```
**Variables Loaded**:
- All whitelist-approved variables (CORE_COUNT, RAM_SIZE, DISK_SIZE, etc.)
- Saved settings from previous container creation
**Usage Examples**:
```bash
# Example 1: Load previous config
if load_vars_file; then
msg_ok "Loaded previous settings for $NSAPP"
else
msg_info "No previous configuration found, using defaults"
fi
# Example 2: Offer to use saved config
# Interactive: Prompts user to confirm previously saved values
```
---
### `maybe_offer_save_app_defaults()`
**Purpose**: Optionally saves current configuration for reuse in future container creations.
**Signature**:
```bash
maybe_offer_save_app_defaults()
```
**Parameters**: None
**Returns**: No explicit return value (saves or skips)
**Behavior**:
- Prompts user if they want to save current settings
- Saves to `~/.community-scripts/${NSAPP}.vars`
- User can load these settings in future runs via `load_vars_file()`
- Saves whitelisted variables only (security)
**Variables Saved**:
- CORE_COUNT, RAM_SIZE, DISK_SIZE
- BRIDGE, STORAGE, MACADDRESS
- VLAN_TAG, DISABLEIPV6
- PASSWORD settings
- Custom network configuration
**Usage Examples**:
```bash
# Example 1: After configuration
configure_container
# ... all settings done ...
maybe_offer_save_app_defaults
# Prompts: "Save these settings for future use? [y/n]"
# If yes: Saves to ~/.community-scripts/jellyfin.vars
# Example 2: Reload in next run
# User runs script again
# Prompted: "Use saved settings from last time? [y/n]"
# If yes: Load_vars_file() populates all variables
```
---
## Build Workflow
### `install_script()`
**Purpose**: Orchestrates container installation workflow inside the LXC container.
**Signature**:
```bash
install_script()
```
**Parameters**: None (uses global `NSAPP` variable)
**Returns**: 0 on success; exits with error code on failure
**Installation Steps**:
1. Copy install script into container
2. Execute via `pct exec $CTID bash /tmp/...`
3. Capture output and exit code
4. Report completion to API
5. Handle errors with cleanup
**Error Handling**:
```bash
# If installation fails:
# - Captures exit code
# - Posts failure to API (if telemetry enabled)
# - Displays error with explanation
# - Offers debug shell (if DEV_MODE_BREAKPOINT)
# - Cleans up container (unless DEV_MODE_KEEP)
```
---
## Advanced Settings Wizard
### `advanced_settings()`
**Purpose**: Interactive 19-step wizard for advanced container configuration.
**Signature**:
```bash
advanced_settings()
```
**Parameters**: None
**Returns**: No explicit return value (populates variables)
**Wizard Steps** (19 total):
1. **CPU Cores** - Allocation (1-128)
2. **RAM Size** - Allocation in MB (256-65536)
3. **Disk Size** - Allocation in GB (1-4096)
4. **Storage** - Select storage backend (local, local-lvm, etc.)
5. **Bridge** - Network bridge (vmbr0, vmbr1, etc.)
6. **MAC Address** - Custom or auto-generated
7. **VLAN Tag** - Optional VLAN configuration
8. **IPv6** - Enable/disable IPv6
9. **Disable IPV6** - Explicit disable option
10. **DHCP** - DHCP or static IP
11. **IP Configuration** - If static: IP/mask
12. **Gateway** - Network gateway
13. **DNS** - DNS server configuration
14. **Hostname** - Container hostname
15. **Root Password** - Set or leave empty (auto-login)
16. **SSH Access** - Enable root SSH
17. **Features** - FUSE, Nesting, keyctl, etc.
18. **Start on Boot** - Autostart configuration
19. **Privileged Mode** - Privileged or unprivileged container
**User Input Methods**:
- Whiptail dialogs (graphical)
- Command-line prompts (fallback)
- Validation of all inputs
- Confirmation summary before creation
**Usage Examples**:
```bash
# Example 1: Run wizard
advanced_settings
# User prompted for each of 19 settings
# Responses stored in variables
# Example 2: Scripted (skip prompts)
CORE_COUNT=4
RAM_SIZE=4096
DISK_SIZE=32
# ... set all 19 variables ...
# advanced_settings() skips prompts since variables already set
```
---
## Defaults System
### 3-Tier Precedence Logic
**Tier 1 (Highest Priority): App-Declared Defaults**
```bash
# In app script header (before default.vars sourced):
var_cpu=4
var_ram=2048
var_disk=20
# If user has higher value in tier 2/3, app value takes precedence
```
**Tier 2 (Medium Priority): User Defaults**
```bash
# In ~/.community-scripts/defaults.sh:
CORE_COUNT=6
RAM_SIZE=4096
DISK_SIZE=32
# Can be overridden by app defaults (tier 1)
```
**Tier 3 (Lowest Priority): Global Built-in Defaults**
```bash
# Built into build.func:
CORE_COUNT=2 (default)
RAM_SIZE=2048 (default, in MB)
DISK_SIZE=8 (default, in GB)
```
**Resolution Algorithm**:
```bash
# For CPU cores (example):
if [ -n "$APP_DEFAULT_CPU" ]; then
CORE_COUNT=$APP_DEFAULT_CPU # Tier 1 wins
elif [ -n "$USER_DEFAULT_CPU" ]; then
CORE_COUNT=$USER_DEFAULT_CPU # Tier 2
else
CORE_COUNT=2 # Tier 3 (global)
fi
```
---
## Best Practices
### 1. **Always Call variables() First**
```bash
#!/bin/bash
source <(curl -fsSL .../build.func)
load_functions
catch_errors
# Must be first real function call
variables
# Then safe to use SESSION_ID, BUILD_LOG, etc.
msg_info "Building container (Session: $SESSION_ID)"
```
### 2. **Declare App Defaults Before Sourcing build.func**
```bash
#!/bin/bash
# Declare app defaults BEFORE sourcing build.func
var_cpu=4
var_ram=4096
var_disk=20
source <(curl -fsSL .../build.func)
variables # These defaults are captured
# Now var_cpu, var_ram, var_disk are in APP_DEFAULT_*
```
### 3. **Use Variable Whitelisting**
```bash
# Only these variables are allowed to be saved/loaded:
WHITELIST="CORE_COUNT RAM_SIZE DISK_SIZE BRIDGE STORAGE MACADDRESS VLAN_TAG DISABLEIPV6"
# Sensitive variables are NEVER saved:
# PASSWORD, SSH keys, API tokens, etc.
```
### 4. **Check Pre-flight Conditions**
```bash
variables
maxkeys_check # Validate kernel limits
pve_check # Validate PVE version
arch_check # Validate architecture
# Only proceed after all checks pass
msg_ok "Pre-flight checks passed"
```
### 5. **Track Sessions**
```bash
# Use SESSION_ID in all logs
BUILD_LOG="/tmp/create-lxc-${SESSION_ID}.log"
# Keep logs for troubleshooting
# Can be reviewed later: tail -50 /tmp/create-lxc-550e8400.log
```
---
## Development Mode
### Dev Mode Variables
Set via environment or in script:
```bash
dev_mode="trace,keep,breakpoint"
parse_dev_mode
# Enables:
# - DEV_MODE_TRACE=true (bash -x)
# - DEV_MODE_KEEP=true (never delete container)
# - DEV_MODE_BREAKPOINT=true (shell on error)
```
### Debug Container Creation
```bash
# Run with all debugging enabled
dev_mode="trace,keep,logs" bash ct/jellyfin.sh
# Then review logs:
tail -200 /var/log/community-scripts/create-lxc-*.log
# Container stays running (DEV_MODE_KEEP)
# Allows ssh inspection: ssh root@<container-ip>
```
---
## Contributing
### Adding New Wizard Steps
1. Add step number and variable to documentation
2. Add whiptail prompt in `advanced_settings()`
3. Add validation logic
4. Add to whitelist if user should save it
5. Update documentation with examples
### Extending Defaults System
To add new tier or change precedence:
1. Update 3-tier logic section
2. Modify resolution algorithm
3. Document new precedence order
4. Update whitelist accordingly
### Testing Build Workflow
```bash
# Test with dry-run mode
dev_mode="dryrun" bash ct/myapp.sh
# Shows all commands without executing
# Test with keep mode
dev_mode="keep" bash ct/myapp.sh
# Container stays if fails, allows inspection
```
---
## Notes
- Build.func is **large and complex** (3800+ lines) - handles most container creation logic
- Variables are **passed to container** via pct set/environment
- Session ID **enables request tracking** across distributed logs
- Defaults system is **flexible** (3-tier precedence)
- Pre-flight checks **prevent many common errors**

View File

@ -1,571 +0,0 @@
# Cloud-Init.func Wiki
VM cloud-init configuration and first-boot setup module for Proxmox VEs, providing automatic system initialization, network configuration, user account setup, and SSH key management for virtual machines.
---
## 📋 Table of Contents
- [Overview](#overview)
- [Cloud-Init Fundamentals](#cloud-init-fundamentals)
- [Main Configuration Functions](#main-configuration-functions)
- [Interactive Configuration](#interactive-configuration)
- [Configuration Parameters](#configuration-parameters)
- [Data Formats](#data-formats)
- [Best Practices](#best-practices)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
---
## Overview
Cloud-init.func provides **VM first-boot automation** infrastructure:
- ✅ Cloud-init drive creation (IDE2 or SCSI fallback)
- ✅ User account and password configuration
- ✅ SSH public key injection
- ✅ Network configuration (DHCP or static IP)
- ✅ DNS and search domain setup
- ✅ Interactive whiptail-based configuration
- ✅ Credential file generation and display
- ✅ Support for Debian nocloud and Ubuntu cloud-init
- ✅ System package upgrade on first boot
### Integration Pattern
```bash
# In Proxmox VM creation scripts
source <(curl -fsSL .../cloud-init.func)
# Basic setup:
setup_cloud_init "$VMID" "$STORAGE" "$HOSTNAME" "yes"
# Interactive setup:
configure_cloud_init_interactive "root"
setup_cloud_init "$VMID" "$STORAGE" "$HOSTNAME" "$CLOUDINIT_ENABLE"
```
### First-Boot Sequence
```
VM Power On
Cloud-init boot phase
Read cloud-init config
Create/modify user account
Install SSH keys
Configure network
Set DNS/search domain
Upgrade packages (if configured)
Boot completion
```
---
## Cloud-Init Fundamentals
### What is Cloud-Init?
Cloud-init is a system that runs on the first boot of a VM/Instance to:
- Create user accounts
- Set passwords
- Configure networking
- Install SSH keys
- Run custom scripts
- Manage system configuration
### Proxmox Cloud-Init Integration
Proxmox VE supports cloud-init natively via:
- **Cloud-init drive**: IDE2 or SCSI disk with cloud-init data
- **QEMU parameters**: User, password, SSH keys, IP configuration
- **First-boot services**: systemd services that execute on first boot
### Nocloud Data Source
Proxmox uses the **nocloud** data source (no internet required):
- Configuration stored on local cloud-init drive
- No external network call needed
- Works in isolated networks
- Suitable for private infrastructure
---
## Main Configuration Functions
### `setup_cloud_init()`
**Purpose**: Configures Cloud-init for automatic VM first-boot setup.
**Signature**:
```bash
setup_cloud_init()
```
**Parameters**:
- `$1` - VMID (required, e.g., 100)
- `$2` - Storage name (required, e.g., local, local-lvm)
- `$3` - Hostname (optional, default: vm-${VMID})
- `$4` - Enable Cloud-Init (yes/no, default: no)
- `$5` - User (optional, default: root)
- `$6` - Network mode (dhcp/static, default: dhcp)
- `$7` - Static IP (optional, CIDR format: 192.168.1.100/24)
- `$8` - Gateway (optional)
- `$9` - Nameservers (optional, space-separated, default: 1.1.1.1 8.8.8.8)
**Returns**: 0 on success, 1 on failure; exits if not enabled
**Behavior**:
```bash
# If enable="no":
# Returns immediately (skips all configuration)
# If enable="yes":
# 1. Create cloud-init drive (IDE2, fallback to SCSI1)
# 2. Set user account
# 3. Generate random password
# 4. Configure network
# 5. Set DNS servers
# 6. Add SSH keys (if available)
# 7. Save credentials to file
# 8. Export variables for calling script
```
**Operations**:
| Operation | Command | Purpose |
|-----------|---------|---------|
| Create drive | `qm set $vmid --ide2 $storage:cloudinit` | Cloud-init data disk |
| Set user | `qm set $vmid --ciuser $ciuser` | Initial user |
| Set password | `qm set $vmid --cipassword $cipassword` | Auto-generated |
| SSH keys | `qm set $vmid --sshkeys $SSH_KEYS_FILE` | Pre-injected |
| DHCP network | `qm set $vmid --ipconfig0 ip=dhcp` | Dynamic IP |
| Static network | `qm set $vmid --ipconfig0 ip=192.168.1.100/24,gw=192.168.1.1` | Fixed IP |
| DNS | `qm set $vmid --nameserver $servers` | 1.1.1.1 8.8.8.8 |
| Search domain | `qm set $vmid --searchdomain local` | Local domain |
**Environment Variables Set**:
- `CLOUDINIT_USER` - Username configured
- `CLOUDINIT_PASSWORD` - Generated password (in memory only)
- `CLOUDINIT_CRED_FILE` - Path to credentials file
**Usage Examples**:
```bash
# Example 1: Basic DHCP setup
VMID=100
STORAGE="local-lvm"
setup_cloud_init "$VMID" "$STORAGE" "myvm" "yes"
# Result: VM configured with DHCP, random password, root user
# Example 2: Static IP configuration
setup_cloud_init "$VMID" "$STORAGE" "myvm" "yes" "root" \
"static" "192.168.1.100/24" "192.168.1.1" "1.1.1.1 8.8.8.8"
# Result: VM configured with static IP, specific DNS
# Example 3: Disabled (no cloud-init)
setup_cloud_init "$VMID" "$STORAGE" "myvm" "no"
# Result: Function returns immediately, no configuration
```
---
### `configure_cloud_init_interactive()`
**Purpose**: Interactive whiptail-based configuration prompts for user preferences.
**Signature**:
```bash
configure_cloud_init_interactive()
```
**Parameters**:
- `$1` - Default user (optional, default: root)
**Returns**: 0 on success, 1 if whiptail unavailable; exports configuration variables
**Environment Variables Exported**:
- `CLOUDINIT_ENABLE` - Enable (yes/no)
- `CLOUDINIT_USER` - Username
- `CLOUDINIT_NETWORK_MODE` - dhcp or static
- `CLOUDINIT_IP` - Static IP (if static mode)
- `CLOUDINIT_GW` - Gateway (if static mode)
- `CLOUDINIT_DNS` - DNS servers (space-separated)
**User Prompts** (5 questions):
1. **Enable Cloud-Init?** (yes/no)
2. **Username?** (default: root)
3. **Network Mode?** (DHCP or static)
4. **Static IP?** (if static, CIDR format)
5. **Gateway IP?** (if static)
6. **DNS Servers?** (default: 1.1.1.1 8.8.8.8)
**Fallback Behavior**:
- If whiptail unavailable: Shows warning and returns 1
- Auto-defaults to DHCP if error occurs
- Non-interactive: Can be skipped in scripts
**Implementation Pattern**:
```bash
configure_cloud_init_interactive() {
local default_user="${1:-root}"
# Check whiptail availability
if ! command -v whiptail >/dev/null 2>&1; then
echo "Warning: whiptail not available"
export CLOUDINIT_ENABLE="no"
return 1
fi
# Ask enable
if ! (whiptail --backtitle "Proxmox VE Helper Scripts" --title "CLOUD-INIT" \
--yesno "Enable Cloud-Init for VM configuration?" 16 68); then
export CLOUDINIT_ENABLE="no"
return 0
fi
export CLOUDINIT_ENABLE="yes"
# Username
CLOUDINIT_USER=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox \
"Cloud-Init Username" 8 58 "$default_user" --title "USERNAME" 3>&1 1>&2 2>&3)
export CLOUDINIT_USER="${CLOUDINIT_USER:-$default_user}"
# Network mode
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "NETWORK MODE" \
--yesno "Use DHCP for network configuration?" 10 58); then
export CLOUDINIT_NETWORK_MODE="dhcp"
else
export CLOUDINIT_NETWORK_MODE="static"
# ... prompt for static IP and gateway ...
fi
# DNS servers
CLOUDINIT_DNS=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox \
"DNS Servers (space-separated)" 8 58 "1.1.1.1 8.8.8.8" --title "DNS" 3>&1 1>&2 2>&3)
export CLOUDINIT_DNS
}
```
**Usage Examples**:
```bash
# Example 1: Interactive configuration
configure_cloud_init_interactive "root"
# Prompts user for all settings interactively
# Exports variables for use in setup_cloud_init()
# Example 2: With custom default user
configure_cloud_init_interactive "debian"
# Suggests "debian" as default username
# Example 3: In script workflow
configure_cloud_init_interactive "$DEFAULT_USER"
setup_cloud_init "$VMID" "$STORAGE" "$HOSTNAME" "$CLOUDINIT_ENABLE" "$CLOUDINIT_USER"
# User configures interactively, then script sets up VM
```
---
## Configuration Parameters
### VMID (Virtual Machine ID)
- **Type**: Integer (100-2147483647)
- **Required**: Yes
- **Example**: `100`
- **Validation**: Must be unique, >= 100 on Proxmox
### Storage
- **Type**: String (storage backend name)
- **Required**: Yes
- **Examples**: `local`, `local-lvm`, `ceph-rbd`
- **Validation**: Must exist in Proxmox
- **Cloud-init Drive**: Placed on this storage
### Hostname
- **Type**: String (valid hostname)
- **Required**: No (defaults to vm-${VMID})
- **Example**: `myvm`, `web-server-01`
- **Format**: Lowercase, alphanumeric, hyphens allowed
### User
- **Type**: String (username)
- **Required**: No (defaults: root)
- **Example**: `root`, `ubuntu`, `debian`
- **Cloud-init**: User account created on first boot
### Network Mode
- **Type**: Enum (dhcp, static)
- **Default**: dhcp
- **Options**:
- `dhcp` - Dynamic IP from DHCP server
- `static` - Manual IP configuration
### Static IP
- **Format**: CIDR notation (192.168.1.100/24)
- **Example**: `192.168.1.50/24`, `10.0.0.5/8`
- **Validation**: Valid IP and netmask
- **Required**: If network mode = static
### Gateway
- **Format**: IP address (192.168.1.1)
- **Example**: `192.168.1.1`, `10.0.0.1`
- **Validation**: Valid IP
- **Required**: If network mode = static
### Nameservers
- **Format**: Space-separated IPs
- **Default**: `1.1.1.1 8.8.8.8`
- **Example**: `1.1.1.1 8.8.8.8 9.9.9.9`
### DNS Search Domain
- **Type**: String
- **Default**: `local`
- **Example**: `example.com`, `internal.corp`
---
## Data Formats
### Cloud-Init Credentials File
Generated at: `/tmp/${hostname}-${vmid}-cloud-init-credentials.txt`
**Format**:
```
========================================
Cloud-Init Credentials
========================================
VM ID: 100
Hostname: myvm
Created: Tue Dec 01 10:30:00 UTC 2024
Username: root
Password: s7k9mL2pQ8wX
Network: dhcp
DNS: 1.1.1.1 8.8.8.8
========================================
SSH Access (if keys configured):
ssh root@<vm-ip>
Proxmox UI Configuration:
VM 100 > Cloud-Init > Edit
- User, Password, SSH Keys
- Network (IP Config)
- DNS, Search Domain
========================================
```
### Proxmox Cloud-Init Config
Stored in: `/etc/pve/nodes/<node>/qemu-server/<vmid>.conf`
**Relevant Settings**:
```
ide2: local-lvm:vm-100-cloudinit,media=cdrom
ciuser: root
cipassword: (encrypted)
ipconfig0: ip=dhcp
nameserver: 1.1.1.1 8.8.8.8
searchdomain: local
```
### Network Configuration Examples
**DHCP**:
```bash
qm set 100 --ipconfig0 "ip=dhcp"
```
**Static IPv4**:
```bash
qm set 100 --ipconfig0 "ip=192.168.1.100/24,gw=192.168.1.1"
```
**Static IPv6**:
```bash
qm set 100 --ipconfig0 "ip6=2001:db8::100/64,gw6=2001:db8::1"
```
**Dual Stack (IPv4 + IPv6)**:
```bash
qm set 100 --ipconfig0 "ip=192.168.1.100/24,gw=192.168.1.1,ip6=2001:db8::100/64,gw6=2001:db8::1"
```
---
## Best Practices
### 1. **Always Configure SSH Keys**
```bash
# Ensure SSH keys available before cloud-init setup
CLOUDINIT_SSH_KEYS="/root/.ssh/authorized_keys"
if [ ! -f "$CLOUDINIT_SSH_KEYS" ]; then
mkdir -p /root/.ssh
# Generate or import SSH keys
fi
setup_cloud_init "$VMID" "$STORAGE" "$HOSTNAME" "yes"
```
### 2. **Save Credentials Securely**
```bash
# After setup_cloud_init():
# Credentials file generated at $CLOUDINIT_CRED_FILE
# Copy to secure location:
cp "$CLOUDINIT_CRED_FILE" "/root/vm-credentials/"
chmod 600 "/root/vm-credentials/$(basename $CLOUDINIT_CRED_FILE)"
# Or display to user:
cat "$CLOUDINIT_CRED_FILE"
```
### 3. **Use Static IPs for Production**
```bash
# DHCP - suitable for dev/test
setup_cloud_init "$VMID" "$STORAGE" "$HOSTNAME" "yes" "root" "dhcp"
# Static - suitable for production
setup_cloud_init "$VMID" "$STORAGE" "$HOSTNAME" "yes" "root" \
"static" "192.168.1.100/24" "192.168.1.1"
```
### 4. **Validate Network Configuration**
```bash
# Before setting up cloud-init, ensure:
# - Gateway IP is reachable
# - IP address not in use
# - DNS servers are accessible
ping -c 1 "$GATEWAY" || msg_error "Gateway unreachable"
```
### 5. **Test First Boot**
```bash
# After cloud-init setup:
qm start "$VMID"
# Wait for boot
sleep 10
# Check cloud-init status
qm exec "$VMID" cloud-init status
# Verify network configuration
qm exec "$VMID" hostname -I
```
---
## Troubleshooting
### Cloud-Init Not Applying
```bash
# Inside VM:
cloud-init status # Show cloud-init status
cloud-init analyze # Analyze cloud-init boot
cloud-init query # Query cloud-init datasource
# Check logs:
tail -100 /var/log/cloud-init-output.log
tail -100 /var/log/cloud-init.log
```
### Network Not Configured
```bash
# Verify cloud-init config in Proxmox:
cat /etc/pve/nodes/$(hostname)/qemu-server/100.conf
# Check cloud-init drive:
qm config 100 | grep ide2
# In VM, verify cloud-init wrote config:
cat /etc/netplan/99-cloudinit.yaml
```
### SSH Keys Not Installed
```bash
# Verify SSH keys set in Proxmox:
qm config 100 | grep sshkeys
# In VM, check SSH directory:
ls -la /root/.ssh/
cat /root/.ssh/authorized_keys
```
### Password Not Set
```bash
# Regenerate cloud-init drive:
qm set 100 --delete ide2 # Remove cloud-init drive
qm set 100 --ide2 local-lvm:vm-100-cloudinit,media=cdrom # Re-create
# Set password again:
qm set 100 --cipassword "newpassword"
```
---
## Contributing
### Adding New Configuration Options
1. Add parameter to `setup_cloud_init()` function signature
2. Add validation for parameter
3. Add `qm set` command to apply configuration
4. Update documentation with examples
5. Test on actual Proxmox VE
### Enhancing Interactive Configuration
1. Add new whiptail dialog to `configure_cloud_init_interactive()`
2. Export variable for use in setup
3. Add validation logic
4. Test with various input scenarios
### Supporting New Data Sources
Beyond nocloud, could support:
- ConfigDrive (cloud-init standard)
- ESXi (if supporting vSphere)
- Hyper-V (if supporting Windows)
---
## Notes
- Cloud-init requires **QEMU guest agent** for optimal functionality
- Network configuration applied **on first boot only**
- Credentials file contains **sensitive information** - keep secure
- SSH keys are **persisted** and not displayed in credentials file
- Cloud-init is **optional** - VMs work without it

View File

@ -1,918 +0,0 @@
# Core.func Wiki
The foundational utility library providing colors, formatting, validation checks, message output, and execution helpers used across all Community-Scripts ecosystem projects.
---
## 📋 Table of Contents
- [Overview](#overview)
- [Initialization Functions](#initialization-functions)
- [Color & Formatting](#color--formatting)
- [Validation Checks](#validation-checks)
- [Message Output Functions](#message-output-functions)
- [Execution Helpers](#execution-helpers)
- [Development Mode](#development-mode)
- [Best Practices](#best-practices)
- [Contributing](#contributing)
---
## Overview
Core.func provides essential utilities for consistent behavior across all Community-Scripts:
- ✅ ANSI color codes for styled terminal output
- ✅ Standard icons and formatting for UI consistency
- ✅ System validation checks (root, PVE version, architecture)
- ✅ Colored message functions (info, ok, error, warn)
- ✅ Silent command execution with log redirection
- ✅ Spinner animations for long-running operations
- ✅ Development mode support (trace, breakpoint, dry-run)
- ✅ Guard clauses to prevent reloading
### Integration Pattern
```bash
#!/bin/bash
source <(curl -fsSL https://git.community-scripts.org/.../core.func)
load_functions # Initialize all color/formatting/defaults
root_check # Validate prerequisites
pve_check # Check Proxmox VE version
```
---
## Initialization Functions
### `load_functions()`
**Purpose**: Initializes all core utility function groups. Must be called once before using any core utilities.
**Signature**:
```bash
load_functions()
```
**Parameters**: None
**Returns**: No explicit return value (sets global variables)
**Guard Mechanism**:
```bash
[[ -n "${__FUNCTIONS_LOADED:-}" ]] && return # Prevent re-loading
_CORE_FUNC_LOADED=1 # Mark as loaded
```
**Initializes** (in order):
1. `color()` - ANSI color codes
2. `formatting()` - Text formatting helpers
3. `icons()` - Emoji/symbol constants
4. `default_vars()` - Retry and timeout settings
5. `set_std_mode()` - Verbose/silent mode
**Usage Examples**:
```bash
# Example 1: Typical initialization
source <(curl -fsSL .../core.func)
load_functions # Safe to call multiple times
msg_info "Starting setup" # Now colors are available
# Example 2: Safe multiple sourcing
source <(curl -fsSL .../core.func)
load_functions
source <(curl -fsSL .../tools.func)
load_functions # Silently returns (already loaded)
```
---
### `color()`
**Purpose**: Defines ANSI escape codes for colored terminal output.
**Signature**:
```bash
color()
```
**Color Variables Defined**:
| Variable | Code | Effect | Use Case |
|----------|------|--------|----------|
| `YW` | `\033[33m` | Yellow | Warnings, secondary info |
| `YWB` | `\e[93m` | Bright Yellow | Emphasis, bright warnings |
| `BL` | `\033[36m` | Cyan/Blue | Hostnames, IPs, values |
| `RD` | `\033[01;31m` | Bright Red | Errors, critical alerts |
| `GN` | `\033[1;92m` | Bright Green | Success, OK status |
| `DGN` | `\033[32m` | Dark Green | Background, secondary success |
| `BGN` | `\033[4;92m` | Green with underline | Highlights |
| `CL` | `\033[m` | Clear | Reset to default |
**Usage Examples**:
```bash
# Example 1: Colored output
color
echo -e "${RD}Error: File not found${CL}"
# Output: "Error: File not found" (in red)
# Example 2: Multiple colors on one line
echo -e "${YW}Warning:${CL} ${BL}$HOSTNAME${CL} is running low on ${RD}RAM${CL}"
# Example 3: In functions
print_status() {
echo -e "${GN}✓${CL} Operation completed"
}
```
---
### `formatting()`
**Purpose**: Defines formatting helpers for terminal output.
**Signature**:
```bash
formatting()
```
**Formatting Variables Defined**:
| Variable | Escape Code | Purpose |
|----------|------------|---------|
| `BFR` | `\r\033[K` | Backspace and clear line |
| `BOLD` | `\033[1m` | Bold text |
| `HOLD` | ` ` (space) | Spacing |
| `TAB` | ` ` (2 spaces) | Indentation |
| `TAB3` | ` ` (6 spaces) | Larger indentation |
**Usage Examples**:
```bash
# Example 1: Overwrite previous line (progress)
for i in {1..10}; do
echo -en "${BFR}Progress: $i/10"
sleep 1
done
# Example 2: Bold emphasis
echo -e "${BOLD}Important:${CL} This requires attention"
# Example 3: Structured indentation
echo "Main Item:"
echo -e "${TAB}Sub-item 1"
echo -e "${TAB}Sub-item 2"
```
---
### `icons()`
**Purpose**: Defines symbolic emoji and icon constants used for UI consistency.
**Signature**:
```bash
icons()
```
**Icon Variables Defined**:
| Variable | Icon | Use |
|----------|------|-----|
| `CM` | ✔️ | Success/checkmark |
| `CROSS` | ✖️ | Error/cross |
| `INFO` | 💡 | Information |
| `OS` | 🖥️ | Operating system |
| `CONTAINERTYPE` | 📦 | Container |
| `DISKSIZE` | 💾 | Disk/storage |
| `CPUCORE` | 🧠 | CPU |
| `RAMSIZE` | 🛠️ | RAM |
| `HOSTNAME` | 🏠 | Hostname |
| `BRIDGE` | 🌉 | Network bridge |
| `NETWORK` | 📡 | Network |
| `GATEWAY` | 🌐 | Gateway |
| `CREATING` | 🚀 | Creating |
| `ADVANCED` | 🧩 | Advanced/options |
| `HOURGLASS` | ⏳ | Wait/timer |
---
### `default_vars()`
**Purpose**: Sets default retry and timing variables for system operations.
**Signature**:
```bash
default_vars()
```
**Variables Set**:
- `RETRY_NUM=10` - Maximum retry attempts
- `RETRY_EVERY=3` - Seconds between retries
- `i=$RETRY_NUM` - Counter for retry loops
**Usage Examples**:
```bash
# Example 1: Retry loop with defaults
RETRY_NUM=10
RETRY_EVERY=3
i=$RETRY_NUM
while [ $i -gt 0 ]; do
if check_network; then
break
fi
echo "Retrying... ($i attempts left)"
sleep $RETRY_EVERY
i=$((i - 1))
done
# Example 2: Custom retry values
RETRY_NUM=5 # Try 5 times
RETRY_EVERY=2 # Wait 2 seconds between attempts
```
---
### `set_std_mode()`
**Purpose**: Configures output verbosity and optional debug tracing based on environment variables.
**Signature**:
```bash
set_std_mode()
```
**Behavior**:
- If `VERBOSE=yes`: `STD=""` (show all output)
- If `VERBOSE=no`: `STD="silent"` (suppress output via silent() wrapper)
- If `DEV_MODE_TRACE=true`: Enable `set -x` bash tracing
**Variables Set**:
- `STD` - Command prefix for optional output suppression
**Usage Examples**:
```bash
# Example 1: Verbose output
VERBOSE="yes"
set_std_mode
$STD apt-get update # Shows all apt output
# Output: All package manager messages displayed
# Example 2: Silent output
VERBOSE="no"
set_std_mode
$STD apt-get update # Silently updates, logs to file
# Output: Only progress bar or errors shown
# Example 3: Debug tracing
DEV_MODE_TRACE="true"
set_std_mode
# bash shows every command before executing: +(script.sh:123): function_name(): cmd
```
---
### `parse_dev_mode()`
**Purpose**: Parses comma-separated dev_mode string to enable development features.
**Signature**:
```bash
parse_dev_mode()
```
**Parameters**: None (uses `$dev_mode` environment variable)
**Supported Flags**:
- `motd` - Setup SSH/MOTD before installation
- `keep` - Never delete container on failure
- `trace` - Enable bash set -x tracing
- `pause` - Pause after each msg_info step
- `breakpoint` - Open shell on error instead of cleanup
- `logs` - Persist logs to /var/log/community-scripts/
- `dryrun` - Show commands without executing
**Environment Variables Set**:
- `DEV_MODE_MOTD=false|true`
- `DEV_MODE_KEEP=false|true`
- `DEV_MODE_TRACE=false|true`
- `DEV_MODE_PAUSE=false|true`
- `DEV_MODE_BREAKPOINT=false|true`
- `DEV_MODE_LOGS=false|true`
- `DEV_MODE_DRYRUN=false|true`
**Usage Examples**:
```bash
# Example 1: Enable debugging
dev_mode="trace,logs"
parse_dev_mode
# Enables bash tracing and persistent logging
# Example 2: Keep container on error
dev_mode="keep,breakpoint"
parse_dev_mode
# Container never deleted on error, opens shell at breakpoint
# Example 3: Multiple modes
dev_mode="motd,keep,trace,pause"
parse_dev_mode
# All four development modes active
```
---
## Color & Formatting
### Color Codes
**Standard Colors**:
```bash
${YW} # Yellow (warnings)
${RD} # Red (errors)
${GN} # Green (success)
${BL} # Blue/Cyan (values)
${CL} # Clear (reset)
```
**Example Combinations**:
```bash
echo -e "${YW}Warning:${CL} ${RD}Critical${CL} at ${BL}$(date)${CL}"
# Output: "Warning: Critical at 2024-12-01 10:30:00" (colored appropriately)
```
---
## Validation Checks
### `shell_check()`
**Purpose**: Verifies script is running under Bash (not sh, dash, etc.).
**Signature**:
```bash
shell_check()
```
**Parameters**: None
**Returns**: 0 if Bash; exits with error if not
**Behavior**:
- Checks `ps -p $$ -o comm=` (current shell command)
- Exits with error message if not "bash"
- Clears screen for better error visibility
**Usage Examples**:
```bash
#!/bin/bash
source <(curl -fsSL .../core.func)
load_functions
shell_check # Exits if run with: sh script.sh or dash script.sh
# If run correctly: bash script.sh - continues
# If run with sh: Displays error and exits
```
---
### `root_check()`
**Purpose**: Verifies script is running with root privileges directly (not via sudo).
**Signature**:
```bash
root_check()
```
**Parameters**: None
**Returns**: 0 if root directly; exits with error if not
**Checks**:
- `id -u` must be 0 (root)
- Parent process (`$PPID`) must not be "sudo"
**Why**: Some scripts require genuine root context, not sudo-elevated user shell.
**Usage Examples**:
```bash
#!/bin/bash
# Must run as root directly, not via sudo
source <(curl -fsSL .../core.func)
load_functions
root_check # Will fail if: sudo bash script.sh
# Correct: bash script.sh (from root shell on Proxmox)
```
---
### `pve_check()`
**Purpose**: Validates Proxmox VE version compatibility.
**Signature**:
```bash
pve_check()
```
**Parameters**: None
**Returns**: 0 if supported version; exits with error if not
**Supported Versions**:
- PVE 8.0 - 8.9
- PVE 9.0 - 9.1
**Version Detection**:
```bash
PVE_VER=$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')
# Example: "pveversion" → "pve-manager/8.2.2/550e8400-e29b"
# Extracted: "8.2.2" → "8"
```
**Usage Examples**:
```bash
# Example 1: On supported PVE 8.2
bash ct/app.sh
# Passes: 8.2 is in range 8.0-8.9
# Example 2: On unsupported PVE 7.4
bash ct/app.sh
# Error: "This version of Proxmox VE is not supported"
# Example 3: On future unsupported PVE 10.0
bash ct/app.sh
# Error: "This version of Proxmox VE is not yet supported"
```
---
### `arch_check()`
**Purpose**: Validates system architecture is amd64/x86_64 (not ARM/PiMox).
**Signature**:
```bash
arch_check()
```
**Parameters**: None
**Returns**: 0 if amd64; exits with error if not
**Behavior**:
- Checks `dpkg --print-architecture`
- Exits if not "amd64"
- Provides link to ARM64-compatible scripts
**Usage Examples**:
```bash
# Example 1: On x86_64 server
arch_check
# Passes silently
# Example 2: On PiMox (ARM64)
arch_check
# Error: "This script will not work with PiMox!"
# Suggests: https://github.com/asylumexp/Proxmox
```
---
### `ssh_check()`
**Purpose**: Detects SSH connection and warns if connecting remotely (recommends Proxmox console).
**Signature**:
```bash
ssh_check()
```
**Parameters**: None
**Returns**: No explicit return value (warning only, does not exit)
**Behavior**:
- Checks `$SSH_CLIENT` environment variable
- Analyzes client IP to determine if local or remote
- Skips warning for local/same-subnet connections
- Warns for external connections
**Usage Examples**:
```bash
# Example 1: Local SSH (Proxmox WebUI console)
ssh_check
# No warning: Client is localhost (127.0.0.1)
# Example 2: External SSH over Internet
ssh -l root 1.2.3.4 "bash script.sh"
# Warning: "Running via external SSH (client: 1.2.3.4)"
# Recommends Proxmox Shell (Console) instead
```
---
## Message Output Functions
### `msg_info()`
**Purpose**: Displays informational message with icon and yellow color.
**Signature**:
```bash
msg_info()
```
**Parameters**:
- `$@` - Message text (concatenated with spaces)
**Format**: `[] Message text` (yellow)
**Usage Examples**:
```bash
msg_info "Starting container setup"
# Output: Starting container setup
msg_info "Updating OS packages" "for debian:12"
# Output: Updating OS packages for debian:12
```
---
### `msg_ok()`
**Purpose**: Displays success message with checkmark and green color.
**Signature**:
```bash
msg_ok()
```
**Parameters**:
- `$@` - Message text
**Format**: `[✔️] Message text` (green)
**Usage Examples**:
```bash
msg_ok "Container created"
# Output: ✔️ Container created (in green)
msg_ok "Network Connected: 10.0.3.50"
# Output: ✔️ Network Connected: 10.0.3.50
```
---
### `msg_error()`
**Purpose**: Displays error message with cross icon and red color. Does not exit.
**Signature**:
```bash
msg_error()
```
**Parameters**:
- `$@` - Message text
**Format**: `[✖️] Message text` (red)
**Usage Examples**:
```bash
msg_error "Container ID already in use"
# Output: ✖️ Container ID already in use (in red)
```
---
### `msg_warn()`
**Purpose**: Displays warning message with yellow color.
**Signature**:
```bash
msg_warn()
```
**Parameters**:
- `$@` - Message text
**Format**: `[⚠️] Message text` (yellow/orange)
**Usage Examples**:
```bash
msg_warn "This will delete all data"
# Output: ⚠️ This will delete all data
```
---
## Execution Helpers
### `silent()`
**Purpose**: Executes command with output redirected to log file. On error: displays last 10 lines of log and exits.
**Signature**:
```bash
silent()
```
**Parameters**:
- `$@` - Command and arguments to execute
**Returns**: 0 on success; exits with original error code on failure
**Environment Effects**:
- Temporarily disables `set -e` and error trap to capture exit code
- Re-enables after command completes
- Logs to `$BUILD_LOG` or `$INSTALL_LOG`
**Log Display On Error**:
```bash
--- Last 10 lines of silent log ---
[log output]
-----------------------------------
```
**Usage Examples**:
```bash
# Example 1: Suppress package manager output
silent apt-get update
# Output: suppressed, logged to file
# Example 2: Conditional display on error
silent curl -fsSL https://api.example.com
# If curl fails: shows last 10 log lines and exits
# Example 3: Verbose mode shows everything
VERBOSE="yes"
silent apt-get update # Shows all output (STD is empty)
```
---
### `spinner()`
**Purpose**: Displays animated spinner with rotating characters during long operations.
**Signature**:
```bash
spinner()
```
**Parameters**: None (uses `$SPINNER_MSG` environment variable)
**Animation**:
```
⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏ (repeating)
```
**Environment Variables**:
- `SPINNER_MSG` - Text to display with spinner
**Lifecycle**:
```bash
# Start spinner in background
SPINNER_MSG="Downloading..."
spinner &
SPINNER_PID=$!
# ... do long operation ...
# Stop spinner
stop_spinner
echo "Done!"
```
**Usage Examples**:
```bash
# Example 1: Long operation with spinner
SPINNER_MSG="Building container..."
spinner &
SPINNER_PID=$!
sleep 10 # Simulate work
stop_spinner
msg_ok "Container created"
```
---
### `clear_line()`
**Purpose**: Clears current terminal line and moves cursor to beginning.
**Signature**:
```bash
clear_line()
```
**Parameters**: None
**Implementation**: Uses `tput` or ANSI escape codes
**Usage Examples**:
```bash
for file in *.sh; do
echo -n "Processing $file..."
process_file "$file"
clear_line
done
# Each file overwrites previous line
```
---
### `stop_spinner()`
**Purpose**: Stops running spinner process and cleans up temporary files.
**Signature**:
```bash
stop_spinner()
```
**Parameters**: None (reads `$SPINNER_PID` or `/tmp/.spinner.pid`)
**Cleanup**:
- Graceful kill of spinner process
- Force kill (-9) if needed
- Removes `/tmp/.spinner.pid` temp file
- Resets terminal state
**Usage Examples**:
```bash
# Example 1: Simple stop
spinner &
SPINNER_PID=$!
sleep 5
stop_spinner
# Example 2: In trap handler
trap 'stop_spinner' EXIT
spinner &
```
---
## Development Mode
### Enabling Development Features
**Via Environment Variable**:
```bash
dev_mode="trace,keep,breakpoint" bash ct/myapp.sh
```
**Via Script Header**:
```bash
#!/bin/bash
export dev_mode="trace,logs,pause"
source <(curl -fsSL .../core.func)
load_functions
parse_dev_mode
```
### Available Modes
| Mode | Effect |
|------|--------|
| `trace` | Enable bash -x tracing (verbose command logging) |
| `keep` | Never delete container on error (for debugging) |
| `logs` | Persist all logs to /var/log/community-scripts/ |
| `pause` | Pause after each msg_info step (manual stepping) |
| `breakpoint` | Open shell on error instead of immediate cleanup |
| `motd` | Configure SSH/MOTD before installation starts |
| `dryrun` | Show commands without executing them |
---
## Best Practices
### 1. **Always Call load_functions() First**
```bash
#!/bin/bash
set -Eeuo pipefail
source <(curl -fsSL .../core.func)
load_functions # MUST be before using any color variables
msg_info "Starting setup" # Now safe to use
```
### 2. **Use Message Functions Consistently**
```bash
msg_info "Starting step"
# Do work...
msg_ok "Step completed"
# Or on error:
if ! command; then
msg_error "Command failed"
exit 1
fi
```
### 3. **Combine Validation Checks**
```bash
#!/bin/bash
source <(curl -fsSL .../core.func)
load_functions
shell_check # Exits if wrong shell
root_check # Exits if not root
pve_check # Exits if unsupported version
arch_check # Exits if wrong architecture
# All checks passed, safe to proceed
msg_ok "Pre-flight checks passed"
```
### 4. **Use Verbose Mode for Debugging**
```bash
VERBOSE="yes" bash ct/myapp.sh
# Shows all silent() command output for troubleshooting
```
### 5. **Log Important Operations**
```bash
silent apt-get update # Suppress unless error
msg_ok "Packages updated" # Show success
silent systemctl start nginx # Suppress unless error
msg_ok "Nginx started" # Show success
```
---
## Contributing
### Adding New Message Functions
Follow existing pattern:
```bash
msg_custom() {
local icon="$1"
local color="$2"
local message="$3"
echo -e "${TAB}${icon}${TAB}${color}${message}${CL}"
}
```
### Adding Color Support
New colors should follow semantic naming:
```bash
BG_ERROR=$'\e[41m' # Red background for errors
BG_SUCCESS=$'\e[42m' # Green background for success
```
### Testing Color Output
```bash
bash
source <(curl -fsSL .../core.func)
load_functions
echo -e "${YW}Yellow${CL} ${RD}Red${CL} ${GN}Green${CL} ${BL}Blue${CL}"
```
---
## Notes
- Core.func is designed to be **sourced once** and **loaded everywhere**
- All color variables are **ANSI escape codes** (work in all terminals)
- Messages use **emoji icons** for visual consistency
- Validation checks use **standard exit codes** (0 for success, 1 for error)
- The module is **lightweight** and loads instantly

View File

@ -279,20 +279,10 @@ echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
4. Initialize application-specific defaults 4. Initialize application-specific defaults
5. Setup SSH/environment configuration 5. Setup SSH/environment configuration
**Example Output**:
```
Setting up variables...
Container ID: 100
Storage: local-lvm
Install method: Default
```
#### `start()` #### `start()`
**Purpose**: Launch the container creation menu with 5 installation modes **Purpose**: Launch the container creation menu with 5 installation modes
**Triggered by**: Called just before `build_container()`
**Menu Options**: **Menu Options**:
``` ```
1. Default Installation (Quick setup, predefined settings) 1. Default Installation (Quick setup, predefined settings)
@ -302,17 +292,6 @@ Install method: Default
5. Settings Menu (Interactive mode selection) 5. Settings Menu (Interactive mode selection)
``` ```
**User Flow**:
```
Select installation mode:
1) Default
2) Advanced
3) User Defaults
4) App Defaults
5) Settings Menu
Enter choice: 2
```
#### `build_container()` #### `build_container()`
**Purpose**: Main orchestrator for LXC container creation **Purpose**: Main orchestrator for LXC container creation
@ -324,63 +303,19 @@ Enter choice: 2
4. Monitors installation progress 4. Monitors installation progress
5. Handles errors and rollback on failure 5. Handles errors and rollback on failure
**Exit Codes**:
- `0` - Success
- `1-255` - Various error conditions (see error_handler.func)
#### `description()` #### `description()`
**Purpose**: Set container description/notes visible in Proxmox UI **Purpose**: Set container description/notes visible in Proxmox UI
**Format**:
```
AppName
IP: [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 ## Advanced Features
### 1. Integration with Defaults System ### 1. Custom Configuration Menus
#### Save App Defaults After Installation
```bash
# 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
```bash
# 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: If your app has additional setup beyond standard vars:
```bash ```bash
# In ct/AppName.sh, after variables()
custom_app_settings() { custom_app_settings() {
CONFIGURE_DB=$(whiptail --title "Database Setup" \ CONFIGURE_DB=$(whiptail --title "Database Setup" \
--yesno "Would you like to configure a custom database?" 8 60) --yesno "Would you like to configure a custom database?" 8 60)
@ -394,25 +329,11 @@ custom_app_settings() {
custom_app_settings custom_app_settings
``` ```
### 3. Version Tracking ### 2. Update Function Patterns
Save installed version for update checks: Save installed version for update checks
```bash ### 3. Health Check Functions
# 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.txt 2>/dev/null)
LATEST=$(curl -fsSL https://api.github.com/repos/user/repo/releases/latest | jq -r '.tag_name')
if [[ "$LATEST" != "$CURRENT" ]]; then
echo "Update available: $CURRENT → $LATEST"
fi
```
### 4. Health Check Functions
Add custom validation: Add custom validation:
@ -432,8 +353,6 @@ function health_check() {
msg_ok "Health check passed" msg_ok "Health check passed"
} }
# Called via: bash ct/appname.sh health_check
``` ```
--- ---
@ -461,87 +380,13 @@ color
catch_errors catch_errors
function update_script() { function update_script() {
header_info # Update logic here
check_container_storage
check_container_resources
if [[ ! -d /opt/homarr ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
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 homarr
cd /opt/homarr
wget -q "https://github.com/ajnart/homarr/releases/download/v${RELEASE}/docker-compose.yml"
docker-compose up -d
echo "${RELEASE}" > /opt/${APP}_version.txt
msg_ok "Updated ${APP} to v${RELEASE}"
else
msg_ok "No update required. ${APP} is already at v${RELEASE}."
fi
exit
} }
start start
build_container build_container
description description
msg_ok "Completed Successfully!\n" msg_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)
```bash
#!/usr/bin/env bash
source <(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"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
if ! command -v psql &>/dev/null; then
msg_error "PostgreSQL not installed!"
exit
fi
msg_info "Updating Alpine packages"
apk update
apk upgrade
msg_ok "Updated Alpine packages"
exit
}
start
build_container
description
msg_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}"
``` ```
--- ---
@ -552,11 +397,6 @@ echo -e "${TAB}${GATEWAY}${BGN}psql -h ${IP} -U postgres${CL}"
**Symptom**: `pct create` exits with error code 209 **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**: **Solution**:
```bash ```bash
# Check existing containers # Check existing containers
@ -570,13 +410,6 @@ pct destroy CTID
### Update Function Doesn't Detect New Version ### 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**: **Debug**:
```bash ```bash
# Check version file # Check version file
@ -584,27 +417,6 @@ cat /opt/AppName_version.txt
# Test GitHub API # Test GitHub API
curl -fsSL https://api.github.com/repos/user/repo/releases/latest | grep tag_name curl -fsSL https://api.github.com/repos/user/repo/releases/latest | grep tag_name
# Inside container
bash 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**:
```bash
# Create header file manually
mkdir -p /usr/local/community-scripts/headers/ct
echo "Your ASCII art here" > /usr/local/community-scripts/headers/ct/appname
# Or remove cache to force re-download
rm -f /usr/local/community-scripts/headers/ct/appname
``` ```
--- ---
@ -615,7 +427,7 @@ Before submitting a PR:
### Script Structure ### Script Structure
- [ ] Shebang is `#!/usr/bin/env bash` - [ ] Shebang is `#!/usr/bin/env bash`
- [ ] Imports `build.func` from community-scripts repo (not personal fork) - [ ] Imports `build.func` from community-scripts repo
- [ ] Copyright header with author and source URL - [ ] Copyright header with author and source URL
- [ ] APP variable matches filename - [ ] APP variable matches filename
- [ ] `var_tags` are semicolon-separated (no spaces) - [ ] `var_tags` are semicolon-separated (no spaces)
@ -624,26 +436,17 @@ Before submitting a PR:
- [ ] `var_cpu` set appropriately (2-4 for most apps) - [ ] `var_cpu` set appropriately (2-4 for most apps)
- [ ] `var_ram` set appropriately (1024-4096 MB minimum) - [ ] `var_ram` set appropriately (1024-4096 MB minimum)
- [ ] `var_disk` sufficient for app + data (5-20 GB) - [ ] `var_disk` sufficient for app + data (5-20 GB)
- [ ] `var_os` is realistic (Alpine if lightweight, Debian/Ubuntu otherwise) - [ ] `var_os` is realistic
- [ ] `var_unprivileged="1"` unless app absolutely needs privileges
### Functions ### Functions
- [ ] `update_script()` implemented (or marked as unavailable) - [ ] `update_script()` implemented
- [ ] Update function checks if app installed - [ ] Update function checks if app installed
- [ ] Update function checks for new version - [ ] Proper error handling with `msg_error`
- [ ] Update function performs cleanup after update
- [ ] Proper error handling with `msg_error` on failure
### Output
- [ ] Success message displayed with access URL
- [ ] URL format: `http://IP:PORT/path` (if web-based)
- [ ] Uses `msg_ok`, `msg_info`, `msg_error` for feedback
### Testing ### Testing
- [ ] Script tested with default installation - [ ] Script tested with default installation
- [ ] Script tested with advanced (19-step) installation - [ ] Script tested with advanced (19-step) installation
- [ ] Update function tested on existing installation - [ ] Update function tested on existing installation
- [ ] Error handling tested (invalid settings, network issues)
--- ---
@ -652,66 +455,18 @@ Before submitting a PR:
### ✅ DO: ### ✅ DO:
1. **Use meaningful defaults** 1. **Use meaningful defaults**
```bash
var_cpu="2" # ✅ Good: Typical workload
var_cpu="128" # ❌ Bad: Unrealistic
```
2. **Implement version tracking** 2. **Implement version tracking**
```bash
echo "${RELEASE}" > /opt/${APP}_version.txt # ✅ Good
# ❌ Bad: No version tracking
```
3. **Handle edge cases** 3. **Handle edge cases**
```bash 4. **Use proper messaging with msg_info/msg_ok/msg_error**
if [[ ! -f /opt/${APP}_version.txt ]]; then
msg_info "First installation detected"
fi
```
4. **Use proper messaging**
```bash
msg_info "Updating..." # ✅ Good: Clear status
echo "Updating..." # ❌ Bad: No formatting
```
### ❌ DON'T: ### ❌ DON'T:
1. **Hardcode versions** 1. **Hardcode versions**
```bash 2. **Use custom color codes** (use built-in variables)
RELEASE="1.2.3" # ❌ Bad: Won't auto-update
```
2. **Use custom color codes**
```bash
echo -e "\033[32mSuccess" # ❌ Bad: Use $GN instead
```
3. **Forget error handling** 3. **Forget error handling**
```bash
wget file.zip # ❌ Bad: No error check
if ! wget -q file.zip; then # ✅ Good
msg_error "Download failed"
fi
```
4. **Leave temporary files** 4. **Leave temporary files**
```bash
rm -rf /opt/file.zip # ✅ Always cleanup
```
---
## Related Documentation
- [install/AppName-install.sh Guide](UPDATED_APP-install.md)
- [build.func Wiki](../misc/build.func.md)
- [tools.func Wiki](../misc/tools.func.md)
- [Defaults System Guide](../DEFAULTS_SYSTEM_GUIDE.md)
--- ---
**Last Updated**: December 2025 **Last Updated**: December 2025
**Compatibility**: ProxmoxVED with build.func v3+ **Compatibility**: ProxmoxVED with build.func v3+
**Questions?** Open an issue in the repository

View File

@ -1,598 +0,0 @@
# Error-Handler.func Wiki
Comprehensive error handling and signal management module providing exit code explanations, error handlers with logging, and signal trap configuration for all Community-Scripts projects.
---
## 📋 Table of Contents
- [Overview](#overview)
- [Exit Code Reference](#exit-code-reference)
- [Error Handler Functions](#error-handler-functions)
- [Signal Traps](#signal-traps)
- [Initialization & Setup](#initialization--setup)
- [Error Logging](#error-logging)
- [Best Practices](#best-practices)
- [Debugging](#debugging)
- [Contributing](#contributing)
---
## Overview
The error_handler.func module provides robust error handling infrastructure:
- ✅ Comprehensive exit code mapping (1-255+ codes documented)
- ✅ Detailed error messages with line numbers and commands
- ✅ Signal trap configuration (ERR, EXIT, INT, TERM, RETURN)
- ✅ Error logging to persistent files
- ✅ Graceful cleanup on signal termination
- ✅ Stack trace display for debugging
- ✅ Integration with core.func message functions
- ✅ Container-agnostic (works in Proxmox + LXC)
### Error Handling Flow
```
Command Execution
ERROR (non-zero exit)
ERR Trap Triggered
error_handler() called
explain_exit_code() lookup
Display error with line/command
Check for log file
Exit with original code
```
---
## Exit Code Reference
Exit codes are categorized by source system. See `api.func.md` for comprehensive mapping documentation.
### Quick Reference Table
| Range | Category | Examples |
|-------|----------|----------|
| 0 | Success | (no error) |
| 1-2 | Shell errors | Syntax error, operation not permitted |
| 100-101 | APT errors | Package manager errors |
| 126-139 | System errors | Command not found, segfault, OOM |
| 200-231 | Proxmox custom | Container creation errors |
| 210-234 | Database errors | PostgreSQL, MySQL connection issues |
| 243-254 | Runtime errors | Node.js, Python, npm errors |
| 255 | DPKG fatal | Package system fatal error |
---
## Error Handler Functions
### `explain_exit_code()`
**Purpose**: Maps numeric exit codes to human-readable descriptions. Shared with api.func for consistency.
**Signature**:
```bash
explain_exit_code()
```
**Parameters**:
- `$1` - Exit code (0-255+)
**Returns**: Human-readable explanation string
**Categories Handled**:
- Generic shell errors (1, 2, 126-128, 130, 137, 139, 143)
- Package managers (100-101, 255)
- Python (210-212)
- Databases (PostgreSQL 231-234, MySQL 241-244, MongoDB 251-254)
- Node.js/npm (243-249, 254)
- Proxmox custom (200-231)
- Default: "Unknown error"
**Usage Examples**:
```bash
# Example 1: Look up error code
explain_exit_code 127
# Output: "Command not found"
# Example 2: In error logging
error_desc=$(explain_exit_code "$exit_code")
echo "Error: $error_desc" >> /tmp/error.log
# Example 3: Unknown code
explain_exit_code 999
# Output: "Unknown error"
```
---
### `error_handler()`
**Purpose**: Main error handler triggered by ERR trap. Displays detailed error information and exits.
**Signature**:
```bash
error_handler()
```
**Parameters**:
- `$1` (optional) - Exit code (default: current $?)
- `$2` (optional) - Command that failed (default: $BASH_COMMAND)
- `$3` (optional) - Line number (default: ${BASH_LINENO[0]})
**Returns**: Exits with original exit code (does not return)
**Output Format**:
```
[ERROR] in line 42: exit code 1 (General error): while executing command curl https://api.example.com
--- Last 10 lines of log file ---
[log content]
------------------------------------
```
**Implementation Pattern**:
```bash
error_handler() {
local exit_code=${1:-$?}
local command=${2:-${BASH_COMMAND:-unknown}}
local line_number=${BASH_LINENO[0]:-unknown}
# If successful, return silently
if [[ "$exit_code" -eq 0 ]]; then
return 0
fi
# Get human-readable error description
local explanation=$(explain_exit_code "$exit_code")
# Show cursor (might be hidden by spinner)
printf "\e[?25h"
# Display error using color messages
if declare -f msg_error >/dev/null 2>&1; then
msg_error "in line ${line_number}: exit code ${exit_code} (${explanation}): while executing command ${command}"
else
echo -e "\n${RD}[ERROR]${CL} in line ${line_number}: exit code ${exit_code}: ${command}\n"
fi
# Log error details if log file configured
if [[ -n "${DEBUG_LOGFILE:-}" ]]; then
{
echo "------ ERROR ------"
echo "Timestamp : $(date '+%Y-%m-%d %H:%M:%S')"
echo "Exit Code : $exit_code ($explanation)"
echo "Line : $line_number"
echo "Command : $command"
echo "-------------------"
} >> "$DEBUG_LOGFILE"
fi
# Show last lines of log if available
local active_log="$(get_active_logfile)"
if [[ -s "$active_log" ]]; then
local log_lines=$(wc -l < "$active_log")
echo "--- Last 10 lines of log ---"
tail -n 10 "$active_log"
echo "----------------------------"
fi
exit "$exit_code"
}
```
**Usage Examples**:
```bash
# Example 1: Automatic trap (recommended)
trap 'error_handler $? "$BASH_COMMAND" $LINENO' ERR
# Error automatically caught and handled
# Example 2: Manual invocation (testing)
error_handler 1 "curl https://api.example.com" 42
# Output: Detailed error with line number
# Example 3: In conditional
if ! some_command; then
error_handler $? "some_command" $LINENO
fi
```
---
## Signal Traps
### `on_exit()`
**Purpose**: Cleanup handler called on normal script exit or error.
**Signature**:
```bash
on_exit()
```
**Parameters**: None
**Returns**: Exits with captured exit code
**Behavior**:
- Captures current exit code
- Removes lock files if present
- Exits with original exit code
**Implementation Pattern**:
```bash
on_exit() {
local exit_code="$?"
# Cleanup lock files
[[ -n "${lockfile:-}" && -e "$lockfile" ]] && rm -f "$lockfile"
# Preserve exit code
exit "$exit_code"
}
```
**Trap Configuration**:
```bash
trap on_exit EXIT # Always called on exit
```
---
### `on_interrupt()`
**Purpose**: Handler for Ctrl+C (SIGINT) signal. Allows graceful shutdown.
**Signature**:
```bash
on_interrupt()
```
**Parameters**: None
**Returns**: Exits with code 130 (standard SIGINT exit code)
**Output**: Displays "Interrupted by user (SIGINT)" message
**Implementation Pattern**:
```bash
on_interrupt() {
echo -e "\n${RD}Interrupted by user (SIGINT)${CL}"
exit 130
}
```
**Trap Configuration**:
```bash
trap on_interrupt INT # Called on Ctrl+C
```
**Usage Example**:
```bash
# Script interrupted by user:
# Ctrl+C pressed
# → on_interrupt() triggers
# → "Interrupted by user (SIGINT)" displayed
# → Exit with code 130
```
---
### `on_terminate()`
**Purpose**: Handler for SIGTERM signal. Allows graceful shutdown on termination.
**Signature**:
```bash
on_terminate()
```
**Parameters**: None
**Returns**: Exits with code 143 (standard SIGTERM exit code)
**Output**: Displays "Terminated by signal (SIGTERM)" message
**Implementation Pattern**:
```bash
on_terminate() {
echo -e "\n${RD}Terminated by signal (SIGTERM)${CL}"
exit 143
}
```
**Trap Configuration**:
```bash
trap on_terminate TERM # Called on SIGTERM
```
**Usage Example**:
```bash
# System sends SIGTERM:
# kill -TERM $PID executed
# → on_terminate() triggers
# → "Terminated by signal (SIGTERM)" displayed
# → Exit with code 143
```
---
## Initialization & Setup
### `catch_errors()`
**Purpose**: Sets up all error traps and signal handlers. Called once at script start.
**Signature**:
```bash
catch_errors()
```
**Parameters**: None
**Returns**: No explicit return value (configures traps)
**Traps Configured**:
1. `ERR``error_handler()` - Catches command failures
2. `EXIT``on_exit()` - Cleanup on any exit
3. `INT``on_interrupt()` - Handle Ctrl+C
4. `TERM``on_terminate()` - Handle SIGTERM
5. `RETURN``error_handler()` - Catch function errors
**Implementation Pattern**:
```bash
catch_errors() {
# Set strict mode
set -Eeuo pipefail
# Configure traps
trap 'error_handler $? "$BASH_COMMAND" $LINENO' ERR
trap on_exit EXIT
trap on_interrupt INT
trap on_terminate TERM
trap 'error_handler $? "$BASH_COMMAND" $LINENO' RETURN
}
```
**Usage Examples**:
```bash
# Example 1: Alpine container script
#!/bin/sh
source <(curl -fsSL .../core.func)
source <(curl -fsSL .../error_handler.func)
load_functions
catch_errors
# Now all signals handled automatically
update_os
# Example 2: Proxmox host script
#!/bin/bash
source <(curl -fsSL .../core.func)
source <(curl -fsSL .../error_handler.func)
load_functions
catch_errors
# Safe to proceed with error handling
create_container
```
---
## Error Logging
### Log File Configuration
**Active Log Detection**:
```bash
# In build.func/install.func:
BUILD_LOG="/tmp/create-lxc-${SESSION_ID}.log"
INSTALL_LOG="/root/install-${SESSION_ID}.log"
SILENT_LOGFILE="$(get_active_logfile)" # Points to appropriate log
```
### Log Output Behavior
When command fails in `silent()`:
1. Last 10 lines of log file are displayed
2. Full log path shown if more than 10 lines
3. Error message includes line number where failure occurred
4. Command that failed is displayed
### Accessing Error Logs
From Proxmox host:
```bash
# Host-side container creation log
/tmp/create-lxc-<SESSION_ID>.log
# View error details
tail -50 /tmp/create-lxc-550e8400.log
grep ERROR /tmp/create-lxc-*.log
# Development mode persistent logs
/var/log/community-scripts/create-lxc-<SESSION_ID>-<TIMESTAMP>.log
```
From inside LXC container:
```bash
# Container installation log
/root/install-<SESSION_ID>.log
# View recent errors
tail -20 /root/install-550e8400.log
```
---
## Best Practices
### 1. **Always Setup Traps Early**
```bash
#!/bin/bash
set -Eeuo pipefail
source <(curl -fsSL .../core.func)
source <(curl -fsSL .../error_handler.func)
load_functions
catch_errors # MUST be called before any real work
# Now safe - all signals handled
```
### 2. **Use Meaningful Error Exit Codes**
```bash
# Use Proxmox custom codes for container-specific errors
if [[ "$CTID" -lt 100 ]]; then
msg_error "Container ID must be >= 100"
exit 205 # Proxmox custom code
fi
# Use standard codes for common errors
if ! command -v curl &>/dev/null; then
msg_error "curl not installed"
exit 127 # Command not found
fi
```
### 3. **Log Context Information**
```bash
# In error_handler, DEBUG_LOGFILE receives:
DEBUG_LOGFILE="/tmp/debug.log"
# All errors logged with timestamp and details
{
echo "Error at $(date)"
echo "Exit code: $exit_code"
echo "Command: $command"
} >> "$DEBUG_LOGFILE"
```
### 4. **Graceful Signal Handling**
```bash
# Setup signal handlers for cleanup
cleanup() {
[[ -f "$temp_file" ]] && rm -f "$temp_file"
[[ -d "$temp_dir" ]] && rm -rf "$temp_dir"
}
trap cleanup EXIT
# Now temporary files always cleaned up
```
### 5. **Test Error Paths**
```bash
# Force error for testing
false # Triggers error_handler
# or
exit 1 # Custom error
# Verify error handling works correctly
# Check log files and messages
```
---
## Debugging
### Enable Stack Trace
```bash
# Via environment variable
DEV_MODE_TRACE=true bash script.sh
# Or in script
set -x # Show all commands
trap 'error_handler $? "$BASH_COMMAND" $LINENO' ERR
```
### View Full Error Context
```bash
# Show full log file instead of last 10 lines
DEBUG_LOGFILE="/tmp/full-debug.log"
# After error, review complete context
less /tmp/full-debug.log
```
### Test Error Handler
```bash
# Manually trigger error handler
bash -c 'source <(curl -fsSL .../error_handler.func); catch_errors; exit 42'
# Should display:
# [ERROR] in line N: exit code 42 (Unknown error): ...
```
---
## Contributing
### Adding New Error Codes
1. Assign code in appropriate range (see Exit Code Reference)
2. Add description to `explain_exit_code()` in both:
- error_handler.func
- api.func (for consistency)
3. Document in exit code table
4. Update error mapping documentation
### Improving Error Messages
Example: Make error message more helpful:
```bash
# Before:
"Container ID must be >= 100"
# After:
"Invalid CTID: $CTID. Container IDs must be >= 100. Current range: 100-999"
```
### Testing Signal Handlers
```bash
# Test INT signal (Ctrl+C)
bash -c 'source <(curl -fsSL .../error_handler.func); catch_errors; sleep 30' &
PID=$!
sleep 1
kill -INT $PID
wait
# Test TERM signal
bash -c 'source <(curl -fsSL .../error_handler.func); catch_errors; sleep 30' &
PID=$!
sleep 1
kill -TERM $PID
wait
```
---
## Notes
- Error handler is **required** for all scripts (ensures safe cleanup)
- Exit codes are **standardized** (0 = success, 1-255 = specific errors)
- Signals are **trapped** to allow graceful shutdown
- Lock files are **automatically cleaned** on exit
- Log files contain **full error context** for debugging

View File

@ -1,646 +0,0 @@
# 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

View File

@ -0,0 +1,646 @@
# 🛠️ **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](#overview)
- [Execution Context](#execution-context)
- [File Structure](#file-structure)
- [Complete Script Template](#complete-script-template)
- [Installation Phases](#installation-phases)
- [Function Reference](#function-reference)
- [Best Practices](#best-practices)
- [Real Examples](#real-examples)
- [Troubleshooting](#troubleshooting)
- [Contribution Checklist](#contribution-checklist)
---
## 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
```bash
# 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
```bash
#!/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
```bash
#!/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
```bash
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)
```bash
# 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
```bash
# 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
```bash
# 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)
```bash
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
```bash
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
```bash
# 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
```bash
# 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
```bash
# 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
```bash
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
```bash
NODE_VERSION="22" setup_nodejs
PHP_VERSION="8.4" setup_php
```
### Phase 4: Application Setup
```bash
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
```bash
msg_info "Installing application"
# Output: ⏳ Installing application (with spinning animation)
```
#### `msg_ok(message)`
Displays success message with checkmark
```bash
msg_ok "Installation completed"
# Output: ✔️ Installation completed
```
#### `msg_error(message)`
Displays error message and exits
```bash
msg_error "Installation failed"
# Output: ✖️ Installation failed
```
### Package Management
#### `$STD` Variable
Controls output verbosity
```bash
# Silent mode (respects VERBOSE setting)
$STD apt-get install -y nginx
```
#### `update_os()`
Updates OS packages
```bash
update_os
# Runs: apt update && apt upgrade
```
### Tool Installation Functions
#### `setup_nodejs()`
Installs Node.js with optional global modules
```bash
NODE_VERSION="22" setup_nodejs
NODE_VERSION="22" NODE_MODULE="yarn,@vue/cli" setup_nodejs
```
#### `setup_php()`
Installs PHP with optional extensions
```bash
PHP_VERSION="8.4" PHP_MODULE="bcmath,curl,gd,intl,redis" setup_php
```
#### Other Tools
```bash
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
```bash
cleanup_lxc
# Output: ⏳ Cleaning up
# ✔️ Cleaned
```
---
## Best Practices
### ✅ DO:
1. **Always Use $STD for Commands**
```bash
# ✅ Good: Respects VERBOSE setting
$STD apt-get install -y nginx
```
2. **Generate Random Passwords Safely**
```bash
# ✅ Good: Alphanumeric only
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
```
3. **Check Command Success**
```bash
# ✅ Good: Verify success
if ! wget -q "https://example.com/file.tar.gz"; then
msg_error "Download failed"
exit 1
fi
```
4. **Set Proper Permissions**
```bash
# ✅ Good: Explicit permissions
chown -R www-data:www-data /opt/appname
chmod -R 755 /opt/appname
```
5. **Save Version for Update Checks**
```bash
# ✅ Good: Version tracked
echo "${RELEASE}" > /opt/${APP}_version.txt
```
6. **Handle Alpine vs Debian Differences**
```bash
# ✅ 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**
```bash
# ❌ Bad: Won't auto-update
wget https://example.com/app-1.2.3.tar.gz
```
2. **Use Root Without Password**
```bash
# ❌ Bad: Security risk
mysql -u root
```
3. **Forget Error Handling**
```bash
# ❌ Bad: Silent failures
wget https://example.com/file
tar -xzf file
```
4. **Leave Temporary Files**
```bash
# ✅ Always cleanup
rm -rf /opt/app-${RELEASE}.tar.gz
```
---
## Real Examples
### Example 1: Node.js Application
```bash
#!/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
```bash
#!/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**:
```bash
ping -c 1 8.8.8.8
```
**Enable verbose mode**:
```bash
# In ct/AppName.sh, before running
VERBOSE="yes" bash install/AppName-install.sh
```
### Package Not Found
**Update package lists**:
```bash
apt update
apt-cache search package_name
```
### Service Won't Start
**Check logs**:
```bash
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+

View File

@ -1,670 +0,0 @@
# API.func Wiki
A telemetry and diagnostics module providing anonymous statistics collection and API integration with the Community-Scripts infrastructure for tracking container/VM creation metrics and installation success/failure data.
---
## 📋 Table of Contents
- [Overview](#overview)
- [Exit Code Reference](#exit-code-reference)
- [Telemetry Functions](#telemetry-functions)
- [API Payload Structure](#api-payload-structure)
- [Privacy & Opt-Out](#privacy--opt-out)
- [Error Mapping](#error-mapping)
- [Best Practices](#best-practices)
- [API Integration](#api-integration)
- [Contributing](#contributing)
---
## Overview
The API.func module provides anonymous telemetry reporting to Community-Scripts infrastructure, enabling:
- ✅ Container/VM creation statistics collection
- ✅ Installation success/failure tracking
- ✅ Comprehensive exit code mapping and explanation
- ✅ Anonymous session-based tracking (UUID)
- ✅ Privacy-respecting data collection (no personal data)
- ✅ Opt-out capability via DIAGNOSTICS setting
- ✅ Consistent error reporting across all scripts
### Integration Points
```bash
# In container build scripts (on Proxmox host):
source <(curl -fsSL .../api.func)
post_to_api # Report container creation
post_update_to_api # Report installation completion
# Error handling (in all scripts):
source <(curl -fsSL .../error_handler.func)
# explain_exit_code shared for consistent mappings
```
### Data Flow
```
Container/VM Creation
post_to_api()
Community-Scripts API
Anonymous Statistics
(No personal data)
```
---
## Exit Code Reference
### Category 1: Generic / Shell Errors
| Code | Meaning | Recovery |
|------|---------|----------|
| 1 | General error / Operation not permitted | Check permissions, re-run command |
| 2 | Misuse of shell builtins (syntax error) | Fix shell syntax, validate script |
| 126 | Command invoked cannot execute | Fix file permissions (chmod +x) |
| 127 | Command not found | Install missing package or tool |
| 128 | Invalid argument to exit | Check exit code parameter (0-255) |
| 130 | Terminated by Ctrl+C (SIGINT) | User interrupted - retry manually |
| 137 | Killed (SIGKILL / Out of memory) | Insufficient RAM - increase allocation |
| 139 | Segmentation fault (core dumped) | Serious application bug - contact support |
| 143 | Terminated (SIGTERM) | System shutdown or manual termination |
### Category 2: Package Manager Errors
| Code | Meaning | Recovery |
|------|---------|----------|
| 100 | APT: Package manager error (broken packages) | Run `apt --fix-broken install` |
| 101 | APT: Configuration error (bad sources.list) | Fix /etc/apt/sources.list, re-run apt update |
| 255 | DPKG: Fatal internal error | Run `dpkg --configure -a` |
### Category 3: Node.js / npm Errors
| Code | Meaning | Recovery |
|------|---------|----------|
| 243 | Node.js: Out of memory (heap out of memory) | Increase container RAM, reduce workload |
| 245 | Node.js: Invalid command-line option | Check node/npm arguments |
| 246 | Node.js: Internal JavaScript Parse Error | Update Node.js version |
| 247 | Node.js: Fatal internal error | Check Node.js installation integrity |
| 248 | Node.js: Invalid C++ addon / N-API failure | Rebuild native modules |
| 249 | Node.js: Inspector error | Disable debugger, retry |
| 254 | npm/pnpm/yarn: Unknown fatal error | Check package.json, clear cache |
### Category 4: Python Errors
| Code | Meaning | Recovery |
|------|---------|----------|
| 210 | Python: Virtualenv / uv environment missing | Recreate virtual environment |
| 211 | Python: Dependency resolution failed | Check package versions, fix conflicts |
| 212 | Python: Installation aborted (EXTERNALLY-MANAGED) | Use venv or remove marker file |
### Category 5: Database Errors
#### PostgreSQL
| Code | Meaning | Recovery |
|------|---------|----------|
| 231 | Connection failed (server not running) | Start PostgreSQL service |
| 232 | Authentication failed (bad user/password) | Verify credentials |
| 233 | Database does not exist | Create database: `createdb dbname` |
| 234 | Fatal error in query / syntax error | Fix SQL syntax |
#### MySQL / MariaDB
| Code | Meaning | Recovery |
|------|---------|----------|
| 241 | Connection failed (server not running) | Start MySQL/MariaDB service |
| 242 | Authentication failed (bad user/password) | Reset password, verify credentials |
| 243 | Database does not exist | Create database: `CREATE DATABASE dbname;` |
| 244 | Fatal error in query / syntax error | Fix SQL syntax |
#### MongoDB
| Code | Meaning | Recovery |
|------|---------|----------|
| 251 | Connection failed (server not running) | Start MongoDB daemon |
| 252 | Authentication failed (bad user/password) | Verify credentials, reset if needed |
| 253 | Database not found | Create database in MongoDB shell |
| 254 | Fatal query error | Check query syntax |
### Category 6: Proxmox Custom Codes
| Code | Meaning | Recovery |
|------|---------|----------|
| 200 | Failed to create lock file | Check /tmp permissions |
| 203 | Missing CTID variable | CTID must be provided to script |
| 204 | Missing PCT_OSTYPE variable | OS type not detected |
| 205 | Invalid CTID (<100) | Container ID must be >= 100 |
| 206 | CTID already in use | Check `pct list`, remove conflicting container |
| 207 | Password contains special characters | Use alphanumeric only for passwords |
| 208 | Invalid configuration format | Check DNS/MAC/Network format |
| 209 | Container creation failed | Check pct create output for details |
| 210 | Cluster not quorate | Ensure cluster nodes are online |
| 211 | Timeout waiting for template lock | Wait for concurrent downloads to finish |
| 214 | Not enough storage space | Free up disk space or expand storage |
| 215 | Container created but not listed | Check /etc/pve/lxc/ for config files |
| 216 | RootFS entry missing in config | Incomplete container creation |
| 217 | Storage does not support rootdir | Use compatible storage backend |
| 218 | Template corrupted or incomplete | Re-download template |
| 220 | Unable to resolve template path | Verify template availability |
| 221 | Template not readable | Fix file permissions |
| 222 | Template download failed (3 attempts) | Check network/storage |
| 223 | Template not available after download | Storage sync issue |
| 225 | No template for OS/Version | Run `pveam available` to see options |
| 231 | LXC stack upgrade/retry failed | Update pve-container package |
---
## Telemetry Functions
### `explain_exit_code()`
**Purpose**: Maps numeric exit codes to human-readable error descriptions. Shared between api.func and error_handler.func for consistency.
**Signature**:
```bash
explain_exit_code()
```
**Parameters**:
- `$1` - Numeric exit code (0-255)
**Returns**: Human-readable description string
**Supported Codes**:
- 1-2, 126-128, 130, 137, 139, 143 (Shell)
- 100-101, 255 (Package managers)
- 210-212 (Python)
- 231-234 (PostgreSQL)
- 241-244 (MySQL/MariaDB)
- 243-249, 254 (Node.js/npm)
- 251-254 (MongoDB)
- 200-231 (Proxmox custom)
**Default**: Returns "Unknown error" for unmapped codes
**Usage Examples**:
```bash
# Example 1: Common error
explain_exit_code 127
# Output: "Command not found"
# Example 2: Database error
explain_exit_code 241
# Output: "MySQL/MariaDB: Connection failed (server not running / wrong socket)"
# Example 3: Custom Proxmox error
explain_exit_code 206
# Output: "Custom: CTID already in use (check 'pct list' and /etc/pve/lxc/)"
# Example 4: Unknown code
explain_exit_code 999
# Output: "Unknown error"
```
---
### `post_to_api()`
**Purpose**: Sends LXC container creation statistics to Community-Scripts telemetry API.
**Signature**:
```bash
post_to_api()
```
**Parameters**: None (uses global environment variables)
**Returns**: No explicit return value (curl result stored in RESPONSE if diagnostics enabled)
**Requirements** (Silent fail if not met):
- `curl` command available
- `DIAGNOSTICS="yes"`
- `RANDOM_UUID` is set
- Executed on Proxmox host (has access to `pveversion`)
**Environment Variables Used**:
- `CT_TYPE` - Container type (privileged=1, unprivileged=0)
- `DISK_SIZE` - Allocated disk in GB
- `CORE_COUNT` - CPU core count
- `RAM_SIZE` - RAM allocated in MB
- `var_os` - Operating system name
- `var_version` - OS version
- `NSAPP` - Normalized application name
- `METHOD` - Installation method (default, template, etc.)
- `DIAGNOSTICS` - Enable telemetry (yes/no)
- `RANDOM_UUID` - Session UUID for tracking
**API Endpoint**: `http://api.community-scripts.org/dev/upload`
**Payload Structure**:
```json
{
"ct_type": 1, // Privileged (1) or Unprivileged (0)
"type": "lxc", // Always "lxc" for containers
"disk_size": 8, // GB
"core_count": 2, // CPU cores
"ram_size": 2048, // MB
"os_type": "debian", // OS name
"os_version": "12", // OS version
"nsapp": "myapp", // Application name
"method": "default", // Setup method
"pve_version": "8.2.2", // Proxmox VE version
"status": "installing", // Current status
"random_id": "550e8400-e29b" // Session UUID (anonymous)
}
```
**Usage Examples**:
```bash
# Example 1: Successful API post
CT_TYPE=1
DISK_SIZE=20
CORE_COUNT=4
RAM_SIZE=4096
var_os="ubuntu"
var_version="22.04"
NSAPP="jellyfin"
METHOD="default"
DIAGNOSTICS="yes"
RANDOM_UUID="550e8400-e29b-41d4-a716-446655440000"
post_to_api
# Result: Statistics sent to API (silently, no output)
# Example 2: Diagnostics disabled (opt-out)
DIAGNOSTICS="no"
post_to_api
# Result: Function returns immediately, no API call
# Example 3: Missing curl
DIAGNOSTICS="yes"
# curl not available in PATH
post_to_api
# Result: Function returns silently (curl requirement not met)
```
---
### `post_to_api_vm()`
**Purpose**: Sends VM creation statistics to Community-Scripts API (similar to post_to_api but for virtual machines).
**Signature**:
```bash
post_to_api_vm()
```
**Parameters**: None (uses global environment variables)
**Returns**: No explicit return value
**Requirements**: Same as `post_to_api()`
**Environment Variables Used**:
- `VMID` - Virtual machine ID
- `VM_TYPE` - VM type (kvm, etc.)
- `VM_CORES` - CPU core count
- `VM_RAM` - RAM in MB
- `VM_DISK` - Disk in GB
- `VM_OS` - Operating system
- `VM_VERSION` - OS version
- `VM_APP` - Application name
- `DIAGNOSTICS` - Enable telemetry
- `RANDOM_UUID` - Session UUID
**Payload Structure** (similar to containers but for VMs):
```json
{
"vm_id": 100,
"type": "qemu",
"vm_cores": 4,
"vm_ram": 4096,
"vm_disk": 20,
"vm_os": "ubuntu",
"vm_version": "22.04",
"vm_app": "jellyfin",
"pve_version": "8.2.2",
"status": "installing",
"random_id": "550e8400-e29b"
}
```
---
### `post_update_to_api()`
**Purpose**: Reports installation completion status (success/failure) for container or VM.
**Signature**:
```bash
post_update_to_api()
```
**Parameters**: None (uses global environment variables)
**Returns**: No explicit return value
**Requirements**: Same as `post_to_api()`
**Environment Variables Used**:
- `RANDOM_UUID` - Session UUID (must match initial post_to_api call)
- `DIAGNOSTICS` - Enable telemetry
- Installation status parameters
**Payload Structure**:
```json
{
"status": "completed", // "completed" or "failed"
"random_id": "550e8400-e29b", // Session UUID
"exit_code": 0, // 0 for success, error code for failure
"error_explanation": "" // Error description if failed
}
```
---
## API Payload Structure
### Container Creation Payload
```json
{
"ct_type": 1, // 1=Privileged, 0=Unprivileged
"type": "lxc", // Always "lxc"
"disk_size": 20, // GB
"core_count": 4, // CPU cores
"ram_size": 4096, // MB
"os_type": "debian", // Distribution name
"os_version": "12", // Version number
"nsapp": "jellyfin", // Application name
"method": "default", // Setup method
"pve_version": "8.2.2", // Proxmox VE version
"status": "installing", // Current phase
"random_id": "550e8400" // Unique session ID
}
```
### VM Creation Payload
```json
{
"vm_id": 100,
"type": "qemu",
"vm_cores": 4,
"vm_ram": 4096,
"vm_disk": 20,
"vm_os": "ubuntu",
"vm_version": "22.04",
"vm_app": "jellyfin",
"pve_version": "8.2.2",
"status": "installing",
"random_id": "550e8400"
}
```
### Update/Completion Payload
```json
{
"status": "completed",
"random_id": "550e8400",
"exit_code": 0,
"error_explanation": ""
}
```
---
## Privacy & Opt-Out
### Privacy Policy
Community-Scripts telemetry is designed to be **privacy-respecting**:
- ✅ **Anonymous**: No personal data collected
- ✅ **Session-based**: UUID allows correlation without identification
- ✅ **Aggregated**: Only statistics are stored, never raw logs
- ✅ **Opt-out capable**: Single environment variable disables all telemetry
- ✅ **No tracking**: UUID cannot be linked to user identity
- ✅ **No credentials**: Passwords, SSH keys never transmitted
### Opt-Out Methods
**Method 1: Environment Variable (Single Script)**
```bash
DIAGNOSTICS="no" bash ct/myapp.sh
```
**Method 2: Script Header (Persistent)**
```bash
#!/bin/bash
export DIAGNOSTICS="no"
# Rest of script continues without telemetry
```
**Method 3: System-wide Configuration**
```bash
# In /etc/environment or ~/.bashrc
export DIAGNOSTICS="no"
```
### What Data Is Collected
| Data | Why | Shared? |
|------|-----|---------|
| Container/VM specs (cores, RAM, disk) | Understand deployment patterns | Yes, aggregated |
| OS type/version | Track popular distributions | Yes, aggregated |
| Application name | Understand popular apps | Yes, aggregated |
| Method (standard vs. custom) | Measure feature usage | Yes, aggregated |
| Success/failure status | Identify issues | Yes, aggregated |
| Exit codes | Debug failures | Yes, anonymized |
### What Data Is NOT Collected
- ❌ Container/VM hostnames
- ❌ IP addresses
- ❌ User credentials
- ❌ SSH keys or secrets
- ❌ Application data
- ❌ System logs
- ❌ Any personal information
---
## Error Mapping
### Mapping Strategy
Exit codes are categorized by source:
```
Exit Code Range | Source | Handling
0 | Success | Not reported to API
1-2 | Shell/Script | Generic error
100-101, 255 | Package managers | APT/DPKG specific
126-128 | Command execution | Permission/not found
130, 143 | Signals | User interrupt/termination
137, 139 | Kernel | OOM/segfault
200-231 | Proxmox custom | Container creation issues
210-212 | Python | Python environment issues
231-234 | PostgreSQL | Database connection issues
241-244 | MySQL/MariaDB | Database connection issues
243-249, 254 | Node.js/npm | Runtime errors
251-254 | MongoDB | Database connection issues
```
### Custom Exit Code Usage
Scripts can define custom exit codes:
```bash
# Example: Custom validation failure
if [[ "$CTID" -lt 100 ]]; then
echo "Container ID must be >= 100"
exit 205 # Custom Proxmox code
fi
```
---
## Best Practices
### 1. **Always Initialize RANDOM_UUID**
```bash
# Generate unique session ID for tracking
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)"
# Use first 8 chars for short session ID (logs)
SESSION_ID="${RANDOM_UUID:0:8}"
BUILD_LOG="/tmp/create-lxc-${SESSION_ID}.log"
```
### 2. **Call post_to_api Early**
```bash
# Call post_to_api right after container creation starts
# This tracks attempt, even if installation fails
variables() {
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)"
# ... other variables ...
}
# Later, in main script:
post_to_api # Report container creation started
# ... perform installation ...
post_update_to_api # Report completion
```
### 3. **Handle Graceful Failures**
```bash
# Wrap API calls to handle network issues
if command -v curl &>/dev/null; then
post_to_api || true # Don't fail if API unavailable
else
msg_warn "curl not available, telemetry skipped"
fi
```
### 4. **Respect User Opt-Out**
```bash
# Check DIAGNOSTICS early and skip all API calls if disabled
if [[ "${DIAGNOSTICS}" != "yes" ]]; then
msg_info "Anonymous diagnostics disabled"
return 0 # Skip telemetry
fi
```
### 5. **Maintain Session Consistency**
```bash
# Use same RANDOM_UUID throughout lifecycle
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)"
post_to_api # Initial report
# ... installation ...
post_update_to_api # Final report (same UUID links them)
```
---
## API Integration
### Connecting to API
The API endpoint is:
```
http://api.community-scripts.org/dev/upload
```
### API Response Handling
```bash
# Capture HTTP response code
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD") || true
# Extract status code (last 3 digits)
HTTP_CODE="${RESPONSE: -3}"
if [[ "$HTTP_CODE" == "200" ]]; then
msg_ok "Telemetry submitted successfully"
elif [[ "$HTTP_CODE" == "429" ]]; then
msg_warn "API rate limited, skipping telemetry"
else
msg_info "Telemetry API unreachable (this is OK)"
fi
```
### Network Resilience
API calls are **best-effort** and never block installation:
```bash
# Telemetry should never cause container creation to fail
if post_to_api 2>/dev/null; then
msg_info "Diagnostics transmitted"
fi
# If API unavailable, continue anyway
```
---
## Contributing
### Adding New Exit Codes
1. Document in the appropriate category section
2. Update `explain_exit_code()` in both api.func and error_handler.func
3. Add recovery suggestions
4. Test mapping with scripts that use the new code
### Testing API Integration
```bash
# Test with mock curl (local testing)
DIAGNOSTICS="yes"
RANDOM_UUID="test-uuid-12345678"
curl -X POST http://localhost:8000/dev/upload \
-H "Content-Type: application/json" \
-d '{"test": "payload"}'
# Verify payload structure
post_to_api 2>&1 | head -20
```
### Telemetry Reporting Improvements
Suggestions for improvement:
1. Installation duration tracking
2. Package version compatibility data
3. Feature usage analytics
4. Performance metrics
5. Custom error codes
---
## Notes
- API calls are **silent by default** and never display sensitive information
- Telemetry can be **completely disabled** via `DIAGNOSTICS="no"`
- **RANDOM_UUID must be generated** before calling any post functions
- Exit code mappings are **shared** between api.func and error_handler.func for consistency
- API is **optional** - containers work perfectly without telemetry

File diff suppressed because it is too large Load Diff