# Community Scripts Rules

> Guides AI agents working on Community Scripts / Proxmox VE Helper Scripts contributions. Use when creating, updating, testing, or opening PRs for community-scripts/ProxmoxVED or community-scripts/ProxmoxVE, or when the user mentions Community Scripts, ProxmoxVED, ProxmoxVE helper scripts, ct scripts, install scripts, json metadata, dev_mode, or the official PR template.

- Skill: `aroldobossoni/community-scripts-rules` (Agent Skill)
- Install (CLI): `npx skillmds@latest add aroldobossoni/community-scripts-rules`
- Raw SKILL.md: https://api.skillmd.com/api/skills/aroldobossoni/community-scripts-rules/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: aroldobossoni (https://skillmd.com/u/aroldobossoni)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/aroldobossoni/community-scripts-rules

---


# Community Scripts Rules

Use this skill before changing, testing, or submitting Community Scripts work.

## Official Sources

Always verify current rules from official sources before coding or opening a PR:

- `https://community-scripts.org/docs`
- `https://community-scripts.org/docs/contribution`
- `https://community-scripts.org/docs/dev_mode`
- `https://github.com/community-scripts/ProxmoxVED`
- `https://github.com/community-scripts/ProxmoxVED/blob/main/.github/pull_request_template.md`
- `https://github.com/community-scripts/ProxmoxVED/blob/main/AGENTS.md`
- `https://github.com/community-scripts/ProxmoxVED/blob/main/.github/agents/pve-script-creator.agent.md`
- `https://github.com/community-scripts/ProxmoxVE/blob/main/CONTRIBUTING.md`

Prefer raw GitHub URLs when fetching markdown:

- `https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/.github/pull_request_template.md`
- `https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/AGENTS.md`
- `https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/.github/agents/pve-script-creator.agent.md`
- `https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/CONTRIBUTING.md`

If official sources conflict, use `ProxmoxVED` rules for new scripts and `ProxmoxVE` rules for fixes to existing promoted scripts.

## Repository Routing

- New scripts go to `community-scripts/ProxmoxVED`.
- Existing script fixes, improvements, and features go to `community-scripts/ProxmoxVE`.
- Do not open new-script PRs directly against `ProxmoxVE`; they are closed without review.
- Keep PRs small and focused.

## Mandatory ProxmoxVED Rules

For new ProxmoxVED application scripts:

- Create exactly three files: `ct/<app>.sh`, `install/<app>-install.sh`, and `json/<app>.json`.
- CT scripts source `misc/build.func` (or `build.func`).
- Install scripts source `$FUNCTIONS_FILE_PATH`.
- CT scripts declare all required `var_*` values, including `var_arm64`.
- CT scripts implement `update_script()`.
- CT scripts end with `start`, `build_container`, `description`, and the standard access footer.
- Install scripts call `color`, `verb_ip6`, `catch_errors`, `setting_up_container`, `network_check`, and `update_os`.
- Install scripts end with `motd_ssh`, `customize`, and `cleanup_lxc`.
- Prefer bare-metal installation; never use Docker for installation scripts.
- Use helper functions instead of custom implementations.

## Required Helpers

Always use project helpers instead of custom implementations:

### Source Deploy & Release Fetchers
- `fetch_and_deploy_gh_release "<app>" "owner/repo" "<mode>" ["latest"] ["/opt/<app>"] ["<asset-pattern>"]`
  - GitHub releases. Modes: `tarball` (source), `binary` (.deb), `prebuild` (prebuilt archive), `singlefile` (single binary).
  - The resolved version is written to `~/.<app>` (read back with `cat ~/.<app>` when needed at build/runtime).
- `fetch_and_deploy_gl_release` / `fetch_and_deploy_gl_tag`
  - GitLab (self-hosted or gitlab.com).
  - Set `GITLAB_URL="https://gitlab.example.org"` (default `https://gitlab.com`) and optional `GITLAB_TOKEN`.
  - Same modes as GitHub helper. Do not use GitHub helper for GitLab repositories.
- `fetch_and_deploy_codeberg_release`
  - Codeberg releases.
- `fetch_and_deploy_from_url`
  - Fallback for fixed URLs when no release API fits (avoids hand-rolled curl/tar).
- Multi-arch asset resolution:
  - Build asset patterns with `arch_resolve "x86_64" "arm64"` instead of hardcoding architecture strings.

### Update Checks
- `check_for_gh_release "<app>" "owner/repo"` (returns 0 when newer release exists).
- `check_for_gl_release` (with `GITLAB_URL`).
- `get_latest_github_release "owner/repo"` (returns latest release version string).

### Runtimes
- `NODE_VERSION="22" NODE_MODULE="pnpm@x" setup_nodejs`
- `setup_go` (no argument = latest; never pin a bare `1.23` — requires full `1.23.x`)
- `RUST_CRATES="..." setup_rust`
- `UV_PYTHON="3.12" setup_uv`
- `RUBY_VERSION setup_ruby`
- `JAVA_VERSION setup_java`
- `PHP_VERSION="8.3" PHP_MODULE="gd,intl,mysql" PHP_FPM="YES" setup_php` (note singular `PHP_MODULE`)

### Databases
- `setup_postgresql` + `PG_DB_NAME PG_DB_USER PG_DB_EXTENSIONS="vector,pg_stat_statements" [PG_DB_GRANT_SUPERUSER="true"] setup_postgresql_db`
  - List every extension enabled by app schema. Non-trusted extensions need pre-creating. Grant superuser only if strictly needed.
- `setup_mariadb` + `setup_mariadb_db`
- `setup_mysql` + `setup_mysql_db`
- `setup_mongodb`
- `setup_clickhouse`
- `setup_meilisearch`

### Tools & Infrastructure
- `setup_composer`
- `setup_ffmpeg`
- `setup_imagemagick`
- `setup_gs`
- `setup_yq`
- `setup_adminer`
- `setup_hwaccel`
- `setup_nltk`

### Repositories, Services, Dependencies & TLS
- `setup_deb822_repo "name" "<gpg_url>" "<repo_url>" "<suite>" ["component"] ["archs"]` for 3rd-party APT repositories (never hand-roll GPG keys or sources.list files).
- `safe_service_restart <svc>`
- `ensure_dependencies <pkg...>` (installs jq, openssl, etc. on demand).
- `install_packages_with_retry <pkg...>`
- `create_self_signed_cert "<app>"` -> `/etc/ssl/<app>/<app>.{crt,key}` (SAN covers hostname + container IP + localhost; never hand-roll openssl).

## Data Persistence & Updates (Critical)

`CLEAN_INSTALL=1 fetch_and_deploy_*` wipes `/opt/<app>` before re-extracting. Any user state or secrets stored inside `/opt/<app>` will be permanently lost during updates.

Follow these strict rules:

1. **Standard Pattern (Preferred):**
   - Store all persistent state and data outside the app directory in `/opt/<app>_data` (NOT `/opt/<app>/data`).
   - Point the application there via its data directory configuration or environment variables (e.g. `DATA_DIR`, `*_DATA_DIR`).
   - Place non-regenerable configuration and secrets (signing keys, generated `.env`, `.toml`) in `/opt/<app>_data` as well.
   - Updates keep everything with **no backup or restore step required**.

2. **Exception Pattern (Manifest Backup Helpers):**
   - Only when data genuinely cannot be relocated outside `/opt/<app>`, back it up in `update_script()` using the manifest helpers (never use manual `cp` or `/tmp`):
     ```bash
     create_backup /opt/<app>/data /opt/<app>/.env
     CLEAN_INSTALL=1 fetch_and_deploy_gh_release ...
     restore_backup
     ```
   - `create_backup` copies paths into `/opt/<NSAPP>.backup` with a manifest, is idempotent, and aborts update on failure.
   - `restore_backup` restores every manifest path and removes the backup store.
   - Override default backup store location with `BACKUP_DIR` if `/opt/<NSAPP>.backup` clashes.

3. **Never back up to `/tmp`** (temporary directories can be cleared by the system).

## Secure-Context Web Apps (HTTPS)

Modern browser APIs such as `crypto.subtle` (Web Crypto / PKCE), `navigator.storage.getDirectory` (OPFS), service workers, and `SharedArrayBuffer` require a **secure context** (HTTPS or localhost). Applications using them break over plain `http://<IP>` with errors like `crypto.subtle is unavailable in insecure contexts`.

When an application requires a secure context:
- Terminate TLS with `create_self_signed_cert "<app>"` behind an Nginx reverse proxy listening on port 443 with SSL enabled.
- Redirect port 80 to port 443.
- Proxy requests to the application on its internal port (or serve static files directly).
- If the application source uses `SharedArrayBuffer`, configure cross-origin isolation headers on the HTTPS server:
  - `add_header Cross-Origin-Opener-Policy same-origin always;`
  - `add_header Cross-Origin-Embedder-Policy require-corp always;`
- In `json/<app>.json` `notes`, instruct users to accept the self-signed certificate in their browser and access the application via `https://`.

## Anti-Patterns

Never do these unless official rules explicitly change:

- Do not wrap `setup_*`, `fetch_and_deploy_*`, or `check_for_*` in `msg_info` / `msg_ok` blocks (they have built-in logging).
- Do not use Docker for ProxmoxVED install scripts.
- Do not implement custom download logic when a helper exists.
- Do not implement custom version checks when `check_for_*` helpers apply.
- Do not create pointless variables such as `APP_DIR`, `APP_USER`, or `APP_PORT`.
- Do not use `sudo`.
- Do not use `apt-get`; use `apt`.
- Do not list pre-installed core packages as dependencies: `curl`, `sudo`, `wget`, `gnupg`, `ca-certificates`, `jq`, `mc`.
- Do not hardcode credentials, secrets, or versions for external tools.
- Do not back up to `/tmp`; use `/opt`.
- Do not use `echo`, `printf`, or `tee` for file creation; use heredocs.
- Do not create external shell scripts, custom credentials files, or unnecessary system users.
- Do not use `export` in `.env` files.
- Do not add `systemctl daemon-reload` for new services unless current rules require it.
- Do not add `(Patience)` in message labels.
- Prefix package (`apt`), `npm`, and build commands with `$STD`.

## JSON Metadata

For `json/<app>.json`, include all required fields:

- Required fields:
  - `name`, `slug`, `categories`, `date_created`, `type`, `updateable`, `privileged`, `architectures`, `interface_port`
  - `documentation`, `website`, `repository`, `logo`, `description`
  - `install_methods`, `default_credentials`, `notes`
- Optional fields:
  - `platforms`, `app_vars`

### Metadata Rules

- **No top-level `config_path`:** `config_path` belongs under individual install methods in `install_methods` (a script can have multiple methods with different paths).
- **`date_created`:** Today's date in `YYYY-MM-DD` format.
- **`install_methods.resources`:** Must match CT script variables (`var_cpu`, `var_ram`, `var_disk`, `var_os`, `var_version`).
- **`repository`:** Upstream repository as a full URL (e.g., `https://github.com/owner/repo`, `https://gitlab.com/owner/repo`, `https://codeberg.org/owner/repo`). Never bare `owner/repo`.
- **`logo`:** Use CDN pattern: `https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/<slug>.webp`.
- **`architectures`:** Replaced the deprecated `has_arm` boolean. It must match `var_arm64` in the CT script (`arch_check` aborts with exit code 106 on arm64 hosts when CT script says `no`):

| `var_arm64` | `architectures`        |
| ----------- | ---------------------- |
| `yes`       | `["amd64", "arm64"]`   |
| `no`        | `["amd64"]`            |
| unset       | omit field             |

- **`platforms` (optional):** `["pve"]`, `["incus"]` or both. Defaults to Proxmox VE if omitted. Only claim `incus` if script exists in the Incus repository.
- **`app_vars` (optional):** Declares variables for unattended installs. Requires matching 3-part implementation:
  1. `install/<app>-install.sh` (prompts only when unset):
     ```bash
     if [[ -z "${var_admin_user:-}" ]]; then
       read -rp "${TAB3}Admin username: " var_admin_user
     fi
     var_admin_user="${var_admin_user:-admin}"
     ```
  2. `ct/<app>.sh` (exports variable to container environment):
     ```bash
     export var_admin_user="${var_admin_user:-}"
     ```
  3. `json/<app>.json` (declares parameter metadata):
     ```json
     "app_vars": [
       { "name": "var_admin_user", "label": "Admin Username", "type": "text", "default": "admin" },
       { "name": "var_admin_token", "label": "API Token", "type": "password", "secret": true, "required": true, "help": "The script exits when this is empty" }
     ]
     ```
  - Supported `type` values: `text`, `password`, `number`, `boolean` (emits `yes`/`no`), `select` (with `options`).
  - Mark credentials and sensitive fields with `"secret": true`.

## Testing

Test on a real Proxmox host before PR when possible.

Useful development modes:

```bash
export dev_mode="keep,logs"
export var_verbose="yes"
bash -c "$(curl -fsSL https://raw.githubusercontent.com/<fork>/<repo>/<branch>/ct/<app>.sh)"
```

Use:

- `logs` for persistent logs under `/var/log/community-scripts/`.
- `keep` to preserve failed containers.
- `motd` for early SSH access.
- `pause` for step-by-step inspection.
- `breakpoint` for an interactive shell on failure.
- `trace` only in isolated environments because it can expose secrets.
- `dryrun` for simulation only.

Validate install, update path, service health, logs, credentials handling, exposed ports, and absence of hardcoded secrets.

## PR Template Rules

Use the official ProxmoxVED PR template verbatim. Do not replace it with a custom body.

For new scripts, the PR must include:

- `🆕 New script` checked.
- One arm64 option checked.
- All prerequisites checked only if true.
- Code and security review checkboxes checked only after self-review.
- Exactly one AI assistance option checked:
  - `No AI used`, or
  - `AI was used`.
- All Application Requirements checked only if true:
  - application is at least 6 months old;
  - actively maintained;
  - 600+ GitHub stars;
  - official release tarballs are published;
  - contributor understands not all scripts are accepted.
- Source links filled.

The automated check closes PRs missing required template sections or required checkbox selections.

## Work Sequence

1. Fetch current official rules from the sources above.
2. Decide the correct repo: `ProxmoxVED` for new scripts, `ProxmoxVE` for existing promoted scripts.
3. Inspect similar existing scripts before coding.
4. Implement with official helpers and standard structure (CT, install, JSON).
5. Test with `dev_mode="keep,logs"` and real Proxmox evidence.
6. Run the local checklist from this skill.
7. Open PR only after checks pass.
8. If the bot closes the PR, read the bot comment exactly and fix the missing rule before opening a replacement PR.

## Local Checklist

- [ ] Official sources checked this session.
- [ ] Correct target repository selected (`ProxmoxVED` for new, `ProxmoxVE` for fixes/updates).
- [ ] Exactly three files created: `ct/<slug>.sh`, `install/<slug>-install.sh`, `json/<slug>.json`.
- [ ] Script structure matches current templates (CT declarations, install flow, footers).
- [ ] Required helper functions used (fetch and deploy, runtimes, databases, tools).
- [ ] No wrapper `msg_*` calls around helpers with built-in logging.
- [ ] No anti-patterns present (no Docker, no `sudo`, no `apt-get`, `$STD` prefix on apt/build).
- [ ] Persistent data and configuration reside in `/opt/<app>_data` (or managed via `create_backup` / `restore_backup` manifest helpers).
- [ ] Backups go to `/opt`, never `/tmp`.
- [ ] Multi-arch asset patterns use `arch_resolve` (no hardcoded architecture tokens).
- [ ] 3rd-party APT repos use `setup_deb822_repo`; TLS certs use `create_self_signed_cert`.
- [ ] GitLab sources use `fetch_and_deploy_gl_release` / `check_for_gl_release` with `GITLAB_URL`.
- [ ] Secure-context web applications configured with HTTPS reverse proxy (and COOP/COEP headers if using `SharedArrayBuffer`).
- [ ] CT `var_arm64` accurately reflects arm64 support.
- [ ] JSON metadata present and consistent with CT script resources.
- [ ] JSON `architectures` agrees with CT `var_arm64` (`yes` -> `["amd64", "arm64"]`, `no` -> `["amd64"]`, unset -> omitted).
- [ ] JSON `repository` is a full URL (`https://...`), not bare `owner/repo`.
- [ ] No top-level `config_path` in JSON (configured on install methods).
- [ ] JSON `platforms` claims `incus` only if script exists in the Incus repository.
- [ ] Every `read` in install script is guarded by `-z "${var_x:-}"`, exported in `ct/<app>.sh`, and declared in JSON `app_vars`.
- [ ] Real install test completed or limitation documented.
- [ ] `update_script()` reviewed or tested.
- [ ] PR body uses official template verbatim.
- [ ] AI assistance checkbox is selected when AI was used.
- [ ] Bot comment reviewed if PR was closed.

