Update AGENTS.md

This commit is contained in:
CanbiZ (MickLesk)
2026-04-07 13:26:34 +02:00
parent c366bf4726
commit fbe0f31a6e

View File

@@ -5,18 +5,23 @@
## 🎯 Core Principles ## 🎯 Core Principles
### 1. **Maximum Use of `tools.func` Functions** ### 1. **Maximum Use of `tools.func` Functions**
We have an extensive library of helper functions. **NEVER** implement your own solutions when a function already exists! We have an extensive library of helper functions. **NEVER** implement your own solutions when a function already exists!
### 2. **No Pointless Variables** ### 2. **No Pointless Variables**
Only create variables when they: Only create variables when they:
- Are used multiple times - Are used multiple times
- Improve readability - Improve readability
- Are intended for configuration - Are intended for configuration
### 3. **Consistent Script Structure** ### 3. **Consistent Script Structure**
All scripts follow an identical structure. Deviations are not acceptable. All scripts follow an identical structure. Deviations are not acceptable.
### 4. **Bare-Metal Installation** ### 4. **Bare-Metal Installation**
We do **NOT use Docker** for our installation scripts. All applications are installed directly on the system. We do **NOT use Docker** for our installation scripts. All applications are installed directly on the system.
--- ---
@@ -164,12 +169,13 @@ cleanup_lxc
### Release Management ### Release Management
| Function | Description | Example | | Function | Description | Example |
|----------|-------------|----------| | ----------------------------- | ------------------------------------- | ---------------------------------------------------------- |
| `fetch_and_deploy_gh_release` | Fetches and installs GitHub Release | `fetch_and_deploy_gh_release "app" "owner/repo" "tarball"` | | `fetch_and_deploy_gh_release` | Fetches and installs GitHub Release | `fetch_and_deploy_gh_release "app" "owner/repo" "tarball"` |
| `check_for_gh_release` | Checks for new version | `if check_for_gh_release "app" "owner/repo"; then` | | `check_for_gh_release` | Checks for new version | `if check_for_gh_release "app" "owner/repo"; then` |
| `get_latest_github_release` | Returns latest release version string | `VERSION=$(get_latest_github_release "owner/repo")` | | `get_latest_github_release` | Returns latest release version string | `VERSION=$(get_latest_github_release "owner/repo")` |
**Modes for `fetch_and_deploy_gh_release`:** **Modes for `fetch_and_deploy_gh_release`:**
```bash ```bash
# Tarball/Source (Standard) - always specify "tarball" explicitly # Tarball/Source (Standard) - always specify "tarball" explicitly
fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" fetch_and_deploy_gh_release "appname" "owner/repo" "tarball"
@@ -185,6 +191,7 @@ fetch_and_deploy_gh_release "appname" "owner/repo" "singlefile" "latest" "/opt/a
``` ```
**Clean Install Flag:** **Clean Install Flag:**
```bash ```bash
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo" "tarball"
``` ```
@@ -194,7 +201,7 @@ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo" "tarball"
### Runtime/Language Setup ### Runtime/Language Setup
| Function | Variable(s) | Example | | Function | Variable(s) | Example |
|----------|-------------|----------| | -------------- | ----------------------------- | ---------------------------------------------------- |
| `setup_nodejs` | `NODE_VERSION`, `NODE_MODULE` | `NODE_VERSION="22" setup_nodejs` | | `setup_nodejs` | `NODE_VERSION`, `NODE_MODULE` | `NODE_VERSION="22" setup_nodejs` |
| `setup_uv` | `UV_PYTHON` | `UV_PYTHON="3.12" setup_uv` | | `setup_uv` | `UV_PYTHON` | `UV_PYTHON="3.12" setup_uv` |
| `setup_go` | `GO_VERSION` | `GO_VERSION="1.22" setup_go` | | `setup_go` | `GO_VERSION` | `GO_VERSION="1.22" setup_go` |
@@ -206,7 +213,7 @@ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo" "tarball"
### Database Setup ### Database Setup
| Function | Variable(s) | Example | | Function | Variable(s) | Example |
|----------|-------------|----------| | --------------------- | ------------------------------------ | ----------------------------------------------------------- |
| `setup_postgresql` | `PG_VERSION`, `PG_MODULES` | `PG_VERSION="16" setup_postgresql` | | `setup_postgresql` | `PG_VERSION`, `PG_MODULES` | `PG_VERSION="16" setup_postgresql` |
| `setup_postgresql_db` | `PG_DB_NAME`, `PG_DB_USER` | `PG_DB_NAME="mydb" PG_DB_USER="myuser" setup_postgresql_db` | | `setup_postgresql_db` | `PG_DB_NAME`, `PG_DB_USER` | `PG_DB_NAME="mydb" PG_DB_USER="myuser" setup_postgresql_db` |
| `setup_mariadb_db` | `MARIADB_DB_NAME`, `MARIADB_DB_USER` | `MARIADB_DB_NAME="mydb" setup_mariadb_db` | | `setup_mariadb_db` | `MARIADB_DB_NAME`, `MARIADB_DB_USER` | `MARIADB_DB_NAME="mydb" setup_mariadb_db` |
@@ -217,7 +224,7 @@ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo" "tarball"
### Tools & Utilities ### Tools & Utilities
| Function | Description | | Function | Description |
|----------|-------------| | ------------------- | ---------------------------------- |
| `setup_adminer` | Installs Adminer for DB management | | `setup_adminer` | Installs Adminer for DB management |
| `setup_composer` | Install PHP Composer | | `setup_composer` | Install PHP Composer |
| `setup_ffmpeg` | Install FFmpeg | | `setup_ffmpeg` | Install FFmpeg |
@@ -228,7 +235,7 @@ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo" "tarball"
### Helper Utilities ### Helper Utilities
| Function/Variable | Description | Example | | Function/Variable | Description | Example |
|-------------------|-------------|----------| | ----------------------------- | ------------------------------------------------------ | ----------------------------------------- |
| `$LOCAL_IP` | Always available - contains the container's IP address | `echo "Access: http://${LOCAL_IP}:3000"` | | `$LOCAL_IP` | Always available - contains the container's IP address | `echo "Access: http://${LOCAL_IP}:3000"` |
| `ensure_dependencies` | Checks/installs dependencies | `ensure_dependencies curl jq` | | `ensure_dependencies` | Checks/installs dependencies | `ensure_dependencies curl jq` |
| `install_packages_with_retry` | APT install with retry | `install_packages_with_retry nginx redis` | | `install_packages_with_retry` | APT install with retry | `install_packages_with_retry nginx redis` |
@@ -238,6 +245,7 @@ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo" "tarball"
## ❌ Anti-Patterns (NEVER use!) ## ❌ Anti-Patterns (NEVER use!)
### 1. Pointless Variables ### 1. Pointless Variables
```bash ```bash
# ❌ WRONG - unnecessary variables # ❌ WRONG - unnecessary variables
APP_NAME="myapp" APP_NAME="myapp"
@@ -251,6 +259,7 @@ cd /opt/myapp
``` ```
### 2. Custom Download Logic ### 2. Custom Download Logic
```bash ```bash
# ❌ WRONG - custom wget/curl logic # ❌ WRONG - custom wget/curl logic
RELEASE=$(curl -s https://api.github.com/repos/owner/repo/releases/latest | jq -r '.tag_name') RELEASE=$(curl -s https://api.github.com/repos/owner/repo/releases/latest | jq -r '.tag_name')
@@ -263,6 +272,7 @@ fetch_and_deploy_gh_release "myapp" "owner/repo"
``` ```
### 3. Custom Version-Check Logic ### 3. Custom Version-Check Logic
```bash ```bash
# ❌ WRONG - custom version check # ❌ WRONG - custom version check
CURRENT=$(cat /opt/myapp/version.txt) CURRENT=$(cat /opt/myapp/version.txt)
@@ -278,6 +288,7 @@ fi
``` ```
### 4. Docker-based Installation ### 4. Docker-based Installation
```bash ```bash
# ❌ WRONG - using Docker # ❌ WRONG - using Docker
docker pull myapp/myapp:latest docker pull myapp/myapp:latest
@@ -289,6 +300,7 @@ npm install && npm run build
``` ```
### 5. Custom Runtime Installation ### 5. Custom Runtime Installation
```bash ```bash
# ❌ WRONG - custom Node.js installation # ❌ WRONG - custom Node.js installation
curl -fsSL https://deb.nodesource.com/setup_22.x | bash - curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
@@ -299,6 +311,7 @@ NODE_VERSION="22" setup_nodejs
``` ```
### 6. Redundant echo Statements ### 6. Redundant echo Statements
```bash ```bash
# ❌ WRONG - custom logging messages # ❌ WRONG - custom logging messages
echo "Installing dependencies..." echo "Installing dependencies..."
@@ -312,6 +325,7 @@ msg_ok "Installed Dependencies"
``` ```
### 7. Missing $STD Usage ### 7. Missing $STD Usage
```bash ```bash
# ❌ WRONG - apt without $STD # ❌ WRONG - apt without $STD
apt install -y nginx apt install -y nginx
@@ -321,6 +335,7 @@ $STD apt install -y nginx
``` ```
### 8. Wrapping `tools.func` Functions in msg Blocks ### 8. Wrapping `tools.func` Functions in msg Blocks
```bash ```bash
# ❌ WRONG - tools.func functions have their own msg_info/msg_ok! # ❌ WRONG - tools.func functions have their own msg_info/msg_ok!
msg_info "Installing Node.js" msg_info "Installing Node.js"
@@ -338,6 +353,7 @@ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo"
``` ```
**Functions with built-in messages (NEVER wrap in msg blocks):** **Functions with built-in messages (NEVER wrap in msg blocks):**
- `fetch_and_deploy_gh_release` - `fetch_and_deploy_gh_release`
- `check_for_gh_release` - `check_for_gh_release`
- `setup_nodejs` - `setup_nodejs`
@@ -359,6 +375,7 @@ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo"
- `setup_hwaccel` - `setup_hwaccel`
### 9. Creating Unnecessary System Users ### 9. Creating Unnecessary System Users
```bash ```bash
# ❌ WRONG - LXC containers run as root, no separate user needed # ❌ WRONG - LXC containers run as root, no separate user needed
useradd -m -s /usr/bin/bash appuser useradd -m -s /usr/bin/bash appuser
@@ -371,6 +388,7 @@ $STD npm install
``` ```
### 10. Using `export` in .env Files ### 10. Using `export` in .env Files
```bash ```bash
# ❌ WRONG - export is unnecessary in .env files # ❌ WRONG - export is unnecessary in .env files
cat <<EOF >/opt/appname/.env cat <<EOF >/opt/appname/.env
@@ -388,6 +406,7 @@ EOF
``` ```
### 11. Using External Shell Scripts ### 11. Using External Shell Scripts
```bash ```bash
# ❌ WRONG - external script that gets executed # ❌ WRONG - external script that gets executed
cat <<'EOF' >/opt/appname/install_script.sh cat <<'EOF' >/opt/appname/install_script.sh
@@ -407,6 +426,7 @@ $STD npm run build
``` ```
### 12. Using `sudo` in LXC Containers ### 12. Using `sudo` in LXC Containers
```bash ```bash
# ❌ WRONG - sudo is unnecessary in LXC (already root) # ❌ WRONG - sudo is unnecessary in LXC (already root)
sudo -u postgres psql -c "CREATE DATABASE mydb;" sudo -u postgres psql -c "CREATE DATABASE mydb;"
@@ -420,6 +440,7 @@ $STD npm install
``` ```
### 13. Unnecessary `systemctl daemon-reload` ### 13. Unnecessary `systemctl daemon-reload`
```bash ```bash
# ❌ WRONG - daemon-reload is only needed when MODIFYING existing services # ❌ WRONG - daemon-reload is only needed when MODIFYING existing services
cat <<EOF >/etc/systemd/system/appname.service cat <<EOF >/etc/systemd/system/appname.service
@@ -436,6 +457,7 @@ systemctl enable -q --now appname
``` ```
### 14. Creating Custom Credentials Files ### 14. Creating Custom Credentials Files
```bash ```bash
# ❌ WRONG - custom credentials file is not part of the standard template # ❌ WRONG - custom credentials file is not part of the standard template
msg_info "Saving Credentials" msg_info "Saving Credentials"
@@ -450,6 +472,7 @@ msg_ok "Saved Credentials"
``` ```
### 15. Wrong Footer Pattern ### 15. Wrong Footer Pattern
```bash ```bash
# ❌ WRONG - old cleanup pattern with msg blocks # ❌ WRONG - old cleanup pattern with msg blocks
motd_ssh motd_ssh
@@ -467,6 +490,7 @@ cleanup_lxc
``` ```
### 16. Manual Database Creation Instead of Functions ### 16. Manual Database Creation Instead of Functions
```bash ```bash
# ❌ WRONG - manual database creation # ❌ WRONG - manual database creation
DB_USER="myuser" DB_USER="myuser"
@@ -481,6 +505,7 @@ PG_DB_NAME="mydb" PG_DB_USER="myuser" PG_DB_EXTENSIONS="postgis" setup_postgresq
``` ```
### 18. Hardcoded Versions for External Tools ### 18. Hardcoded Versions for External Tools
```bash ```bash
# ❌ WRONG - hardcoded versions that will become outdated # ❌ WRONG - hardcoded versions that will become outdated
RESTIC_VERSION="0.18.1" RESTIC_VERSION="0.18.1"
@@ -497,6 +522,7 @@ VERSION=$(get_latest_github_release "restic/restic")
``` ```
### 19. Backing Up to /tmp in Update Scripts ### 19. Backing Up to /tmp in Update Scripts
```bash ```bash
# ❌ WRONG - /tmp can be cleared by the system # ❌ WRONG - /tmp can be cleared by the system
msg_info "Backing up Configuration" msg_info "Backing up Configuration"
@@ -515,6 +541,7 @@ rm -f /opt/appname.env.bak
``` ```
### 20. Using "(Patience)" in msg_info by Default ### 20. Using "(Patience)" in msg_info by Default
```bash ```bash
# ❌ WRONG - "(Patience)" should not be a default label # ❌ WRONG - "(Patience)" should not be a default label
msg_info "Building Application (Patience)" msg_info "Building Application (Patience)"
@@ -528,6 +555,7 @@ msg_ok "Built Application"
``` ```
### 21. Writing Files Without Heredocs ### 21. Writing Files Without Heredocs
```bash ```bash
# ❌ WRONG - echo / printf / tee # ❌ WRONG - echo / printf / tee
echo "# Config" > /opt/app/config.yml echo "# Config" > /opt/app/config.yml
@@ -546,6 +574,7 @@ EOF
``` ```
### 22. Using `apt-get` Instead of `apt` ### 22. Using `apt-get` Instead of `apt`
```bash ```bash
# ❌ WRONG - apt-get is not the project convention # ❌ WRONG - apt-get is not the project convention
$STD apt-get install -y nginx $STD apt-get install -y nginx
@@ -557,6 +586,7 @@ $STD apt update
``` ```
### 23. Listing Core/Pre-installed Packages as Dependencies ### 23. Listing Core/Pre-installed Packages as Dependencies
```bash ```bash
# ❌ WRONG - curl is already installed by _bootstrap() in install.func # ❌ WRONG - curl is already installed by _bootstrap() in install.func
# sudo is already available in LXC, mc is not a dependency # sudo is already available in LXC, mc is not a dependency
@@ -575,6 +605,7 @@ msg_ok "Installed Dependencies"
``` ```
**Packages that must NOT be listed as dependencies (already available):** **Packages that must NOT be listed as dependencies (already available):**
- `curl` — installed by `_bootstrap()` in `install.func` - `curl` — installed by `_bootstrap()` in `install.func`
- `sudo` — base LXC package (and scripts run as root anyway) - `sudo` — base LXC package (and scripts run as root anyway)
- `wget` — base Debian LXC package - `wget` — base Debian LXC package
@@ -591,6 +622,7 @@ msg_ok "Installed Dependencies"
## 📝 Important Rules ## 📝 Important Rules
### Variable Declarations (CT Script) ### Variable Declarations (CT Script)
```bash ```bash
# Standard declarations (ALWAYS present) # Standard declarations (ALWAYS present)
APP="AppName" APP="AppName"
@@ -604,6 +636,7 @@ var_unprivileged="${var_unprivileged:-1}"
``` ```
### Update-Script Pattern ### Update-Script Pattern
```bash ```bash
function update_script() { function update_script() {
header_info header_info
@@ -653,6 +686,7 @@ function update_script() {
``` ```
### Systemd Service Pattern ### Systemd Service Pattern
```bash ```bash
msg_info "Creating Service" msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/appname.service cat <<EOF >/etc/systemd/system/appname.service
@@ -677,6 +711,7 @@ msg_ok "Created Service"
``` ```
### Installation Script Footer ### Installation Script Footer
```bash ```bash
# ALWAYS at the end of the install script: # ALWAYS at the end of the install script:
motd_ssh motd_ssh
@@ -712,12 +747,14 @@ cleanup_lxc
## 📖 Reference: Good Example (Termix) ## 📖 Reference: Good Example (Termix)
### CT Script: [ct/termix.sh](ct/termix.sh) ### CT Script: [ct/termix.sh](ct/termix.sh)
- Uses `check_for_gh_release` for version checking - Uses `check_for_gh_release` for version checking
- Uses `CLEAN_INSTALL=1 fetch_and_deploy_gh_release` for clean updates - Uses `CLEAN_INSTALL=1 fetch_and_deploy_gh_release` for clean updates
- Backup/restore of `/opt/termix/data` - Backup/restore of `/opt/termix/data`
- Correct structure with all required variables - Correct structure with all required variables
### Install Script: [install/termix-install.sh](install/termix-install.sh) ### Install Script: [install/termix-install.sh](install/termix-install.sh)
- `NODE_VERSION="22" setup_nodejs` instead of manual installation - `NODE_VERSION="22" setup_nodejs` instead of manual installation
- `fetch_and_deploy_gh_release "termix" "Termix-SSH/Termix"` instead of wget/curl - `fetch_and_deploy_gh_release "termix" "Termix-SSH/Termix"` instead of wget/curl
- Clean service configuration - Clean service configuration
@@ -770,7 +807,7 @@ Every application requires a JSON metadata file in `json/<appname>.json`.
### Required Fields ### Required Fields
| Field | Type | Description | | Field | Type | Description |
|-------|------|-------------| | --------------------- | ------- | -------------------------------------------------- |
| `name` | string | Display name of the application | | `name` | string | Display name of the application |
| `slug` | string | Lowercase, no spaces, used for filenames | | `slug` | string | Lowercase, no spaces, used for filenames |
| `categories` | array | Category ID(s) - see category list below | | `categories` | array | Category ID(s) - see category list below |
@@ -791,7 +828,7 @@ Every application requires a JSON metadata file in `json/<appname>.json`.
### Categories ### Categories
| ID | Category | | ID | Category |
|----|----------| | --- | ------------------------- |
| 0 | Miscellaneous | | 0 | Miscellaneous |
| 1 | Proxmox & Virtualization | | 1 | Proxmox & Virtualization |
| 2 | Operating Systems | | 2 | Operating Systems |
@@ -806,7 +843,7 @@ Every application requires a JSON metadata file in `json/<appname>.json`.
| 11 | Files & Downloads | | 11 | Files & Downloads |
| 12 | Documents & Notes | | 12 | Documents & Notes |
| 13 | Media & Streaming | | 13 | Media & Streaming |
| 14 | *Arr Suite | | 14 | \*Arr Suite |
| 15 | NVR & Cameras | | 15 | NVR & Cameras |
| 16 | IoT & Smart Home | | 16 | IoT & Smart Home |
| 17 | ZigBee, Z-Wave & Matter | | 17 | ZigBee, Z-Wave & Matter |
@@ -846,6 +883,7 @@ Every application requires a JSON metadata file in `json/<appname>.json`.
``` ```
Or no credentials: Or no credentials:
```json ```json
"default_credentials": { "default_credentials": {
"username": null, "username": null,