Update contribution docs and templates for best practices

Refreshed AI.md with new reference scripts, expanded checklist, and improved AI assistant tips. Updated container and install script templates for modern defaults (Debian 13, larger disk, two tags), clarified helper function usage, and improved update/backup patterns. Enhanced JSON template with realistic metadata, new fields, and example notes.
This commit is contained in:
CanbiZ
2026-01-18 17:54:44 +01:00
parent 5a975901ea
commit acdf4dbb2a
4 changed files with 190 additions and 135 deletions
+64 -39
View File
@@ -624,40 +624,33 @@ cleanup_lxc
--- ---
## 🔍 Checklist Before PR Creation ## 📖 Reference: Good Example Scripts
- [ ] No Docker installation used Look at these recent well-implemented applications as reference:
- [ ] `fetch_and_deploy_gh_release` used for GitHub releases
- [ ] `check_for_gh_release` used for update checks
- [ ] `setup_*` functions used for runtimes (nodejs, postgresql, etc.)
- [ ] **`tools.func` functions NOT wrapped in msg_info/msg_ok blocks**
- [ ] No redundant variables
- [ ] `$STD` before all apt/npm/build commands
- [ ] `msg_info`/`msg_ok`/`msg_error` for logging (only for custom code)
- [ ] Correct script structure followed
- [ ] Update function present and functional
- [ ] Data backup implemented in update function
- [ ] `motd_ssh`, `customize`, `cleanup_lxc` at the end
- [ ] No custom download/version-check logic
- [ ] JSON metadata file created in `frontend/public/json/<appname>.json`
--- ### Container Scripts (Latest 10)
- [ct/thingsboard.sh](../ct/thingsboard.sh) - IoT platform with proper update_script
- [ct/unifi-os-server.sh](../ct/unifi-os-server.sh) - Complex setup with podman
- [ct/trip.sh](../ct/trip.sh) - Simple Ruby app
- [ct/fladder.sh](../ct/fladder.sh) - Media app with database
- [ct/qui.sh](../ct/qui.sh) - Lightweight utility
- [ct/kutt.sh](../ct/kutt.sh) - Node.js with PostgreSQL
- [ct/flatnotes.sh](../ct/flatnotes.sh) - Python notes app
- [ct/investbrain.sh](../ct/investbrain.sh) - Finance app
- [ct/gwn-manager.sh](../ct/gwn-manager.sh) - Network management
- [ct/sportarr.sh](../ct/sportarr.sh) - Specialized *Arr variant
## 📖 Reference: Good Example (Termix) ### Install Scripts (Latest)
- [install/unifi-os-server-install.sh](../install/unifi-os-server-install.sh) - Complex setup with API integration
- [install/trip-install.sh](../install/trip-install.sh) - Rails application setup
- [install/mail-archiver-install.sh](../install/mail-archiver-install.sh) - Email-related service
### CT Script: [ct/termix.sh](../ct/termix.sh) **Key things to notice:**
- Proper error handling with `catch_errors`
- Uses `check_for_gh_release` for version checking - Use of `check_for_gh_release` and `fetch_and_deploy_gh_release`
- Uses `CLEAN_INSTALL=1 fetch_and_deploy_gh_release` for clean updates - Correct backup/restore patterns in `update_script`
- Backup/restore of `/opt/termix/data` - Footer always ends with `motd_ssh`, `customize`, `cleanup_lxc`
- Correct structure with all required variables - JSON metadata files created for each app
### Install Script: [install/termix-install.sh](../install/termix-install.sh)
- `NODE_VERSION="22" setup_nodejs` instead of manual installation
- `fetch_and_deploy_gh_release "termix" "Termix-SSH/Termix"` instead of wget/curl
- Clean service configuration
- Correct footer with `motd_ssh`, `customize`, `cleanup_lxc`
--- ---
@@ -792,19 +785,51 @@ Or no credentials:
--- ---
## 💡 Tips for AI Assistants ## 🔍 Checklist Before PR Creation
1. **Search `tools.func` first** before implementing custom solutions - [ ] No Docker installation used
2. **Use existing scripts as reference** (e.g., `linkwarden-install.sh`, `homarr-install.sh`) - [ ] `fetch_and_deploy_gh_release` used for GitHub releases
- [ ] `check_for_gh_release` used for update checks
- [ ] `setup_*` functions used for runtimes (nodejs, postgresql, etc.)
- [ ] **`tools.func` functions NOT wrapped in msg_info/msg_ok blocks**
- [ ] No redundant variables (only when used multiple times)
- [ ] `$STD` before all apt/npm/build commands
- [ ] `msg_info`/`msg_ok`/`msg_error` for logging (only for custom code)
- [ ] Correct script structure followed (see templates)
- [ ] Update function present and functional (CT scripts)
- [ ] Data backup implemented in update function (if applicable)
- [ ] `motd_ssh`, `customize`, `cleanup_lxc` at the end of install scripts
- [ ] No custom download/version-check logic
- [ ] All links point to `community-scripts/ProxmoxVE` (not `ProxmoxVED`!)
- [ ] JSON metadata file created in `frontend/public/json/<appname>.json`
- [ ] Category IDs are valid (0-25)
- [ ] Default OS version is Debian 13 or newer (unless special requirement)
- [ ] Default resources are reasonable for the application
---
## 💡 Tips for AI Assistants
1. **ALWAYS search `tools.func` first** before implementing custom solutions
2. **Use recent scripts as reference** (Thingsboard, UniFi OS, Trip, Flatnotes, etc.)
3. **Ask when uncertain** instead of introducing wrong patterns 3. **Ask when uncertain** instead of introducing wrong patterns
4. **Consistency > Creativity** - follow established patterns 4. **Test locally** - try running scripts in test containers
5. **Test local variables** - use `${VAR:-default}` pattern for optional values 5. **Consistency > Creativity** - follow established patterns strictly
6. **Check the templates** - they show the correct structure
7. **Don't wrap tools.func functions** - they handle their own msg_info/msg_ok output
8. **Minimal variables** - only create variables that are truly reused multiple times
9. **Always use $STD** - ensures silent/non-interactive execution
10. **Reference good examples** - look at recent additions in each category
--- ---
## 📚 Further Documentation ## 📚 Further Documentation
- [CONTRIBUTING.md](contribution/CONTRIBUTING.md) - General contribution guidelines - [CONTRIBUTING.md](CONTRIBUTING.md) - General contribution guidelines
- [GUIDE.md](contribution/GUIDE.md) - Detailed developer documentation - [GUIDE.md](GUIDE.md) - Detailed developer documentation
- [TECHNICAL_REFERENCE.md](TECHNICAL_REFERENCE.md) - Technical details - [HELPER_FUNCTIONS.md](HELPER_FUNCTIONS.md) - Complete tools.func reference
- [EXIT_CODES.md](EXIT_CODES.md) - Exit code reference - [../TECHNICAL_REFERENCE.md](../TECHNICAL_REFERENCE.md) - Technical deep dive
- [../EXIT_CODES.md](../EXIT_CODES.md) - Exit code reference
- [templates_ct/](templates_ct/) - CT script templates
- [templates_install/](templates_install/) - Install script templates
- [templates_json/](templates_json/) - JSON metadata templates
+23 -30
View File
@@ -7,12 +7,12 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# App Default Values # App Default Values
APP="[AppName]" APP="[AppName]"
var_tags="${var_tags:-[category]}" var_tags="${var_tags:-[category1];[category2]}"
var_cpu="${var_cpu:-2}" var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}" var_ram="${var_ram:-2048}"
var_disk="${var_disk:-4}" var_disk="${var_disk:-8}"
var_os="${var_os:-debian}" var_os="${var_os:-debian}"
var_version="${var_version:-12}" var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}" var_unprivileged="${var_unprivileged:-1}"
# ============================================================================= # =============================================================================
@@ -20,12 +20,12 @@ var_unprivileged="${var_unprivileged:-1}"
# ============================================================================= # =============================================================================
# APP - Display name, title case (e.g. "Koel", "Wallabag", "Actual Budget") # APP - Display name, title case (e.g. "Koel", "Wallabag", "Actual Budget")
# var_tags - Max 2 tags, semicolon separated (e.g. "music;streaming", "finance") # var_tags - Max 2 tags, semicolon separated (e.g. "music;streaming", "finance")
# var_cpu - CPU cores: 1-4 typical # var_cpu - CPU cores: 1-4 typical, 4+ for heavy apps
# var_ram - RAM in MB: 512, 1024, 2048, 4096 typical # var_ram - RAM in MB: 512, 1024, 2048, 4096, 8192 typical
# var_disk - Disk in GB: 4, 6, 8, 10, 20 typical # var_disk - Disk in GB: 6, 8, 10, 20 typical (more for data-heavy apps)
# var_os - OS: debian, ubuntu, alpine # var_os - OS: debian, ubuntu, alpine
# var_version - OS version: 12/13 (debian), 22.04/24.04 (ubuntu), 3.20/3.21 (alpine) # var_version - OS version: 13 (debian), 24.04 (ubuntu), 3.21 (alpine)
# var_unprivileged - 1 = unprivileged (secure, default), 0 = privileged (for docker etc.) # var_unprivileged - 1 = unprivileged (secure, default), 0 = privileged (for podman/docker)
header_info "$APP" header_info "$APP"
variables variables
@@ -45,39 +45,32 @@ function update_script() {
# check_for_gh_release returns 0 (true) if update available, 1 (false) if not # check_for_gh_release returns 0 (true) if update available, 1 (false) if not
if check_for_gh_release "[appname]" "[owner/repo]"; then if check_for_gh_release "[appname]" "[owner/repo]"; then
msg_info "Stopping Services" msg_info "Stopping Service"
systemctl stop [appname] systemctl stop [appname]
msg_ok "Stopped Services" msg_ok "Stopped Service"
# Optional: Backup important data before update # Optional: Backup important data before update
msg_info "Creating Backup" msg_info "Backing up Data"
mkdir -p /tmp/[appname]_backup cp -r /opt/[appname]/data /opt/[appname]_data_backup 2>/dev/null || true
cp /opt/[appname]/.env /tmp/[appname]_backup/ 2>/dev/null || true msg_ok "Backed up Data"
cp -r /opt/[appname]/data /tmp/[appname]_backup/ 2>/dev/null || true
msg_ok "Created Backup"
# CLEAN_INSTALL=1 removes old directory before extracting new version # CLEAN_INSTALL=1 removes old directory before extracting new version
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "[appname]" "[owner/repo]" "tarball" "latest" "/opt/[appname]" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "[appname]" "[owner/repo]"
# Restore configuration and data # Restore configuration and data (if needed)
msg_info "Restoring Data" msg_info "Restoring Data"
cp /tmp/[appname]_backup/.env /opt/[appname]/ 2>/dev/null || true cp -r /opt/[appname]_data_backup/. /opt/[appname]/data/ 2>/dev/null || true
cp -r /tmp/[appname]_backup/data/* /opt/[appname]/data/ 2>/dev/null || true rm -rf /opt/[appname]_data_backup
rm -rf /tmp/[appname]_backup
msg_ok "Restored Data" msg_ok "Restored Data"
# Optional: Run any post-update commands # Optional: Run any post-update commands (npm, composer, migrations, etc.)
msg_info "Running Post-Update Tasks" # cd /opt/[appname] && $STD npm ci --production
cd /opt/[appname] # cd /opt/[appname] && $STD composer install --no-dev
# Examples: # cd /opt/[appname] && $STD php artisan migrate --force
# $STD npm ci --production
# $STD php artisan migrate --force
# $STD composer install --no-dev
msg_ok "Ran Post-Update Tasks"
msg_info "Starting Services" msg_info "Starting Service"
systemctl start [appname] systemctl start [appname]
msg_ok "Started Services" msg_ok "Started Service"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
@@ -14,90 +14,121 @@ setting_up_container
network_check network_check
update_os update_os
# =============================================================================
# AVAILABLE HELPER FUNCTIONS (from tools.func)
# =============================================================================
#
# LANGUAGE/RUNTIME SETUP (use these, DON'T do manual installation!):
# NODE_VERSION="22" setup_nodejs # Node.js (18, 20, 22)
# PYTHON_VERSION="3.13" setup_uv # Python with uv package manager
# GO_VERSION="1.22" setup_go # Go language
# RUST_CRATES="monolith" setup_rust # Rust
# RUBY_VERSION="3.3" setup_ruby # Ruby
# JAVA_VERSION="21" setup_java # Java (17, 21)
# PHP_VERSION="8.4" setup_php # PHP
#
# DATABASE SETUP (use these instead of manual setup!):
# setup_postgresql # PostgreSQL server
# PG_DB_NAME="mydb" PG_DB_USER="myuser" setup_postgresql_db # Create DB & user
# setup_mariadb # MariaDB server
# MARIADB_DB_NAME="mydb" setup_mariadb_db # Create MariaDB DB
# setup_mysql # MySQL server
# setup_mongodb # MongoDB server
#
# GITHUB RELEASES (PREFERRED - handles versioning automatically!):
# fetch_and_deploy_gh_release "appname" "owner/repo" # Auto-detect mode
# fetch_and_deploy_gh_release "appname" "owner/repo" "binary" # .deb package
# CLEAN_INSTALL=1 fetch_and_deploy_gh_release ... # Clean install (remove old dir first)
#
# UTILITIES:
# import_local_ip # Sets $LOCAL_IP variable (call early!)
# setup_ffmpeg # FFmpeg with codecs
# setup_imagemagick # ImageMagick 7
# setup_hwaccel # GPU acceleration
# setup_docker # Docker Engine
# setup_adminer # Adminer (DB web interface)
# ============================================================================= # =============================================================================
# DEPENDENCIES # DEPENDENCIES
# ============================================================================= # =============================================================================
# Only install what's actually needed - curl/sudo/mc are already in the base image
msg_info "Installing Dependencies" msg_info "Installing Dependencies"
$STD apt install -y \ $STD apt install -y \
nginx \ ca-certificates \
build-essential curl \
gnupg
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
# ============================================================================= # =============================================================================
# HELPER FUNCTIONS FROM tools.func # EXAMPLE: Node.js App with PostgreSQL
# =============================================================================
# These functions are available via $FUNCTIONS_FILE_PATH (tools.func)
# Call them with optional environment variables for configuration
#
# --- Runtime & Language Setup ---
# NODE_VERSION="22" setup_nodejs # Install Node.js (22, 24)
# NODE_VERSION="24" NODE_MODULE="pnpm" setup_nodejs # With pnpm
# PYTHON_VERSION="3.13" setup_uv # Python with uv package manager
# setup_go # Install Go (latest)
# setup_rust # Install Rust via rustup
# setup_ruby # Install Ruby
# PHP_VERSION="8.4" PHP_FPM="YES" PHP_MODULE="mysqli,gd" setup_php
# PHP_VERSION="8.3" PHP_FPM="YES" PHP_APACHE="YES" PHP_MODULE="bcmath,curl,gd,intl,mbstring,mysql,xml,zip" setup_php
# setup_composer # Install PHP Composer
# JAVA_VERSION="21" setup_java # Install Java (17, 21)
#
# --- Database Setup ---
# setup_mariadb # Install MariaDB server
# MARIADB_DB_NAME="mydb" MARIADB_DB_USER="myuser" setup_mariadb_db
# setup_mysql # Install MySQL server
# PG_VERSION="17" setup_postgresql # Install PostgreSQL (16, 17)
# PG_VERSION="17" PG_MODULES="postgis" setup_postgresql # With extensions
# PG_DB_NAME="mydb" PG_DB_USER="myuser" setup_postgresql_db
# setup_mongodb # Install MongoDB
#
# --- GitHub Release (PREFERRED METHOD) ---
# fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" # Downloads, extracts, tracks version
# fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" "latest" "/opt/appname"
# fetch_and_deploy_gh_release "appname" "owner/repo" "prebuild" "latest" "/opt/appname" "app-*.tar.gz"
#
# --- Tools & Utilities ---
# import_local_ip # Sets $LOCAL_IP variable (call early!)
# setup_ffmpeg # Install FFmpeg with codecs
# setup_hwaccel # Setup GPU hardware acceleration
# setup_imagemagick # Install ImageMagick 7
# setup_docker # Install Docker Engine
# setup_adminer # Install Adminer for DB management
# create_self_signed_cert # Creates cert in /etc/ssl/[appname]/
# =============================================================================
# EXAMPLE 1: Node.js Application with PostgreSQL
# ============================================================================= # =============================================================================
# NODE_VERSION="22" setup_nodejs # NODE_VERSION="22" setup_nodejs
# PG_VERSION="17" setup_postgresql # PG_VERSION="17" setup_postgresql
# PG_DB_NAME="myapp" PG_DB_USER="myapp" setup_postgresql_db # PG_DB_NAME="myapp" PG_DB_USER="myapp" setup_postgresql_db
# import_local_ip # import_local_ip
# fetch_and_deploy_gh_release "myapp" "owner/myapp" "tarball" "latest" "/opt/myapp"
# #
# msg_info "Configuring MyApp" # msg_info "Deploying Application"
# fetch_and_deploy_gh_release "myapp" "owner/myapp"
# msg_ok "Deployed Application"
#
# msg_info "Installing Dependencies"
# cd /opt/myapp # cd /opt/myapp
# $STD npm ci # $STD npm ci --production
# msg_ok "Installed Dependencies"
#
# msg_info "Configuring Environment"
# cat <<EOF >/opt/myapp/.env # cat <<EOF >/opt/myapp/.env
# DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost/${PG_DB_NAME} # DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost/${PG_DB_NAME}
# HOST=${LOCAL_IP} # APP_HOST=${LOCAL_IP}
# PORT=3000 # APP_PORT=3000
# NODE_ENV=production
# EOF # EOF
# msg_ok "Configured MyApp" # msg_ok "Configured Environment"
# ============================================================================= # =============================================================================
# EXAMPLE 2: Python Application with uv # EXAMPLE: Python App with uv
# ============================================================================= # =============================================================================
# PYTHON_VERSION="3.13" setup_uv # PYTHON_VERSION="3.13" setup_uv
# import_local_ip # import_local_ip
# fetch_and_deploy_gh_release "myapp" "owner/myapp" "tarball" "latest" "/opt/myapp" # msg_info "Deploying Application"
# fetch_and_deploy_gh_release "myapp" "owner/myapp"
# msg_ok "Deployed Application"
# #
# msg_info "Setting up MyApp" # msg_info "Installing Dependencies"
# cd /opt/myapp # cd /opt/myapp
# $STD uv sync # $STD uv sync --frozen
# msg_ok "Installed Dependencies"
#
# cat <<EOF >/opt/myapp/.env # cat <<EOF >/opt/myapp/.env
# HOST=${LOCAL_IP} # HOST=${LOCAL_IP}
# PORT=8000 # PORT=8000
# DEBUG=false
# EOF
# =============================================================================
# CREATE SYSTEMD SERVICE
# =============================================================================
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/[appname].service
[Unit]
Description=[AppName] Service
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/[appname]
Environment=NODE_ENV=production
ExecStart=/usr/bin/node /opt/[appname]/server.js
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now [appname]
msg_ok "Created Service"
# EOF # EOF
# msg_ok "Setup MyApp" # msg_ok "Setup MyApp"
+17 -11
View File
@@ -4,25 +4,26 @@
"categories": [ "categories": [
0 0
], ],
"date_created": "DATE CREATED", "date_created": "2026-01-18",
"type": "ct", "type": "ct",
"updateable": true, "updateable": true,
"privileged": false, "privileged": false,
"interface_port": "DEFAULT-PORT", "interface_port": 3000,
"documentation": null, "documentation": "https://docs.example.com/",
"website": "LINK TO WEBSITE", "website": "https://example.com/",
"logo": "LINK TO LOGO", "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/appname.webp",
"description": "Description of the app", "config_path": "/opt/appname/.env",
"description": "Short description of what AppName does and its main features.",
"install_methods": [ "install_methods": [
{ {
"type": "default", "type": "default",
"script": "ct/AppName.sh", "script": "ct/appname.sh",
"resources": { "resources": {
"cpu": 2, "cpu": 2,
"ram": 2048, "ram": 2048,
"hdd": 4, "hdd": 8,
"os": "debian", "os": "Debian",
"version": "12" "version": "13"
} }
} }
], ],
@@ -30,5 +31,10 @@
"username": null, "username": null,
"password": null "password": null
}, },
"notes": [] "notes": [
{
"text": "Change the default password after first login!",
"type": "warning"
}
]
} }