Compare commits

..

1 Commits

Author SHA1 Message Date
CanbiZ (MickLesk)
5a9a038610 fix(reitti): refactor scripts for v4 - remove RabbitMQ and Photon
- Remove rabbitmq-server from install dependencies
- Remove RabbitMQ configuration block from install script
- Remove Photon JAR download and photon.service from install script
- Remove RabbitMQ and Photon config from application.properties
- Update reitti.service After/Wants to drop rabbitmq and photon deps
- Add v3->v4 migration in update_script: purge RabbitMQ, disable Photon
  service, clean up application.properties and service unit file
- Remove orphaned nginx tile cache migration block from update_script

Refs: https://www.dedicatedcode.com/projects/reitti/4.0/upgrade/
2026-04-14 09:18:05 +02:00
161 changed files with 26597 additions and 3097 deletions

18
.gitattributes vendored
View File

@@ -4,29 +4,35 @@
*.sh linguist-detectable=true
*.bash linguist-language=Shell
*.func linguist-language=Shell
*.func linguist-detectable=true
*.install linguist-language=Shell
# ---------------------------------------
# Exclude header art from stats
# Treat Golang files as Go (for /api/)
api/**/*.go linguist-language=Go
# ---------------------------------------
ct/headers/* linguist-documentation
# Treat frontend as JavaScript/TypeScript (optional)
frontend/**/*.ts linguist-language=TypeScript
frontend/**/*.js linguist-language=JavaScript
# ---------------------------------------
# Exclude documentation from stats
# ---------------------------------------
*.md linguist-documentation
docs/** linguist-documentation
README.md linguist-documentation
CONTRIBUTING.md linguist-documentation
SECURITY.md linguist-documentation
# ---------------------------------------
# Exclude generated/config files
# ---------------------------------------
*.json linguist-generated
frontend/public/json/*.json linguist-generated=false
*.lock linguist-generated
*.yml linguist-generated
*.yaml linguist-generated
.github/** linguist-generated
.vscode/** linguist-generated
# ---------------------------------------
# Standard text handling
# ---------------------------------------
* text=auto eol=lf

3
.github/CODEOWNERS generated vendored
View File

@@ -12,3 +12,6 @@
# Set default reviewers
* @community-scripts/Contributor
# All changes in frontend
/frontend/ @community-scripts/Frontend-Dev

2
.github/pull_request_template.md generated vendored
View File

@@ -22,6 +22,6 @@ Fixes #
- [ ]**New feature** Adds new, non-breaking functionality.
- [ ] 💥 **Breaking change** Alters existing functionality in a way that may require updates.
- [ ] 🆕 **New script** A fully functional and tested script or script set.
- [ ] 🌍 **Website update** Changes to script metadata (PocketBase/website data).
- [ ] 🌍 **Website update** Changes to website-related JSON files or metadata.
- [ ] 🔧 **Refactoring / Code Cleanup** Improves readability or maintainability without changing functionality.
- [ ] 📝 **Documentation update** Changes to `README`, `AppName.md`, `CONTRIBUTING.md`, or other docs.

480
.github/workflows/pocketbase-bot.yml generated vendored
View File

@@ -31,8 +31,6 @@ jobs:
ACTOR: ${{ github.event.comment.user.login }}
ACTOR_ASSOCIATION: ${{ github.event.comment.author_association }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FRONTEND_URL: ${{ secrets.FRONTEND_URL }}
REVALIDATE_SECRET: ${{ secrets.REVALIDATE_SECRET }}
run: |
node << 'ENDSCRIPT'
(async function () {
@@ -115,6 +113,7 @@ jobs:
}
// ── Permission check ───────────────────────────────────────────────
// author_association: OWNER = repo/org owner, MEMBER = org member (includes Contributors team)
const association = process.env.ACTOR_ASSOCIATION;
if (association !== 'OWNER' && association !== 'MEMBER') {
await addReaction('-1');
@@ -129,11 +128,18 @@ jobs:
await addReaction('eyes');
// ── Parse command ──────────────────────────────────────────────────
// Formats (first line of comment):
// /pocketbase <slug> field=value [field=value ...] ← field updates (simple values)
// /pocketbase <slug> set <field> ← value from code block below
// /pocketbase <slug> note list|add|edit|remove ... ← note management
// /pocketbase <slug> method list ← list install methods
// /pocketbase <slug> method <type> cpu=N ram=N hdd=N ← edit install method resources
const commentBody = process.env.COMMENT_BODY || '';
const lines = commentBody.trim().split('\n');
const firstLine = lines[0].trim();
const withoutCmd = firstLine.replace(/^\/pocketbase\s+/, '').trim();
// Extract code block content from comment body (```...``` or ```lang\n...```)
function extractCodeBlock(body) {
const m = body.match(/```[^\n]*\n([\s\S]*?)```/);
return m ? m[1].trim() : null;
@@ -141,8 +147,6 @@ jobs:
const codeBlockValue = extractCodeBlock(commentBody);
const HELP_TEXT =
'**Show current state:**\n' +
'```\n/pocketbase <slug> info\n```\n\n' +
'**Field update (simple):** `/pocketbase <slug> field=value [field=value ...]`\n\n' +
'**Field update (HTML/multiline) — value from code block:**\n' +
'````\n' +
@@ -158,16 +162,12 @@ jobs:
'/pocketbase <slug> note edit <type> "<old text>" "<new text>"\n' +
'/pocketbase <slug> note remove <type> "<text>"\n' +
'```\n\n' +
'**Install method management:**\n' +
'**Install method resources:**\n' +
'```\n' +
'/pocketbase <slug> method list\n' +
'/pocketbase <slug> method <type> hdd=10\n' +
'/pocketbase <slug> method <type> cpu=4 ram=2048 hdd=20\n' +
'/pocketbase <slug> method <type> config_path="/opt/app/.env"\n' +
'/pocketbase <slug> method <type> os=debian version=13\n' +
'/pocketbase <slug> method add <type> cpu=2 ram=2048 hdd=8 os=debian version=13\n' +
'/pocketbase <slug> method remove <type>\n' +
'```\n' +
'Method fields: `cpu` `ram` `hdd` `os` `version` `config_path` `script`\n\n' +
'```\n\n' +
'**Editable fields:** `name` `description` `logo` `documentation` `website` `project_url` `github` ' +
'`config_path` `port` `default_user` `default_passwd` ' +
'`updateable` `privileged` `has_arm` `is_dev` ' +
@@ -189,7 +189,8 @@ jobs:
process.exit(0);
}
// ── PocketBase: authenticate ───────────────────────────────────────
// ── Allowed fields and their types ─────────────────────────────────
// ── PocketBase: authenticate (shared by all paths) ─────────────────
const raw = process.env.POCKETBASE_URL.replace(/\/$/, '');
const apiBase = /\/api$/i.test(raw) ? raw : raw + '/api';
const coll = process.env.POCKETBASE_COLLECTION;
@@ -209,7 +210,7 @@ jobs:
}
const token = JSON.parse(authRes.body).token;
// ── PocketBase: find record by slug ────────────────────────────────
// ── PocketBase: find record by slug (shared by all paths) ──────────
const recordsUrl = apiBase + '/collections/' + encodeURIComponent(coll) + '/records';
const filter = "(slug='" + slug.replace(/'/g, "''") + "')";
const listRes = await request(recordsUrl + '?filter=' + encodeURIComponent(filter) + '&perPage=1', {
@@ -227,164 +228,57 @@ jobs:
process.exit(0);
}
// ── Shared helpers ─────────────────────────────────────────────────
// Key=value parser: handles unquoted and "quoted" values
function parseKVPairs(str) {
const fields = {};
let pos = 0;
while (pos < str.length) {
while (pos < str.length && /\s/.test(str[pos])) pos++;
if (pos >= str.length) break;
let keyStart = pos;
while (pos < str.length && str[pos] !== '=' && !/\s/.test(str[pos])) pos++;
const key = str.substring(keyStart, pos).trim();
if (!key || pos >= str.length || str[pos] !== '=') { pos++; continue; }
pos++;
let value;
if (pos < str.length && str[pos] === '"') {
pos++;
let valStart = pos;
while (pos < str.length && str[pos] !== '"') {
if (str[pos] === '\\') pos++;
pos++;
}
value = str.substring(valStart, pos).replace(/\\"/g, '"');
if (pos < str.length) pos++;
} else {
let valStart = pos;
while (pos < str.length && !/\s/.test(str[pos])) pos++;
value = str.substring(valStart, pos);
}
fields[key] = value;
}
return fields;
}
// Token parser for note commands: unquoted-word OR "quoted string"
function parseTokens(str) {
const tokens = [];
let pos = 0;
while (pos < str.length) {
while (pos < str.length && /\s/.test(str[pos])) pos++;
if (pos >= str.length) break;
if (str[pos] === '"') {
pos++;
let start = pos;
while (pos < str.length && str[pos] !== '"') {
if (str[pos] === '\\') pos++;
pos++;
}
tokens.push(str.substring(start, pos).replace(/\\"/g, '"'));
if (pos < str.length) pos++;
} else {
let start = pos;
while (pos < str.length && !/\s/.test(str[pos])) pos++;
tokens.push(str.substring(start, pos));
}
}
return tokens;
}
// Read JSON blob from record (handles parsed objects and strings)
function readJsonBlob(val) {
if (Array.isArray(val)) return val;
try { return JSON.parse(val || '[]'); } catch (e) { return []; }
}
// Frontend cache revalidation (silent, best-effort)
async function revalidate(s) {
const frontendUrl = process.env.FRONTEND_URL;
const secret = process.env.REVALIDATE_SECRET;
if (!frontendUrl || !secret) return;
try {
await request(frontendUrl.replace(/\/$/, '') + '/api/revalidate', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + secret, 'Content-Type': 'application/json' },
body: JSON.stringify({ tags: ['scripts', 'script-' + s] })
});
} catch (e) { console.warn('Revalidation skipped:', e.message); }
}
// Format notes list for display
function formatNotesList(arr) {
if (arr.length === 0) return '*None*';
return arr.map(function (n, i) {
return (i + 1) + '. **`' + (n.type || '?') + '`**: ' + (n.text || '');
}).join('\n');
}
// Format install methods list for display
function formatMethodsList(arr) {
if (arr.length === 0) return '*None*';
return arr.map(function (im, i) {
const r = im.resources || {};
const parts = [
(r.os || '?') + ' ' + (r.version || '?'),
(r.cpu != null ? r.cpu : '?') + 'C / ' + (r.ram != null ? r.ram : '?') + ' MB / ' + (r.hdd != null ? r.hdd : '?') + ' GB'
];
if (im.config_path) parts.push('config: `' + im.config_path + '`');
if (im.script) parts.push('script: `' + im.script + '`');
return (i + 1) + '. **`' + (im.type || '?') + '`** — ' + parts.join(', ');
}).join('\n');
}
// ── Route: dispatch to subcommand handler ──────────────────────────
const infoMatch = rest.match(/^info$/i);
const noteMatch = rest.match(/^note\s+(list|add|edit|remove)\b/i);
const methodMatch = rest.match(/^method\b/i);
const setMatch = rest.match(/^set\s+(\S+)/i);
if (infoMatch) {
// ── INFO SUBCOMMAND ──────────────────────────────────────────────
const notesArr = readJsonBlob(record.notes_json);
const methodsArr = readJsonBlob(record.install_methods_json);
const out = [];
out.push(' **PocketBase Bot**: Info for **`' + slug + '`**\n');
out.push('**Basic info:**');
out.push('- **Name:** ' + (record.name || '—'));
out.push('- **Slug:** `' + slug + '`');
out.push('- **Port:** ' + (record.port != null ? '`' + record.port + '`' : '—'));
out.push('- **Updateable:** ' + (record.updateable ? 'Yes' : 'No'));
out.push('- **Privileged:** ' + (record.privileged ? 'Yes' : 'No'));
out.push('- **ARM:** ' + (record.has_arm ? 'Yes' : 'No'));
if (record.is_dev) out.push('- **Dev:** Yes');
if (record.is_disabled) out.push('- **Disabled:** Yes' + (record.disable_message ? ' — ' + record.disable_message : ''));
if (record.is_deleted) out.push('- **Deleted:** Yes' + (record.deleted_message ? ' — ' + record.deleted_message : ''));
out.push('');
out.push('**Links:**');
out.push('- **Website:** ' + (record.website || '—'));
out.push('- **Docs:** ' + (record.documentation || '—'));
out.push('- **Logo:** ' + (record.logo ? '[link](' + record.logo + ')' : '—'));
out.push('- **GitHub:** ' + (record.github || '—'));
if (record.config_path) out.push('- **Config:** `' + record.config_path + '`');
out.push('');
out.push('**Credentials:**');
out.push('- **User:** ' + (record.default_user || '—'));
out.push('- **Password:** ' + (record.default_passwd ? '*(set)*' : '—'));
out.push('');
out.push('**Install methods** (' + methodsArr.length + '):');
out.push(formatMethodsList(methodsArr));
out.push('');
out.push('**Notes** (' + notesArr.length + '):');
out.push(formatNotesList(notesArr));
await addReaction('+1');
await postComment(out.join('\n'));
} else if (noteMatch) {
// ── NOTE SUBCOMMAND ──────────────────────────────────────────────
if (noteMatch) {
// ── NOTE SUBCOMMAND (reads/writes notes_json on script record) ────
const noteAction = noteMatch[1].toLowerCase();
const noteArgsStr = rest.substring(noteMatch[0].length).trim();
let notesArr = readJsonBlob(record.notes_json);
async function patchNotes(arr) {
// Parse notes_json from the already-fetched script record
// PocketBase may return JSON fields as already-parsed objects
let notesArr = [];
try {
const rawNotes = record.notes_json;
notesArr = Array.isArray(rawNotes) ? rawNotes : JSON.parse(rawNotes || '[]');
} catch (e) { notesArr = []; }
// Token parser: unquoted-word OR "quoted string" (supports \" escapes)
function parseNoteTokens(str) {
const tokens = [];
let pos = 0;
while (pos < str.length) {
while (pos < str.length && /\s/.test(str[pos])) pos++;
if (pos >= str.length) break;
if (str[pos] === '"') {
pos++;
let start = pos;
while (pos < str.length && str[pos] !== '"') {
if (str[pos] === '\\') pos++;
pos++;
}
tokens.push(str.substring(start, pos).replace(/\\"/g, '"'));
if (pos < str.length) pos++;
} else {
let start = pos;
while (pos < str.length && !/\s/.test(str[pos])) pos++;
tokens.push(str.substring(start, pos));
}
}
return tokens;
}
function formatNotesList(arr) {
if (arr.length === 0) return '*None*';
return arr.map(function (n, i) {
return (i + 1) + '. **`' + (n.type || '?') + '`**: ' + (n.text || '');
}).join('\n');
}
async function patchNotesJson(arr) {
const res = await request(recordsUrl + '/' + record.id, {
method: 'PATCH',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
@@ -392,7 +286,7 @@ jobs:
});
if (!res.ok) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: Failed to update notes:\n```\n' + res.body + '\n```');
await postComment('❌ **PocketBase Bot**: Failed to update `notes_json`:\n```\n' + res.body + '\n```');
process.exit(1);
}
}
@@ -405,7 +299,7 @@ jobs:
);
} else if (noteAction === 'add') {
const tokens = parseTokens(noteArgsStr);
const tokens = parseNoteTokens(noteArgsStr);
if (tokens.length < 2) {
await addReaction('-1');
await postComment(
@@ -417,8 +311,7 @@ jobs:
const noteType = tokens[0].toLowerCase();
const noteText = tokens.slice(1).join(' ');
notesArr.push({ type: noteType, text: noteText });
await patchNotes(notesArr);
await revalidate(slug);
await patchNotesJson(notesArr);
await addReaction('+1');
await postComment(
'✅ **PocketBase Bot**: Added note to **`' + slug + '`**\n\n' +
@@ -428,7 +321,7 @@ jobs:
);
} else if (noteAction === 'edit') {
const tokens = parseTokens(noteArgsStr);
const tokens = parseNoteTokens(noteArgsStr);
if (tokens.length < 3) {
await addReaction('-1');
await postComment(
@@ -453,8 +346,7 @@ jobs:
process.exit(0);
}
notesArr[idx].text = newText;
await patchNotes(notesArr);
await revalidate(slug);
await patchNotesJson(notesArr);
await addReaction('+1');
await postComment(
'✅ **PocketBase Bot**: Edited note in **`' + slug + '`**\n\n' +
@@ -465,7 +357,7 @@ jobs:
);
} else if (noteAction === 'remove') {
const tokens = parseTokens(noteArgsStr);
const tokens = parseNoteTokens(noteArgsStr);
if (tokens.length < 2) {
await addReaction('-1');
await postComment(
@@ -489,8 +381,7 @@ jobs:
);
process.exit(0);
}
await patchNotes(notesArr);
await revalidate(slug);
await patchNotesJson(notesArr);
await addReaction('+1');
await postComment(
'✅ **PocketBase Bot**: Removed note from **`' + slug + '`**\n\n' +
@@ -501,36 +392,36 @@ jobs:
}
} else if (methodMatch) {
// ── METHOD SUBCOMMAND ────────────────────────────────────────────
// ── METHOD SUBCOMMAND (reads/writes install_methods_json on script record) ──
const methodArgs = rest.replace(/^method\s*/i, '').trim();
const methodListMode = !methodArgs || methodArgs.toLowerCase() === 'list';
let methodsArr = readJsonBlob(record.install_methods_json);
// Method field classification
const RESOURCE_KEYS = { cpu: 'number', ram: 'number', hdd: 'number', os: 'string', version: 'string' };
const METHOD_KEYS = { config_path: 'string', script: 'string' };
const ALL_METHOD_KEYS = Object.assign({}, RESOURCE_KEYS, METHOD_KEYS);
// Parse install_methods_json from the already-fetched script record
// PocketBase may return JSON fields as already-parsed objects
let methodsArr = [];
try {
const rawMethods = record.install_methods_json;
methodsArr = Array.isArray(rawMethods) ? rawMethods : JSON.parse(rawMethods || '[]');
} catch (e) { methodsArr = []; }
function applyMethodChanges(method, parsed) {
if (!method.resources) method.resources = {};
for (const [k, v] of Object.entries(parsed)) {
if (RESOURCE_KEYS[k]) {
method.resources[k] = RESOURCE_KEYS[k] === 'number' ? parseInt(v, 10) : v;
} else if (METHOD_KEYS[k]) {
method[k] = v === '' ? null : v;
}
}
function formatMethodsList(arr) {
if (arr.length === 0) return '*None*';
return arr.map(function (im, i) {
const r = im.resources || {};
return (i + 1) + '. **`' + (im.type || '?') + '`** — CPU: `' + (r.cpu != null ? r.cpu : '?') +
'` · RAM: `' + (r.ram != null ? r.ram : '?') + ' MB` · HDD: `' + (r.hdd != null ? r.hdd : '?') + ' GB`';
}).join('\n');
}
async function patchMethods(arr) {
async function patchInstallMethodsJson(arr) {
const res = await request(recordsUrl + '/' + record.id, {
method: 'PATCH',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify({ install_methods_json: arr })
body: JSON.stringify({ install_methods_json: JSON.stringify(arr) })
});
if (!res.ok) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: Failed to update install methods:\n```\n' + res.body + '\n```');
await postComment('❌ **PocketBase Bot**: Failed to update `install_methods_json`:\n```\n' + res.body + '\n```');
process.exit(1);
}
}
@@ -541,122 +432,70 @@ jobs:
' **PocketBase Bot**: Install methods for **`' + slug + '`** (' + methodsArr.length + ' total)\n\n' +
formatMethodsList(methodsArr)
);
} else {
// Check for add / remove sub-actions
const addMatch = methodArgs.match(/^add\s+(\S+)(?:\s+(.+))?$/i);
const removeMatch = methodArgs.match(/^remove\s+(\S+)$/i);
if (addMatch) {
// ── METHOD ADD ───────────────────────────────────────────────
const newType = addMatch[1];
if (methodsArr.some(function (im) { return (im.type || '').toLowerCase() === newType.toLowerCase(); })) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: Install method `' + newType + '` already exists for `' + slug + '`.\n\nUse `/pocketbase ' + slug + ' method list` to see all methods.');
process.exit(0);
}
const newMethod = { type: newType, resources: { cpu: 1, ram: 512, hdd: 4, os: 'debian', version: '13' } };
if (addMatch[2]) {
const parsed = parseKVPairs(addMatch[2]);
const unknown = Object.keys(parsed).filter(function (k) { return !ALL_METHOD_KEYS[k]; });
if (unknown.length > 0) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: Unknown method field(s): `' + unknown.join('`, `') + '`\n\n**Allowed:** `' + Object.keys(ALL_METHOD_KEYS).join('`, `') + '`');
process.exit(0);
}
applyMethodChanges(newMethod, parsed);
}
methodsArr.push(newMethod);
await patchMethods(methodsArr);
await revalidate(slug);
await addReaction('+1');
// Parse: <type> cpu=N ram=N hdd=N
const methodParts = methodArgs.match(/^(\S+)\s+(.+)$/);
if (!methodParts) {
await addReaction('-1');
await postComment(
' **PocketBase Bot**: Added install method **`' + newType + '`** to **`' + slug + '`**\n\n' +
formatMethodsList([newMethod]) + '\n\n' +
'*Executed by @' + actor + '*'
);
} else if (removeMatch) {
// ── METHOD REMOVE ────────────────────────────────────────────
const removeType = removeMatch[1].toLowerCase();
const removed = methodsArr.filter(function (im) { return (im.type || '').toLowerCase() === removeType; });
if (removed.length === 0) {
await addReaction('-1');
const available = methodsArr.map(function (im) { return im.type || '?'; });
await postComment('❌ **PocketBase Bot**: No install method `' + removeType + '` found.\n\n**Available:** `' + (available.length ? available.join('`, `') : '(none)') + '`');
process.exit(0);
}
methodsArr = methodsArr.filter(function (im) { return (im.type || '').toLowerCase() !== removeType; });
await patchMethods(methodsArr);
await revalidate(slug);
await addReaction('+1');
await postComment(
'✅ **PocketBase Bot**: Removed install method **`' + removed[0].type + '`** from **`' + slug + '`**\n\n' +
'*Executed by @' + actor + '*'
);
} else {
// ── METHOD EDIT ──────────────────────────────────────────────
const editParts = methodArgs.match(/^(\S+)\s+(.+)$/);
if (!editParts) {
await addReaction('-1');
await postComment(
'❌ **PocketBase Bot**: Invalid `method` syntax.\n\n' +
'**Usage:**\n```\n/pocketbase ' + slug + ' method list\n' +
'/pocketbase ' + slug + ' method <type> cpu=4 ram=2048 hdd=20\n' +
'/pocketbase ' + slug + ' method <type> config_path="/opt/app/.env"\n' +
'/pocketbase ' + slug + ' method add <type> cpu=2 ram=2048 hdd=8\n' +
'/pocketbase ' + slug + ' method remove <type>\n```'
);
process.exit(0);
}
const targetType = editParts[1].toLowerCase();
const parsed = parseKVPairs(editParts[2]);
const unknown = Object.keys(parsed).filter(function (k) { return !ALL_METHOD_KEYS[k]; });
if (unknown.length > 0) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: Unknown method field(s): `' + unknown.join('`, `') + '`\n\n**Allowed:** `' + Object.keys(ALL_METHOD_KEYS).join('`, `') + '`');
process.exit(0);
}
if (Object.keys(parsed).length === 0) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: No valid `key=value` pairs found.\n\n**Allowed:** `' + Object.keys(ALL_METHOD_KEYS).join('`, `') + '`');
process.exit(0);
}
const idx = methodsArr.findIndex(function (im) { return (im.type || '').toLowerCase() === targetType; });
if (idx === -1) {
await addReaction('-1');
const available = methodsArr.map(function (im) { return im.type || '?'; });
await postComment(
'❌ **PocketBase Bot**: No install method `' + targetType + '` found for `' + slug + '`.\n\n' +
'**Available:** `' + (available.length ? available.join('`, `') : '(none)') + '`\n\n' +
'Use `/pocketbase ' + slug + ' method list` to see all methods.'
);
process.exit(0);
}
applyMethodChanges(methodsArr[idx], parsed);
await patchMethods(methodsArr);
await revalidate(slug);
const changesLines = Object.entries(parsed)
.map(function ([k, v]) {
const unit = k === 'ram' ? ' MB' : k === 'hdd' ? ' GB' : '';
return '- `' + k + '` → `' + v + unit + '`';
}).join('\n');
await addReaction('+1');
await postComment(
'✅ **PocketBase Bot**: Updated install method **`' + methodsArr[idx].type + '`** for **`' + slug + '`**\n\n' +
'**Changes applied:**\n' + changesLines + '\n\n' +
'*Executed by @' + actor + '*'
' **PocketBase Bot**: Invalid `method` syntax.\n\n' +
'**Usage:**\n```\n/pocketbase ' + slug + ' method list\n/pocketbase ' + slug + ' method <type> hdd=10\n/pocketbase ' + slug + ' method <type> cpu=4 ram=2048 hdd=20\n```'
);
process.exit(0);
}
const targetType = methodParts[1].toLowerCase();
const resourcesStr = methodParts[2];
// Parse resource fields (only cpu/ram/hdd allowed)
const RESOURCE_FIELDS = { cpu: true, ram: true, hdd: true };
const resourceChanges = {};
const rePairs = /([a-z]+)=(\d+)/gi;
let m;
while ((m = rePairs.exec(resourcesStr)) !== null) {
const key = m[1].toLowerCase();
if (RESOURCE_FIELDS[key]) resourceChanges[key] = parseInt(m[2], 10);
}
if (Object.keys(resourceChanges).length === 0) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: No valid resource fields found. Use `cpu=N`, `ram=N`, `hdd=N`.');
process.exit(0);
}
// Find matching method by type name (case-insensitive)
const idx = methodsArr.findIndex(function (im) {
return (im.type || '').toLowerCase() === targetType;
});
if (idx === -1) {
await addReaction('-1');
const availableTypes = methodsArr.map(function (im) { return im.type || '?'; });
await postComment(
'❌ **PocketBase Bot**: No install method with type `' + targetType + '` found for `' + slug + '`.\n\n' +
'**Available types:** `' + (availableTypes.length ? availableTypes.join('`, `') : '(none)') + '`\n\n' +
'Use `/pocketbase ' + slug + ' method list` to see all methods.'
);
process.exit(0);
}
if (!methodsArr[idx].resources) methodsArr[idx].resources = {};
if (resourceChanges.cpu != null) methodsArr[idx].resources.cpu = resourceChanges.cpu;
if (resourceChanges.ram != null) methodsArr[idx].resources.ram = resourceChanges.ram;
if (resourceChanges.hdd != null) methodsArr[idx].resources.hdd = resourceChanges.hdd;
await patchInstallMethodsJson(methodsArr);
const changesLines = Object.entries(resourceChanges)
.map(function ([k, v]) { return '- `' + k + '` → `' + v + (k === 'ram' ? ' MB' : k === 'hdd' ? ' GB' : '') + '`'; })
.join('\n');
await addReaction('+1');
await postComment(
'✅ **PocketBase Bot**: Updated install method **`' + methodsArr[idx].type + '`** for **`' + slug + '`**\n\n' +
'**Changes applied:**\n' + changesLines + '\n\n' +
'*Executed by @' + actor + '*'
);
}
} else if (setMatch) {
// ── SET SUBCOMMAND (value from code block) ───────────────────────
// ── SET SUBCOMMAND (multi-line / HTML / special chars via code block) ──
const fieldName = setMatch[1].toLowerCase();
const SET_ALLOWED = {
name: 'string', description: 'string', logo: 'string',
@@ -692,7 +531,6 @@ jobs:
await postComment('❌ **PocketBase Bot**: PATCH failed for `' + slug + '`:\n```\n' + setPatchRes.body + '\n```');
process.exit(1);
}
await revalidate(slug);
const preview = codeBlockValue.length > 300 ? codeBlockValue.substring(0, 300) + '…' : codeBlockValue;
await addReaction('+1');
await postComment(
@@ -703,6 +541,11 @@ jobs:
} else {
// ── FIELD=VALUE PATH ─────────────────────────────────────────────
const fieldsStr = rest;
// Skipped: slug, script_created/updated, created (auto), categories/
// install_methods/notes/type (relations), github_data/install_methods_json/
// notes_json (auto-generated), execute_in (select relation), last_update_commit (auto)
const ALLOWED_FIELDS = {
name: 'string',
description: 'string',
@@ -725,7 +568,39 @@ jobs:
deleted_message: 'string',
};
const parsedFields = parseKVPairs(rest);
// Field=value parser (handles quoted values and empty=null)
function parseFields(str) {
const fields = {};
let pos = 0;
while (pos < str.length) {
while (pos < str.length && /\s/.test(str[pos])) pos++;
if (pos >= str.length) break;
let keyStart = pos;
while (pos < str.length && str[pos] !== '=' && !/\s/.test(str[pos])) pos++;
const key = str.substring(keyStart, pos).trim();
if (!key || pos >= str.length || str[pos] !== '=') { pos++; continue; }
pos++;
let value;
if (str[pos] === '"') {
pos++;
let valStart = pos;
while (pos < str.length && str[pos] !== '"') {
if (str[pos] === '\\') pos++;
pos++;
}
value = str.substring(valStart, pos).replace(/\\"/g, '"');
if (pos < str.length) pos++;
} else {
let valStart = pos;
while (pos < str.length && !/\s/.test(str[pos])) pos++;
value = str.substring(valStart, pos);
}
fields[key] = value;
}
return fields;
}
const parsedFields = parseFields(fieldsStr);
const unknownFields = Object.keys(parsedFields).filter(function (f) { return !ALLOWED_FIELDS[f]; });
if (unknownFields.length > 0) {
@@ -780,7 +655,6 @@ jobs:
await postComment('❌ **PocketBase Bot**: PATCH failed for `' + slug + '`:\n```\n' + patchRes.body + '\n```');
process.exit(1);
}
await revalidate(slug);
await addReaction('+1');
const changesLines = Object.entries(payload)
.map(function ([k, v]) { return '- `' + k + '` → `' + JSON.stringify(v) + '`'; })

View File

@@ -170,6 +170,7 @@ jobs:
website: data.website,
logo: data.logo,
description: data.description,
config_path: data.config_path,
default_user: (data.default_credentials && data.default_credentials.username) || data.default_user || null,
default_passwd: (data.default_credentials && data.default_credentials.password) || data.default_passwd || null,
is_dev: false

43
.gitignore vendored
View File

@@ -2,14 +2,32 @@
.DS_Store
Thumbs.db
# Editor & IDE files
# Editor & IDE files (keeping .vscode settings but ignoring unnecessary metadata)
!.vscode/
.vscode/*.workspace
.vscode/*.tmp
# Log files
# Log and Cache files
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Python-specific exclusions
__pycache__/
*.pyc
*.pyo
*.pyd
*.venv/
venv/
env/
*.env
# API and Backend specific exclusions
api/.env
api/__pycache__/
api/*.sqlite3
# Install scripts and temporary files
install/tmp/
@@ -23,7 +41,7 @@ vm/*.vmdk
vm/*.iso
vm/*.bak
# Miscellaneous temporary files
# Miscellaneous temporary or unnecessary files
*.bak
*.swp
*.swo
@@ -31,7 +49,22 @@ vm/*.bak
*.tmp
*.backup
# JSON temporary files
json/
# JSON configuration backups
json/*.bak
json/*.tmp
json/.vscode/
# Ignore compiled binaries or packaged artifacts
*.exe
*.dll
*.bin
*.deb
*.rpm
*.tar.gz
*.zip
*.tgz
# Ignore repository metadata or Git itself
.git/
.gitignore
.vscode/settings.json

16
.vscode/.editorconfig generated vendored Normal file
View File

@@ -0,0 +1,16 @@
; editorconfig.org
root = true
[*]
charset = utf-8
continuation_indent_size = 2
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
max_line_length = 120
tab_width = 2
; trim_trailing_whitespace = true ; disabled until files are cleaned up
[*.md]
trim_trailing_whitespace = false

View File

View File

@@ -442,48 +442,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details>
## 2026-04-15
### 🆕 New Scripts
- GitHub-Runner ([#13709](https://github.com/community-scripts/ProxmoxVE/pull/13709))
- Revert "Remove low-install-count CT scripts and installers (#13570)" [@CrazyWolf13](https://github.com/CrazyWolf13) ([#13752](https://github.com/community-scripts/ProxmoxVE/pull/13752))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Domain Monitor: Fix file ownership after update [@tremor021](https://github.com/tremor021) ([#13759](https://github.com/community-scripts/ProxmoxVE/pull/13759))
- #### 💥 Breaking Changes
- Reitti: refactor scripts for v4 - remove RabbitMQ and Photon [@MickLesk](https://github.com/MickLesk) ([#13728](https://github.com/community-scripts/ProxmoxVE/pull/13728))
### 📚 Documentation
- cleanup: remove docs/, update README & CONTRIBUTING, fix repo config [@MickLesk](https://github.com/MickLesk) ([#13770](https://github.com/community-scripts/ProxmoxVE/pull/13770))
## 2026-04-14
### 🚀 Updated Scripts
- Immich: Pin photo-processing library revisions [@vhsdream](https://github.com/vhsdream) ([#13748](https://github.com/community-scripts/ProxmoxVE/pull/13748))
- #### 🐞 Bug Fixes
- BentoPDF: Nginx fixes [@tremor021](https://github.com/tremor021) ([#13741](https://github.com/community-scripts/ProxmoxVE/pull/13741))
- Zerobyte: add git to dependencies to fix bun install failure [@Copilot](https://github.com/Copilot) ([#13721](https://github.com/community-scripts/ProxmoxVE/pull/13721))
- alpine-nextcloud-install: do not use deprecated nginx config [@AlexanderStein](https://github.com/AlexanderStein) ([#13726](https://github.com/community-scripts/ProxmoxVE/pull/13726))
- #### ✨ New Features
- Mealie: support v3.15+ Nuxt 4 migration [@MickLesk](https://github.com/MickLesk) ([#13731](https://github.com/community-scripts/ProxmoxVE/pull/13731))
- #### 🔧 Refactor
- Lyrion: correct service name and version file in update script [@MickLesk](https://github.com/MickLesk) ([#13734](https://github.com/community-scripts/ProxmoxVE/pull/13734))
- Changedetection: move env vars from service file to .env [@tremor021](https://github.com/tremor021) ([#13732](https://github.com/community-scripts/ProxmoxVE/pull/13732))
## 2026-04-13
### 🚀 Updated Scripts

View File

@@ -1,137 +0,0 @@
# Contributing to Proxmox VE Helper-Scripts
Welcome! We're glad you want to contribute. This guide covers everything you need to add new scripts, improve existing ones, or help in other ways.
For detailed coding standards and full documentation, visit **[community-scripts.org/docs](https://community-scripts.org/docs)**.
---
## How Can I Help?
> [!IMPORTANT]
> **New scripts** must always be submitted to [ProxmoxVED](https://github.com/community-scripts/ProxmoxVED) first — not to this repository.
> PRs with new scripts opened directly against ProxmoxVE **will be closed without review**.
> **Bug fixes, improvements, and features for existing scripts** go here (ProxmoxVE).
| I want to… | Where to go |
| :------------------------------------------ | :------------------------------------------------------------------------------------------- |
| **Add a brand-new script** | [ProxmoxVED](https://github.com/community-scripts/ProxmoxVED) — testing repo for new scripts |
| **Fix a bug or improve an existing script** | This repo (ProxmoxVE) — open a PR here |
| **Add a feature to an existing script** | This repo (ProxmoxVE) — open a PR here |
| Report a bug or broken script | [Open an Issue](https://github.com/community-scripts/ProxmoxVE/issues) |
| Request a new script or feature | [Start a Discussion](https://github.com/community-scripts/ProxmoxVE/discussions) |
| Report a security vulnerability | [Security Policy](SECURITY.md) |
| Chat with contributors | [Discord](https://discord.gg/3AnUqsXnmK) |
---
## Prerequisites
Before writing scripts, we recommend setting up:
- **Visual Studio Code** with these extensions:
- [Shell Syntax](https://marketplace.visualstudio.com/items?itemName=bmalehorn.shell-syntax)
- [ShellCheck](https://marketplace.visualstudio.com/items?itemName=timonwong.shellcheck)
- [Shell Format](https://marketplace.visualstudio.com/items?itemName=foxundermoon.shell-format)
---
## Script Structure
Every script consists of two files:
| File | Purpose |
| :--------------------------- | :------------------------------------------------------ |
| `ct/AppName.sh` | Container creation, variable setup, and update handling |
| `install/AppName-install.sh` | Application installation logic |
Use existing scripts in [`ct/`](ct/) and [`install/`](install/) as reference. Full coding standards and annotated templates are at **[community-scripts.org/docs/contribution](https://community-scripts.org/docs/contribution)**.
---
## Contribution Process
### Adding a new script
New scripts are **not accepted directly in this repository**. The workflow is:
1. Fork [ProxmoxVED](https://github.com/community-scripts/ProxmoxVED) and clone it
2. Create a branch: `git switch -c feat/myapp`
3. Write your two script files:
- `ct/myapp.sh`
- `install/myapp-install.sh`
4. Test thoroughly in ProxmoxVED — run the script against a real Proxmox instance
5. Open a PR in **ProxmoxVED** for review and testing
6. Once accepted and verified there, the script will be promoted to ProxmoxVE by maintainers
Follow the coding standards at [community-scripts.org/docs/contribution](https://community-scripts.org/docs/contribution).
---
### Fixing a bug or improving an existing script
Changes to scripts that already exist in ProxmoxVE go directly here:
1. Fork **this repository** (ProxmoxVE) and clone it:
```bash
git clone https://github.com/YOUR_USERNAME/ProxmoxVE
cd ProxmoxVE
```
2. Create a branch:
```bash
git switch -c fix/myapp-description
```
3. Make your changes to the relevant files in `ct/` and/or `install/`
4. Open a PR from your fork to `community-scripts/ProxmoxVE/main`
Your PR should only contain the files you changed. Do not include unrelated modifications.
---
## Code Standards
Key rules at a glance:
- One script per service — keep them focused
- Naming convention: lowercase, hyphen-separated (`my-app.sh`)
- Shebang: `#!/usr/bin/env bash`
- Quote all variables: `"$VAR"` not `$VAR`
- Use lowercase variable names
- Do not hardcode credentials or sensitive values
Full standards and examples: **[community-scripts.org/docs/contribution](https://community-scripts.org/docs/contribution)**
---
## Developer Mode & Debugging
Set the `dev_mode` variable to enable debugging features when testing. Flags can be combined (comma-separated):
```bash
dev_mode="trace,keep" bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/myapp.sh)"
```
| Flag | Description |
| :----------- | :----------------------------------------------------------- |
| `trace` | Enables `set -x` for maximum verbosity during execution |
| `keep` | Prevents the container from being deleted if the build fails |
| `pause` | Pauses execution at key points before customization |
| `breakpoint` | Drops to a shell at hardcoded `breakpoint` calls in scripts |
| `logs` | Saves detailed build logs to `/var/log/community-scripts/` |
| `dryrun` | Bypasses actual container creation (limited support) |
| `motd` | Forces an update of the Message of the Day |
---
## Notes
- **Website metadata** (name, description, logo, tags) is managed via the website — use the "Report Issue" link on any script page to request changes. Do not submit metadata changes via repo files.
- **JSON files** in `json/` define script properties used by the website. See existing files for structure reference.
- Keep PRs small and focused. One fix or feature per PR is ideal.
- PRs with **new scripts** opened against ProxmoxVE will be closed — submit them to [ProxmoxVED](https://github.com/community-scripts/ProxmoxVED) instead.
- PRs that fail CI checks will not be merged.

400
README.md
View File

@@ -1,209 +1,283 @@
<div align="center">
<img src="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png" height="112px" alt="Proxmox VE Helper-Scripts Logo" />
<img src="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png" height="120px" alt="Proxmox VE Helper-Scripts Logo" />
<h1>Proxmox VE Helper-Scripts</h1>
<p><strong>One-command installations for services, containers, and VMs on Proxmox VE</strong><br/>
A community project — built on the foundation of <a href="https://github.com/tteck">@tteck</a>'s original work</p>
<p><em>A Community Legacy in Memory of @tteck</em></p>
<p>
<a href="https://community-scripts.org"><img src="https://img.shields.io/badge/Website-community--scripts.org-4c9b3f?style=flat-square" /></a>
<a href="https://discord.gg/3AnUqsXnmK"><img src="https://img.shields.io/badge/Discord-Join_us-7289da?style=flat-square&logo=discord&logoColor=white" /></a>
<a href="https://github.com/community-scripts/ProxmoxVE/stargazers"><img src="https://img.shields.io/github/stars/community-scripts/ProxmoxVE?style=flat-square&label=Stars&color=f5a623" /></a>
<a href="https://github.com/community-scripts/ProxmoxVE/blob/main/CHANGELOG.md"><img src="https://img.shields.io/badge/Changelog-view-6c5ce7?style=flat-square" /></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue?style=flat-square" /></a>
<a href="https://community-scripts.org">
<img src="https://img.shields.io/badge/🌐_Website-Visit-4c9b3f?style=for-the-badge&labelColor=2d3748" alt="Website" />
</a>
<a href="https://discord.gg/3AnUqsXnmK">
<img src="https://img.shields.io/badge/💬_Discord-Join-7289da?style=for-the-badge&labelColor=2d3748" alt="Discord" />
</a>
<a href="https://ko-fi.com/community_scripts">
<img src="https://img.shields.io/badge/❤_Support-Donate-FF5F5F?style=for-the-badge&labelColor=2d3748" alt="Donate" />
</a>
</p>
<p>
<a href="https://github.com/community-scripts/ProxmoxVE/blob/main/docs/contribution/README.md">
<img src="https://img.shields.io/badge/🤝_Contribute-Guidelines-ff4785?style=for-the-badge&labelColor=2d3748" alt="Contribute" />
</a>
<a href="https://github.com/community-scripts/ProxmoxVE/blob/main/docs/contribution/USER_SUBMITTED_GUIDES.md">
<img src="https://img.shields.io/badge/📚_Guides-Read-0077b5?style=for-the-badge&labelColor=2d3748" alt="Guides" />
</a>
<a href="https://github.com/community-scripts/ProxmoxVE/blob/main/CHANGELOG.md">
<img src="https://img.shields.io/badge/📋_Changelog-View-6c5ce7?style=for-the-badge&labelColor=2d3748" alt="Changelog" />
</a>
</p>
<br />
**Simplify your Proxmox VE setup with community-driven automation scripts**
Originally created by tteck, now maintained and expanded by the community
</div>
<br />
<div align="center">
<sub>🙌 <strong>Shoutout to</strong></sub>
<br />
<br />
<a href="https://selfh.st/">
<img src="https://img.shields.io/badge/selfh.st-Icons_for_Self--Hosted-2563eb?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTIgMkM2LjQ4IDIgMiA2LjQ4IDIgMTJzNC40OCAxMCAxMCAxMCAxMC00LjQ4IDEwLTEwUzE3LjUyIDIgMTIgMnptMCAxOGMtNC40MSAwLTgtMy41OS04LThzMy41OS04IDgtOCA4IDMuNTkgOCA4LTMuNTkgOC04IDh6IiBmaWxsPSJ3aGl0ZSIvPjwvc3ZnPg==&labelColor=1e3a8a" alt="selfh.st Icons" />
</a>
<br />
<sub><a href="https://github.com/selfhst/icons">View on GitHub</a> • Consistent, beautiful icons for 5000+ self-hosted apps</sub>
</div>
---
## What is this?
## 🎯 Key Features
**Simplify your Proxmox VE setup with community-driven automation scripts.**
<div align="center">
Install and configure popular self-hosted services with a single command — no manual package hunting, no config file archaeology. Paste a command into your Proxmox shell, answer a few prompts, and your container or VM is up and running.
The collection covers hundreds of services across categories like home automation, media servers, networking tools, databases, monitoring stacks, and more.
---
## Requirements
| Component | Details |
| -------------- | ------------------------------------------------ |
| **Proxmox VE** | Version 8.4, 9.0, or 9.1 |
| **Host OS** | Proxmox VE (Debian-based) |
| **Access** | Root shell access on the Proxmox host |
| **Network** | Internet connection required during installation |
---
## Getting Started
The fastest way to find and run scripts:
1. Go to **[community-scripts.org](https://community-scripts.org)**
2. Search for the service you want (e.g. "Home Assistant", "Nginx Proxy Manager", "Jellyfin")
3. Copy the one-line install command from the script page
4. Open your **Proxmox Shell** and paste it
5. Choose between **Default** or **Advanced** setup and follow the prompts
Each script page documents what the container includes, default resource allocation, and post-install notes.
---
## How Scripts Work
Every script follows the same pattern:
**Default mode** — Picks sensible resource defaults (CPU, RAM, storage) and asks only the minimum required questions. Most installs finish in under five minutes.
**Advanced mode** — Gives you full control over container settings, networking, storage backends, and application-level configuration before anything is installed.
After installation, each container ships with a **post-install helper** accessible from the Proxmox shell. It handles common tasks like:
- Applying updates to the installed service
- Changing application settings without manually editing config files
- Basic troubleshooting and log access
---
## What's Included
The repository covers a wide range of categories. A few examples:
| Category | Examples |
| --------------- | --------------------------------------------------- |
| Home Automation | Home Assistant, Zigbee2MQTT, ESPHome, Node-RED |
| Media | Jellyfin, Plex, Radarr, Sonarr, Immich |
| Networking | AdGuard Home, Nginx Proxy Manager, Pi-hole, Traefik |
| Monitoring | Grafana, Prometheus, Uptime Kuma, Netdata |
| Databases | PostgreSQL, MariaDB, Redis, InfluxDB |
| Security | Vaultwarden, CrowdSec, Authentik |
| Dev & Tools | Gitea, Portainer, VS Code Server, n8n |
> Browse the full list at **[community-scripts.org/categories](https://community-scripts.org/categories)** — new scripts are added regularly.
---
## Contributing
This project runs on community contributions. Whether you want to write new scripts, improve existing ones, or just report a bug — every bit helps.
### Where to start
| I want to… | Go here |
| ------------------------------------- | ------------------------------------------------------------------------------------------------- |
| Add a **new** script | [ProxmoxVED](https://github.com/community-scripts/ProxmoxVED) — new scripts are tested here first |
| Fix or improve an **existing** script | [Contributing Guidelines](CONTRIBUTING.md) — open a PR in this repo |
| Report a bug or broken script | [Issues](https://github.com/community-scripts/ProxmoxVE/issues) |
| Request a new script or feature | [Discussions](https://github.com/community-scripts/ProxmoxVE/discussions) |
| Report a security vulnerability | [Security Policy](SECURITY.md) |
| Get help or chat with other users | [Discord](https://discord.gg/3AnUqsXnmK) |
### Before you open a PR
- **New scripts go to [ProxmoxVED](https://github.com/community-scripts/ProxmoxVED), not here.** PRs with new scripts opened directly against this repo will be closed.
- Bug fixes and improvements to existing scripts belong in this repo — read the [Contributing Guidelines](CONTRIBUTING.md) first.
- Keep PRs focused. One fix or feature per PR.
- Document what your script installs and any non-obvious decisions in the corresponding JSON metadata file.
---
## Core Team
<table align="center">
<table>
<tr>
<td align="center">
<a href="https://github.com/MickLesk">
<img src="https://github.com/MickLesk.png" width="80" height="80" style="border-radius:50%" alt="MickLesk" /><br/>
<sub><b>MickLesk</b></sub>
<td align="center" width="25%">
<h3>⚡ Quick Setup</h3>
<p>One-command installations for popular services and containers</p>
</td>
<td align="center" width="25%">
<h3>⚙️ Flexible Config</h3>
<p>Simple mode for beginners, advanced options for power users</p>
</td>
<td align="center" width="25%">
<h3>🔄 Auto Updates</h3>
<p>Keep your installations current with built-in update mechanisms</p>
</td>
<td align="center" width="25%">
<h3>🛠️ Easy Management</h3>
<p>Post-install scripts for configuration and troubleshooting</p>
</td>
</tr>
<tr>
<td align="center" width="25%">
<h3>👥 Community Driven</h3>
<p>Actively maintained with contributions from users worldwide</p>
</td>
<td align="center" width="25%">
<h3>📖 Well Documented</h3>
<p>Comprehensive guides and community support</p>
</td>
<td align="center" width="25%">
<h3>🔒 Secure</h3>
<p>Regular security updates and best practices</p>
</td>
<td align="center" width="25%">
<h3>⚡ Performance</h3>
<p>Optimized configurations for best performance</p>
</td>
</tr>
</table>
</div>
---
## 📋 Requirements
<div align="center">
<table>
<tr>
<td align="center" width="33%">
<h3>🖥️ Proxmox VE</h3>
<p>Version: 8.4.x | 9.0.x | 9.1.x</p>
</td>
<td align="center" width="33%">
<h3>🐧 Operating System</h3>
<p>Debian-based with Proxmox Tools</p>
</td>
<td align="center" width="33%">
<h3>🌐 Network</h3>
<p>Internet connection required</p>
</td>
</tr>
</table>
</div>
---
## 📥 Getting Started
Choose your preferred installation method:
### Method 1: One-Click Web Installer
The fastest way to get started:
1. Visit **[community-scripts.org](https://community-scripts.org/)** 🌐
2. Search for your desired script (e.g., "Home Assistant", "Docker")
3. Copy the bash command displayed on the script page
4. Open your **Proxmox Shell** and paste the command
5. Press Enter and follow the interactive prompts
### Method 2: PVEScripts-Local
Install a convenient script manager directly in your Proxmox UI:
```bash
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/pve-scripts-local.sh)"
```
This adds a menu to your Proxmox interface for easy script access without visiting the website.
📖 **Learn more:** [ProxmoxVE-Local Repository](https://github.com/community-scripts/ProxmoxVE-Local)
---
## 💬 Join the Community
<div align="center">
<table>
<tr>
<td align="center" width="33%">
<h3>💬 Discord</h3>
<p>Real-time chat, support, and discussions</p>
<a href="https://discord.gg/3AnUqsXnmK">
<img src="https://img.shields.io/badge/Join-7289da?style=for-the-badge&logo=discord&logoColor=white" alt="Discord" />
</a>
</td>
<td align="center">
<a href="https://github.com/michelroegl-brunner">
<img src="https://github.com/michelroegl-brunner.png" width="80" height="80" style="border-radius:50%" alt="michelroegl-brunner" /><br/>
<sub><b>michelroegl-brunner</b></sub>
<td align="center" width="33%">
<h3>💭 Discussions</h3>
<p>Feature requests, Q&A, and ideas</p>
<a href="https://github.com/community-scripts/ProxmoxVE/discussions">
<img src="https://img.shields.io/badge/Discuss-238636?style=for-the-badge&logo=github&logoColor=white" alt="Discussions" />
</a>
</td>
<td align="center">
<a href="https://github.com/BramSuurdje">
<img src="https://github.com/BramSuurdje.png" width="80" height="80" style="border-radius:50%" alt="BramSuurdje" /><br/>
<sub><b>BramSuurdje</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/CrazyWolf13">
<img src="https://github.com/CrazyWolf13.png" width="80" height="80" style="border-radius:50%" alt="CrazyWolf13" /><br/>
<sub><b>CrazyWolf13</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/tremor021">
<img src="https://github.com/tremor021.png" width="80" height="80" style="border-radius:50%" alt="tremor021" /><br/>
<sub><b>tremor021</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/vhsdream">
<img src="https://github.com/vhsdream.png" width="80" height="80" style="border-radius:50%" alt="vhsdream" /><br/>
<sub><b>vhsdream</b></sub>
<td align="center" width="33%">
<h3>🐛 Issues</h3>
<p>Bug reports and issue tracking</p>
<a href="https://github.com/community-scripts/ProxmoxVE/issues">
<img src="https://img.shields.io/badge/Report-d73a4a?style=for-the-badge&logo=github&logoColor=white" alt="Issues" />
</a>
</td>
</tr>
</table>
</div>
---
## Project Activity
## 🛠️ Contribute
<div align="center">
<table>
<tr>
<td align="center" width="25%">
<h3>💻 Code</h3>
<p>Add new scripts or improve existing ones</p>
</td>
<td align="center" width="25%">
<h3>📝 Documentation</h3>
<p>Write guides, improve READMEs, translate content</p>
</td>
<td align="center" width="25%">
<h3>🧪 Testing</h3>
<p>Test scripts and report compatibility issues</p>
</td>
<td align="center" width="25%">
<h3>💡 Ideas</h3>
<p>Suggest features or workflow improvements</p>
</td>
</tr>
</table>
</div>
<div align="center">
<br />
👉 Check our **[Contributing Guidelines](https://github.com/community-scripts/ProxmoxVE/blob/main/docs/contribution/README.md)** to get started
</div>
---
## ❤️ Support the Project
This project is maintained by volunteers in memory of tteck. Your support helps us maintain infrastructure, improve documentation, and give back to important causes.
**🎗️ 30% of all donations go directly to cancer research and hospice care**
<div align="center">
<a href="https://ko-fi.com/community_scripts">
<img src="https://img.shields.io/badge/☕_Buy_us_a_coffee-Support_on_Ko--fi-FF5F5F?style=for-the-badge&labelColor=2d3748" alt="Support on Ko-fi" />
</a>
<br />
<sub>Every contribution helps keep this project alive and supports meaningful causes</sub>
</div>
---
## 📈 Project Statistics
<p align="center">
<img
src="https://repobeats.axiom.co/api/embed/57edde03e00f88d739bdb5b844ff7d07dd079375.svg"
alt="Repository activity"
width="700"
alt="Repobeats analytics"
width="650"
/>
</p>
<p align="center">
<a href="https://star-history.com/#community-scripts/ProxmoxVE&Date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date" width="700" />
<source
media="(prefers-color-scheme: dark)"
srcset="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date&theme=dark"
/>
<source
media="(prefers-color-scheme: light)"
srcset="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date"
/>
<img
alt="Star History Chart"
src="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date"
width="650"
/>
</picture>
</a>
</p>
---
## Support the Project
## 📜 License
This project is maintained by volunteers. All infrastructure costs come out of pocket, and the work is done in people's spare time.
**30% of all donations are forwarded directly to cancer research and hospice care** — a cause that was important to tteck.
<div align="center">
<a href="https://ko-fi.com/community_scripts">
<img src="https://img.shields.io/badge/Support_on_Ko--fi-FF5F5F?style=for-the-badge&logo=ko-fi&logoColor=white" alt="Support on Ko-fi" />
</a>
&nbsp;
<a href="https://community-scripts.org/donate">
<img src="https://img.shields.io/badge/Donate-community--scripts.org%2Fdonate-4c9b3f?style=for-the-badge" alt="Donate via community-scripts.org" />
</a>
</div>
---
## License
This project is licensed under the [MIT License](LICENSE) — free to use, modify, and redistribute for personal and commercial purposes.
See the full license text in [LICENSE](LICENSE).
This project is licensed under the **[MIT License](LICENSE)** - feel free to use, modify, and distribute.
---
<div align="center">
<sub>Built on the foundation of <a href="https://github.com/tteck">tteck</a>'s original work · <a href="https://github.com/tteck/Proxmox">Original Repository</a></sub><br/>
<sub>Maintained and expanded by the community · In memory of tteck</sub><br/>
<sub>Made with ❤️ by the Proxmox community in memory of tteck</sub>
<br />
<sub><i>Proxmox® is a registered trademark of <a href="https://www.proxmox.com/en/about/company">Proxmox Server Solutions GmbH</a></i></sub>
</div>

View File

@@ -1,43 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://cassandra.apache.org/_/index.html
APP="Apache-Cassandra"
var_tags="${var_tags:-database;NoSQL}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/init.d/cassandra ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating Apache Cassandra"
$STD apt update
$STD apt install -y --only-upgrade cassandra cassandra-tools
msg_ok "Updated Apache Cassandra"
msg_ok "Updated successfully!"
exit
}
start
build_container
description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"

View File

@@ -1,52 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://release-argus.io/ | Github: https://github.com/release-argus/Argus
APP="Argus"
var_tags="${var_tags:-watcher}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-3}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/argus ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "argus" "release-argus/Argus"; then
msg_info "Stopping service"
systemctl stop argus
msg_ok "Service stopped"
fetch_and_deploy_gh_release "Argus" "release-argus/Argus" "singlefile" "latest" "/opt/argus" "Argus*linux-amd64"
msg_info "Starting service"
systemctl start argus
msg_ok "Service started"
msg_ok "Updated successfully!"
fi
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"

View File

@@ -1,68 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.commafeed.com/#/welcome | Github: https://github.com/Athou/commafeed
APP="CommaFeed"
var_tags="${var_tags:-rss-reader}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/commafeed ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
JAVA_VERSION="25" setup_java
if check_for_gh_release "commafeed" "Athou/commafeed"; then
msg_info "Stopping Service"
systemctl stop commafeed
msg_ok "Stopped Service"
ensure_dependencies rsync
if [ -d /opt/commafeed/data ] && [ "$(ls -A /opt/commafeed/data)" ]; then
msg_info "Backing up existing data"
mv /opt/commafeed/data /opt/data.bak
msg_ok "Backed up existing data"
fi
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "commafeed" "Athou/commafeed" "prebuild" "latest" "/opt/commafeed" "commafeed-*-h2-jvm.zip"
if [ -d /opt/data.bak ] && [ "$(ls -A /opt/data.bak)" ]; then
msg_info "Restoring data"
mv /opt/data.bak /opt/commafeed/data
msg_ok "Restored data"
fi
msg_info "Starting Service"
systemctl start commafeed
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8082${CL}"

View File

@@ -34,7 +34,7 @@ function update_script() {
fi
if ! grep -Fq "www-data /usr/bin/php /opt/domain-monitor/cron/check_domains.php" /etc/crontab; then
echo "0 0 * * * www-data /usr/bin/php /opt/domain-monitor/cron/check_domains.php" >>/etc/crontab
echo "0 0 * * * www-data /usr/bin/php /opt/domain-monitor/cron/check_domains.php" >> /etc/crontab
fi
if check_for_gh_release "domain-monitor" "Hosteroid/domain-monitor"; then
@@ -52,7 +52,6 @@ function update_script() {
msg_info "Updating Domain Monitor"
cd /opt/domain-monitor
$STD composer install
chown -R www-data:www-data /opt/domain-monitor
msg_ok "Updated Domain Monitor"
msg_info "Restoring backup"

View File

@@ -1,71 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/actions/runner
APP="GitHub-Runner"
var_tags="${var_tags:-ci}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
var_nesting="${var_nesting:-1}"
var_keyctl="${var_keyctl:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /opt/actions-runner/run.sh ]]; then
msg_error "No ${APP} Installation Found!"
exit 1
fi
if check_for_gh_release "actions-runner" "actions/runner"; then
msg_info "Stopping Service"
systemctl stop actions-runner
msg_ok "Stopped Service"
msg_info "Backing up runner configuration"
BACKUP_DIR="/opt/actions-runner.backup"
mkdir -p "$BACKUP_DIR"
for f in .runner .credentials .credentials_rsaparams .env .path; do
[[ -f /opt/actions-runner/$f ]] && cp -a /opt/actions-runner/$f "$BACKUP_DIR/"
done
msg_ok "Backed up configuration"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "actions-runner" "actions/runner" "prebuild" "latest" "/opt/actions-runner" "actions-runner-linux-x64-*.tar.gz"
msg_info "Restoring runner configuration"
for f in .runner .credentials .credentials_rsaparams .env .path; do
[[ -f "$BACKUP_DIR/$f" ]] && cp -a "$BACKUP_DIR/$f" /opt/actions-runner/
done
rm -rf "$BACKUP_DIR"
msg_ok "Restored configuration"
msg_info "Starting Service"
systemctl start actions-runner
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
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} After first boot, run config.sh with your token and start the service.${CL}"

View File

@@ -1,44 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Giovanni Pellerano (evilaliv3)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/globaleaks/globaleaks-whistleblowing-software
APP="GlobaLeaks"
var_tags="${var_tags:-whistleblowing-software}"
var_disk="${var_disk:-4}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /usr/sbin/globaleaks ]]; then
msg_error "No ${APP} installation found!"
exit
fi
msg_info "Updating $APP LXC"
$STD apt update
$STD apt -y upgrade
msg_ok "Updated $APP LXC"
msg_ok "Updated successfully!"
}
start
build_container
description
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}https://${IP}${CL}"

View File

@@ -1,6 +0,0 @@
___ __ ______ __
/ | ____ ____ ______/ /_ ___ / ____/___ _______________ _____ ____/ /________ _
/ /| | / __ \/ __ `/ ___/ __ \/ _ \______/ / / __ `/ ___/ ___/ __ `/ __ \/ __ / ___/ __ `/
/ ___ |/ /_/ / /_/ / /__/ / / / __/_____/ /___/ /_/ (__ |__ ) /_/ / / / / /_/ / / / /_/ /
/_/ |_/ .___/\__,_/\___/_/ /_/\___/ \____/\__,_/____/____/\__,_/_/ /_/\__,_/_/ \__,_/
/_/

View File

@@ -1,6 +0,0 @@
___
/ | _________ ___ _______
/ /| | / ___/ __ `/ / / / ___/
/ ___ |/ / / /_/ / /_/ (__ )
/_/ |_/_/ \__, /\__,_/____/
/____/

View File

@@ -1,6 +0,0 @@
______ ______ __
/ ____/___ ____ ___ ____ ___ ____ _/ ____/__ ___ ____/ /
/ / / __ \/ __ `__ \/ __ `__ \/ __ `/ /_ / _ \/ _ \/ __ /
/ /___/ /_/ / / / / / / / / / / / /_/ / __/ / __/ __/ /_/ /
\____/\____/_/ /_/ /_/_/ /_/ /_/\__,_/_/ \___/\___/\__,_/

View File

@@ -1,6 +0,0 @@
_______ __ __ __ __ ____
/ ____(_) /_/ / / /_ __/ /_ / __ \__ ______ ____ ___ _____
/ / __/ / __/ /_/ / / / / __ \______/ /_/ / / / / __ \/ __ \/ _ \/ ___/
/ /_/ / / /_/ __ / /_/ / /_/ /_____/ _, _/ /_/ / / / / / / / __/ /
\____/_/\__/_/ /_/\__,_/_.___/ /_/ |_|\__,_/_/ /_/_/ /_/\___/_/

View File

@@ -1,6 +0,0 @@
________ __ __ __
/ ____/ /___ / /_ ____ _/ / ___ ____ _/ /_______
/ / __/ / __ \/ __ \/ __ `/ / / _ \/ __ `/ //_/ ___/
/ /_/ / / /_/ / /_/ / /_/ / /___/ __/ /_/ / ,< (__ )
\____/_/\____/_.___/\__,_/_____/\___/\__,_/_/|_/____/

View File

@@ -1,6 +0,0 @@
__ ___ __ _______
/ / / (_) _____ / |/ / __ \
/ /_/ / / | / / _ \/ /|_/ / / / /
/ __ / /| |/ / __/ / / / /_/ /
/_/ /_/_/ |___/\___/_/ /_/\___\_\

View File

@@ -1,6 +0,0 @@
____ ________ ______ __
/ _/___ _________ / _/ __ \/ ____/___/ /
/ // __ \/ ___/ __ \ / // /_/ / / / __ /
_/ // / / (__ ) /_/ // // _, _/ /___/ /_/ /
/___/_/ /_/____/ .___/___/_/ |_|\____/\__,_/
/_/

View File

@@ -1,6 +0,0 @@
__ __ __
/ //_/_ __/ /_ ____
/ ,< / / / / __ \/ __ \
/ /| / /_/ / /_/ / /_/ /
/_/ |_\__,_/_.___/\____/

View File

@@ -1,6 +0,0 @@
_ __ __ __ _
/ | / /__ ____ / // / (_)
/ |/ / _ \/ __ \/ // /_/ /
/ /| / __/ /_/ /__ __/ /
/_/ |_/\___/\____/ /_/_/ /
/___/

View File

@@ -1,6 +0,0 @@
_ __ __ ____ ____
/ | / /___ ____/ /__ / __ )/ __ )
/ |/ / __ \/ __ / _ \/ __ / __ |
/ /| / /_/ / /_/ / __/ /_/ / /_/ /
/_/ |_/\____/\__,_/\___/_____/_____/

View File

@@ -1,6 +0,0 @@
____ _ __
/ __ \____ ___ ____ ____ _(_)____/ /_
/ / / / __ \/ _ \/ __ \/ __ `/ / ___/ __/
/ /_/ / /_/ / __/ / / / /_/ / (__ ) /_
\____/ .___/\___/_/ /_/\__, /_/____/\__/
/_/ /____/

View File

@@ -1,6 +0,0 @@
____ ___________
/ __ \/_ __/ ___/
/ / / / / / \__ \
/ /_/ / / / ___/ /
\____/ /_/ /____/

View File

@@ -1,6 +0,0 @@
____ _____ ______ __ _______ ____________
/ __ \/ ___// ____/ / |/ / __ \/_ __/_ __/
/ /_/ /\__ \/___ \______/ /|_/ / / / / / / / /
/ ____/___/ /___/ /_____/ / / / /_/ / / / / /
/_/ /____/_____/ /_/ /_/\___\_\/_/ /_/

View File

@@ -1,6 +0,0 @@
__ __
_______ _______/ /___ ______ ____ ______/ /____
/ ___/ / / / ___/ __/ / / / __ \/ __ `/ ___/ __/ _ \
/ / / /_/ (__ ) /_/ /_/ / /_/ / /_/ (__ ) /_/ __/
/_/ \__,_/____/\__/\__, / .___/\__,_/____/\__/\___/
/____/_/

View File

@@ -1,6 +0,0 @@
______
________ ___ / / __/
/ ___/ _ \/ _ \/ / /_
(__ ) __/ __/ / __/
/____/\___/\___/_/_/

View File

@@ -1,6 +0,0 @@
__ ___ __ __ _
_____/ /_________ ____ _____ ___ / (_)___ / /__ _ _____ / /_ __ __(_)
/ ___/ __/ ___/ _ \/ __ `/ __ `__ \/ / / __ \/ //_/____| | /| / / _ \/ __ \/ / / / /
(__ ) /_/ / / __/ /_/ / / / / / / / / / / / ,< /_____/ |/ |/ / __/ /_/ / /_/ / /
/____/\__/_/ \___/\__,_/_/ /_/ /_/_/_/_/ /_/_/|_| |__/|__/\___/_.___/\__,_/_/

View File

@@ -1,6 +0,0 @@
_ __ ____
| | / /___ _/ / /_____ __ __
| | / / __ `/ / //_/ _ \/ / / /
| |/ / /_/ / / ,< / __/ /_/ /
|___/\__,_/_/_/|_|\___/\__, /
/____/

View File

@@ -1,6 +0,0 @@
_ __ __
| | / /___ __ _____ / /___ ____ _
| | /| / / __ `/ | / / _ \/ / __ \/ __ `/
| |/ |/ / /_/ /| |/ / __/ / /_/ / /_/ /
|__/|__/\__,_/ |___/\___/_/\____/\__, /
/____/

View File

@@ -1,6 +0,0 @@
_ __ _ __ ______ __
| | / /____(_) /____ / ____/_______ ___ / /_ __
| | /| / / ___/ / __/ _ \/ /_ / ___/ _ \/ _ \/ / / / /
| |/ |/ / / / / /_/ __/ __/ / / / __/ __/ / /_/ /
|__/|__/_/ /_/\__/\___/_/ /_/ \___/\___/_/\__, /
/____/

View File

@@ -1,39 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.hivemq.com/ | Github: https://github.com/hivemq/hivemq-community-edition
APP="HiveMQ"
var_tags="${var_tags:-mqtt}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /var ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "Currently we don't provide an update function for this ${APP}."
exit
}
start
build_container
description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"

View File

@@ -309,8 +309,7 @@ function compile_libjxl() {
SOURCE=${SOURCE_DIR}/libjxl
JPEGLI_LIBJPEG_LIBRARY_SOVERSION="62"
JPEGLI_LIBJPEG_LIBRARY_VERSION="62.3.0"
LIBJXL_REVISION="794a5dcf0d54f9f0b20d288a12e87afb91d20dfc"
# : "${LIBJXL_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libjxl.json)}"
: "${LIBJXL_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libjxl.json)}"
if [[ "$LIBJXL_REVISION" != "$(grep 'libjxl' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
msg_info "Recompiling libjxl"
[[ -d "$SOURCE" ]] && rm -rf "$SOURCE"
@@ -354,8 +353,7 @@ function compile_libjxl() {
function compile_libheif() {
SOURCE=${SOURCE_DIR}/libheif
ensure_dependencies libaom-dev
LIBHEIF_REVISION="35dad50a9145332a7bfdf1ff6aef6801fb613d68"
# : "${LIBHEIF_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libheif.json)}"
: "${LIBHEIF_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libheif.json)}"
if [[ "${update:-}" ]] || [[ "$LIBHEIF_REVISION" != "$(grep 'libheif' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
msg_info "Recompiling libheif"
[[ -d "$SOURCE" ]] && rm -rf "$SOURCE"
@@ -386,8 +384,7 @@ function compile_libheif() {
function compile_libraw() {
SOURCE=${SOURCE_DIR}/libraw
LIBRAW_REVISION="0b56545a4f828743f28a4345cdfdd4c49f9f9a2a"
# : "${LIBRAW_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libraw.json)}"
: "${LIBRAW_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libraw.json)}"
if [[ "$LIBRAW_REVISION" != "$(grep 'libraw' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
msg_info "Recompiling libraw"
[[ -d "$SOURCE" ]] && rm -rf "$SOURCE"

View File

@@ -1,52 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: kristocopani
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.inspircd.org/ | Github: https://github.com/inspircd/inspircd
APP="InspIRCd"
var_tags="${var_tags:-IRC}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-2}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /lib/systemd/system/inspircd.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "inspircd" "inspircd/inspircd"; then
msg_info "Stopping Service"
systemctl stop inspircd
msg_ok "Stopped Service"
fetch_and_deploy_gh_release "inspircd" "inspircd/inspircd" "binary" "latest" "/opt/inspircd" "inspircd_*.deb13u1_amd64.deb"
msg_info "Starting Service"
systemctl start inspircd
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
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} Server-Acces it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}${IP}:6667${CL}"

View File

@@ -1,52 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster) | Co-Author: ulmentflam
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/ipfs/kubo
APP="Kubo"
var_tags="${var_tags:-sharing}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /usr/local/kubo/ipfs ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "kubo" "ipfs/kubo"; then
msg_info "Stopping service"
systemctl stop ipfs
msg_ok "Stopped service"
fetch_and_deploy_gh_release "kubo" "ipfs/kubo" "prebuild" "latest" "/usr/local/kubo" "kubo*linux-amd64.tar.gz"
msg_info "Starting service"
systemctl start ipfs
msg_ok "Service started"
msg_ok "Updated successfully!"
fi
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5001/webui${CL}"

View File

@@ -30,16 +30,16 @@ function update_script() {
exit
fi
DEB_URL=$(curl_with_retry 'https://lyrion.org/getting-started/' | grep -oP '<a\s[^>]*href="\K[^"]*amd64\.deb(?="[^>]*>)' | head -n 1)
DEB_URL=$(curl -s 'https://lyrion.org/getting-started/' | grep -oP '<a\s[^>]*href="\K[^"]*amd64\.deb(?="[^>]*>)' | head -n 1)
RELEASE=$(echo "$DEB_URL" | grep -oP 'lyrionmusicserver_\K[0-9.]+(?=_amd64\.deb)')
DEB_FILE="/tmp/lyrionmusicserver_${RELEASE}_amd64.deb"
if [[ ! -f /opt/lyrion_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/lyrion_version.txt)" ]]; then
msg_info "Updating $APP to ${RELEASE}"
curl_with_retry "$DEB_URL" "$DEB_FILE"
curl -fsSL -o "$DEB_FILE" "$DEB_URL"
$STD apt install "$DEB_FILE" -y
systemctl restart lyrionmusicserver
rm -f "$DEB_FILE"
echo "${RELEASE}" >/opt/lyrion_version.txt
systemctl restart lyrion
$STD rm -f "$DEB_FILE"
echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated $APP to ${RELEASE}"
msg_ok "Updated successfully!"
else

View File

@@ -28,7 +28,8 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "mealie" "mealie-recipes/mealie"; then
RELEASE="v3.14.0"
if check_for_gh_release "mealie" "mealie-recipes/mealie" "${RELEASE}" "each release is tested individually before the version is updated. Please do not open issues for this"; then
PYTHON_VERSION="3.12" setup_uv
NODE_MODULE="yarn" NODE_VERSION="24" setup_nodejs
@@ -40,7 +41,7 @@ function update_script() {
cp -f /opt/mealie/mealie.env /opt/mealie.env
msg_ok "Backup completed"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "mealie" "mealie-recipes/mealie" "tarball"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "mealie" "mealie-recipes/mealie" "tarball" "${RELEASE}" "/opt/mealie"
msg_info "Installing Python Dependencies with uv"
cd /opt/mealie
@@ -49,10 +50,9 @@ function update_script() {
msg_info "Building Frontend"
MEALIE_VERSION=$(<$HOME/.mealie)
SITE_SETTINGS=$(find /opt/mealie/frontend -name "site-settings.vue" -path "*/admin/*" | head -1)
$STD sed -i "s|https://github.com/mealie-recipes/mealie/commit/|https://github.com/mealie-recipes/mealie/releases/tag/|g" "$SITE_SETTINGS"
$STD sed -i "s|value: data.buildId,|value: \"v${MEALIE_VERSION}\",|g" "$SITE_SETTINGS"
$STD sed -i "s|value: data.production ? i18n.t(\"about.production\") : i18n.t(\"about.development\"),|value: \"bare-metal\",|g" "$SITE_SETTINGS"
$STD sed -i "s|https://github.com/mealie-recipes/mealie/commit/|https://github.com/mealie-recipes/mealie/releases/tag/|g" /opt/mealie/frontend/pages/admin/site-settings.vue
$STD sed -i "s|value: data.buildId,|value: \"v${MEALIE_VERSION}\",|g" /opt/mealie/frontend/pages/admin/site-settings.vue
$STD sed -i "s|value: data.production ? i18n.t(\"about.production\") : i18n.t(\"about.development\"),|value: \"bare-metal\",|g" /opt/mealie/frontend/pages/admin/site-settings.vue
export NUXT_TELEMETRY_DISABLED=1
cd /opt/mealie/frontend
$STD yarn install --prefer-offline --frozen-lockfile --non-interactive --production=false --network-timeout 1000000
@@ -98,3 +98,4 @@ 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}:9000${CL}"

View File

@@ -1,46 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Author: tteck | Co-Author: havardthom
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://neo4j.com/product/neo4j-graph-database/
APP="Neo4j"
var_tags="${var_tags:-database}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /etc/neo4j ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
JAVA_VERSION="21" setup_java
msg_info "Updating ${APP}"
$STD apt update
$STD apt -y upgrade
msg_ok "Updated successfully!"
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:7474${CL}"

View File

@@ -1,59 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (Canbiz)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/NodeBB/NodeBB
APP="NodeBB"
var_tags="${var_tags:-forum}"
var_disk="${var_disk:-10}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-2048}"
var_os="${var_os:-ubuntu}"
var_version="${var_version:-24.04}"
var_unprivileged="${var_unprivileged:-1}"
# App Output & Base Settings
header_info "$APP"
# Core
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/nodebb ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "nodebb" "NodeBB/NodeBB"; then
msg_info "Stopping Service"
systemctl stop nodebb
msg_ok "Stopped Service"
msg_info "Updating ${APP}"
cd /opt/nodebb
$STD ./nodebb upgrade
echo "${CHECK_UPDATE_RELEASE}" >~/.nodebb
msg_ok "Updated ${APP}"
msg_info "Starting Service"
systemctl start nodebb
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:4567${CL}"

View File

@@ -1,60 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Jonathan (jd-apprentice)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://opengist.io/ | Github: https://github.com/thomiceli/opengist
APP="Opengist"
var_tags="${var_tags:-development}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/opengist ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "opengist" "thomiceli/opengist"; then
msg_info "Stopping Service"
systemctl stop opengist
msg_ok "Stopped Service"
msg_info "Creating backup"
mv /opt/opengist /opt/opengist-backup
msg_ok "Backup created"
fetch_and_deploy_gh_release "opengist" "thomiceli/opengist" "prebuild" "latest" "/opt/opengist" "opengist*linux-amd64.tar.gz"
msg_info "Restoring Configuration"
mv /opt/opengist-backup/config.yml /opt/opengist/config.yml
msg_ok "Configuration Restored"
msg_info "Starting Service"
systemctl start opengist
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:6157${CL}"

View File

@@ -1,54 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: bvdberg01
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/Luzifer/ots
APP="OTS"
var_tags="${var_tags:-secrets-sharer}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-3}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/ots ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "ots" "Luzifer/ots"; then
msg_info "Stopping Services"
systemctl stop ots
systemctl stop nginx
msg_ok "Stopped Services"
fetch_and_deploy_gh_release "ots" "Luzifer/ots" "prebuild" "latest" "/opt/ots" "ots_linux_amd64.tgz"
msg_info "Starting Services"
systemctl start ots
systemctl start nginx
msg_ok "Started Services"
msg_ok "Updated successfully!"
fi
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}https://${IP}${CL}"

View File

@@ -1,58 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: liecno
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/FunkeyFlo/ps5-mqtt/
APP="PS5-MQTT"
var_tags="${var_tags:-smarthome;automation}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-3}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/ps5-mqtt ]]; then
msg_error "No ${APP} installation found!"
exit
fi
if check_for_gh_release "ps5-mqtt" "FunkeyFlo/ps5-mqtt"; then
msg_info "Stopping service"
systemctl stop ps5-mqtt
msg_ok "Stopped service"
fetch_and_deploy_gh_release "ps5-mqtt" "FunkeyFlo/ps5-mqtt" "tarball"
msg_info "Configuring ${APP}"
cd /opt/ps5-mqtt/ps5-mqtt/
$STD npm install
$STD npm run build
msg_ok "Configured ${APP}"
msg_info "Starting service"
systemctl start ps5-mqtt
msg_ok "Started service"
msg_ok "Updated successfully!"
fi
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8645${CL}"

View File

@@ -1,69 +0,0 @@
#!/usr/bin/env bash
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: GoldenSpringness
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/orhun/rustypaste
APP="rustypaste"
var_tags="${var_tags:-pastebin;storage}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-20}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /opt/rustypaste/rustypaste ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "rustypaste" "orhun/rustypaste"; then
msg_info "Stopping Services"
systemctl stop rustypaste
msg_ok "Stopped Services"
msg_info "Creating Backup"
tar -czf "/opt/rustypaste_backup_$(date +%F).tar.gz" /opt/rustypaste/upload 2>/dev/null || true
cp /opt/rustypaste/config.toml /tmp/rustypaste_config.toml.bak
msg_ok "Backup Created"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "rustypaste" "orhun/rustypaste" "prebuild" "latest" "/opt/rustypaste" "*x86_64-unknown-linux-gnu.tar.gz"
msg_info "Restoring Data"
mv /tmp/rustypaste_config.toml.bak /opt/rustypaste/config.toml
tar -xzf "/opt/rustypaste_backup_$(date +%F).tar.gz" -C /opt/rustypaste/upload 2>/dev/null || true
rm -rf /opt/rustypaste_backup_$(date +%F).tar.gz
msg_ok "Restored Data"
msg_info "Starting Services"
systemctl start rustypaste
msg_ok "Started Services"
msg_ok "Updated successfully!"
fi
if check_for_gh_release "rustypaste-cli" "orhun/rustypaste-cli"; then
fetch_and_deploy_gh_release "rustypaste-cli" "orhun/rustypaste-cli" "prebuild" "latest" "/usr/local/bin" "*x86_64-unknown-linux-gnu.tar.gz"
fi
exit
}
start
build_container
description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}rustypaste setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8000${CL}"

View File

@@ -1,56 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Slaviša Arežina (tremor021)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/YuukanOO/seelf
APP="seelf"
var_tags="${var_tags:-server;docker}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-10}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/seelf ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "seelf" "YuukanOO/seelf"; then
msg_info "Stopping Service"
systemctl stop seelf
msg_info "Stopped Service"
msg_info "Updating seelf"
cd /opt/seelf
$STD make build
msg_ok "Updated seelf"
msg_info "Starting Service"
systemctl start seelf
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"

View File

@@ -1,66 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: CrazyWolf13
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/CrazyWolf13/streamlink-webui
APP="streamlink-webui"
var_tags="${var_tags:-download;streaming}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-10}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/streamlink-webui ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "streamlink-webui" "CrazyWolf13/streamlink-webui"; then
msg_info "Stopping Service"
systemctl stop streamlink-webui
msg_info "Stopped Service"
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
setup_uv
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "streamlink-webui" "CrazyWolf13/streamlink-webui" "tarball"
msg_info "Updating streamlink-webui"
$STD uv venv --clear /opt/streamlink-webui/backend/src/.venv
source /opt/streamlink-webui/backend/src/.venv/bin/activate
$STD uv pip install -r /opt/streamlink-webui/backend/src/requirements.txt --python=/opt/streamlink-webui/backend/src/.venv
cd /opt/streamlink-webui/frontend/src
$STD yarn install
$STD yarn build
chmod +x /opt/streamlink-webui/start.sh
msg_ok "Updated streamlink-webui"
msg_info "Starting Service"
systemctl start streamlink-webui
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8000${CL}"

View File

@@ -1,45 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: pshankinclarke (lazarillo)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://valkey.io/
APP="Valkey"
var_tags="${var_tags:-database}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /lib/systemd/system/valkey-server.service ]]; then
msg_error "No Valkey Installation Found!"
exit
fi
msg_info "Updating Valkey LXC"
$STD apt update
$STD apt -y upgrade
msg_ok "Updated Valkey LXC"
msg_ok "Updated successfully!"
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:6379${CL}"

View File

@@ -1,77 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Don Locke (DonLocke)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/wavelog/wavelog
APP="Wavelog"
var_tags="${var_tags:-radio-logging}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-2}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/wavelog ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
setup_mariadb
if check_for_gh_release "wavelog" "wavelog/wavelog"; then
msg_info "Stopping Services"
systemctl stop apache2
msg_ok "Services Stopped"
msg_info "Creating backup"
cp /opt/wavelog/application/config/config.php /opt/config.php
cp /opt/wavelog/application/config/database.php /opt/database.php
cp -r /opt/wavelog/userdata /opt/userdata
if [[ -f /opt/wavelog/assets/js/sections/custom.js ]]; then
cp /opt/wavelog/assets/js/sections/custom.js /opt/custom.js
fi
msg_ok "Backup created"
rm -rf /opt/wavelog
fetch_and_deploy_gh_release "wavelog" "wavelog/wavelog" "tarball"
msg_info "Updating Wavelog"
rm -rf /opt/wavelog/install
mv /opt/config.php /opt/wavelog/application/config/config.php
mv /opt/database.php /opt/wavelog/application/config/database.php
cp -r /opt/userdata/* /opt/wavelog/userdata
rm -rf /opt/userdata
if [[ -f /opt/custom.js ]]; then
mv /opt/custom.js /opt/wavelog/assets/js/sections/custom.js
fi
chown -R www-data:www-data /opt/wavelog/
find /opt/wavelog/ -type d -exec chmod 755 {} \;
find /opt/wavelog/ -type f -exec chmod 664 {} \;
msg_ok "Updated Wavelog"
msg_info "Starting Services"
systemctl start apache2
msg_ok "Started Services"
msg_ok "Updated successfully!"
fi
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"

View File

@@ -1,72 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: StellaeAlis
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/writefreely/writefreely
APP="WriteFreely"
var_tags="${var_tags:-writing}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/writefreely ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "writefreely" "writefreely/writefreely"; then
msg_info "Stopping Services"
systemctl stop writefreely
msg_ok "Stopped Services"
msg_info "Creating Backup"
mkdir -p /tmp/writefreely_backup
cp /opt/writefreely/keys /tmp/writefreely_backup/ 2>/dev/null
cp /opt/writefreely/config.ini /tmp/writefreely_backup/ 2>/dev/null
msg_ok "Created Backup"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "writefreely" "writefreely/writefreely" "prebuild" "latest" "/opt/writefreely" "writefreely_*_linux_amd64.tar.gz"
msg_info "Restoring Data"
cp /tmp/writefreely_backup/config.ini /opt/writefreely/ 2>/dev/null
cp /tmp/writefreely_backup/keys/* /opt/writefreely/keys/ 2>/dev/null
rm -rf /tmp/writefreely_backup
msg_ok "Restored Data"
msg_info "Running Post-Update Tasks"
cd /opt/writefreely
$STD ./writefreely db migrate
ln -s /opt/writefreely/writefreely /usr/local/bin/writefreely
msg_ok "Ran Post-Update Tasks"
msg_info "Starting Services"
systemctl start writefreely
msg_ok "Started Services"
msg_ok "Updated successfully!"
fi
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"

View File

@@ -38,7 +38,6 @@ function update_script() {
cp /opt/zerobyte/.env /opt/zerobyte.env.bak
msg_ok "Backed up Configuration"
ensure_dependencies git
NODE_VERSION="24" setup_nodejs
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "zerobyte" "nicotsx/zerobyte" "tarball"

532
docs/DEV_MODE.md Normal file
View File

@@ -0,0 +1,532 @@
# Dev Mode - Debugging & Development Guide
Development modes provide powerful debugging and testing capabilities for container creation and installation processes.
## Quick Start
```bash
# Single mode
export dev_mode="motd"
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/wallabag.sh)"
# Multiple modes (comma-separated)
export dev_mode="motd,keep,trace"
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/wallabag.sh)"
# Combine with verbose output
export var_verbose="yes"
export dev_mode="pause,logs"
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/wallabag.sh)"
```
## Available Modes
### 1. **motd** - Early SSH/MOTD Setup
Sets up SSH access and MOTD **before** the main application installation.
**Use Case**:
- Quick access to container for manual debugging
- Continue installation manually if something goes wrong
- Verify container networking before main install
**Behavior**:
```
✔ Container created
✔ Network configured
[DEV] Setting up MOTD and SSH before installation
✔ [DEV] MOTD/SSH ready - container accessible
# Container is now accessible via SSH while installation proceeds
```
**Combined with**: `keep`, `breakpoint`, `logs`
---
### 2. **keep** - Preserve Container on Failure
Never delete the container when installation fails. Skips cleanup prompt.
**Use Case**:
- Repeated tests of the same installation
- Debugging failed installations
- Manual fix attempts
**Behavior**:
```
✖ Installation failed in container 107 (exit code: 1)
✔ Container creation log: /tmp/create-lxc-107-abc12345.log
✔ Installation log: /tmp/install-lxc-107-abc12345.log
🔧 [DEV] Keep mode active - container 107 preserved
root@proxmox:~#
```
**Container remains**: `pct enter 107` to access and debug
**Combined with**: `motd`, `trace`, `logs`
---
### 3. **trace** - Bash Command Tracing
Enables `set -x` for complete command-line tracing. Shows every command before execution.
**Use Case**:
- Deep debugging of installation logic
- Understanding script flow
- Identifying where errors occur exactly
**Behavior**:
```
+(/opt/wallabag/bin/console): /opt/wallabag/bin/console cache:warmup
+(/opt/wallabag/bin/console): env APP_ENV=prod /opt/wallabag/bin/console cache:warmup
+(/opt/wallabag/bin/console): [[ -d /opt/wallabag/app/cache ]]
+(/opt/wallabag/bin/console): rm -rf /opt/wallabag/app/cache/*
```
**⚠️ Warning**: Exposes passwords and secrets in log output! Only use in isolated environments.
**Log Output**: All trace output saved to logs (see `logs` mode)
**Combined with**: `keep`, `pause`, `logs`
---
### 4. **pause** - Step-by-Step Execution
Pauses after each major step (`msg_info`). Requires manual Enter press to continue.
**Use Case**:
- Inspect container state between steps
- Understand what each step does
- Identify which step causes problems
**Behavior**:
```
⏳ Setting up Container OS
[PAUSE] Press Enter to continue...
⏳ Updating Container OS
[PAUSE] Press Enter to continue...
⏳ Installing Dependencies
[PAUSE] Press Enter to continue...
```
**Between pauses**: You can open another terminal and inspect the container
```bash
# In another terminal while paused
pct enter 107
root@container:~# df -h # Check disk usage
root@container:~# ps aux # Check running processes
```
**Combined with**: `motd`, `keep`, `logs`
---
### 5. **breakpoint** - Interactive Shell on Error
Opens interactive shell inside the container when an error occurs instead of cleanup prompt.
**Use Case**:
- Live debugging in the actual container
- Manual command testing
- Inspect container state at point of failure
**Behavior**:
```
✖ Installation failed in container 107 (exit code: 1)
✔ Container creation log: /tmp/create-lxc-107-abc12345.log
✔ Installation log: /tmp/install-lxc-107-abc12345.log
🐛 [DEV] Breakpoint mode - opening shell in container 107
Type 'exit' to return to host
root@wallabag:~#
# Now you can debug:
root@wallabag:~# tail -f /root/.install-abc12345.log
root@wallabag:~# mysql -u root -p$PASSWORD wallabag
root@wallabag:~# apt-get install -y strace
root@wallabag:~# exit
Container 107 still running. Remove now? (y/N): n
🔧 Container 107 kept for debugging
```
**Combined with**: `keep`, `logs`, `trace`
---
### 6. **logs** - Persistent Logging
Saves all logs to `/var/log/community-scripts/` with timestamps. Logs persist even on successful installation.
**Use Case**:
- Post-mortem analysis
- Performance analysis
- Automated testing with log collection
- CI/CD integration
**Behavior**:
```
Logs location: /var/log/community-scripts/
create-lxc-abc12345-20251117_143022.log (host-side creation)
install-abc12345-20251117_143022.log (container-side installation)
```
**Access logs**:
```bash
# View creation log
tail -f /var/log/community-scripts/create-lxc-*.log
# Search for errors
grep ERROR /var/log/community-scripts/*.log
# Analyze performance
grep "msg_info\|msg_ok" /var/log/community-scripts/create-*.log
```
**With trace mode**: Creates detailed trace of all commands
```bash
grep "^+" /var/log/community-scripts/install-*.log
```
**Combined with**: All other modes (recommended for CI/CD)
---
### 7. **dryrun** - Simulation Mode
Shows all commands that would be executed without actually running them.
**Use Case**:
- Test script logic without making changes
- Verify command syntax
- Understand what will happen
- Pre-flight checks
**Behavior**:
```
[DRYRUN] apt-get update
[DRYRUN] apt-get install -y curl
[DRYRUN] mkdir -p /opt/wallabag
[DRYRUN] cd /opt/wallabag
[DRYRUN] git clone https://github.com/wallabag/wallabag.git .
```
**No actual changes made**: Container/system remains unchanged
**Combined with**: `trace` (shows dryrun trace), `logs` (shows what would run)
---
## Mode Combinations
### Development Workflow
```bash
# First test: See what would happen
export dev_mode="dryrun,logs"
bash -c "$(curl ...)"
# Then test with tracing and pauses
export dev_mode="pause,trace,logs"
bash -c "$(curl ...)"
# Finally full debug with early SSH access
export dev_mode="motd,keep,breakpoint,logs"
bash -c "$(curl ...)"
```
### CI/CD Integration
```bash
# Automated testing with full logging
export dev_mode="logs"
export var_verbose="yes"
bash -c "$(curl ...)"
# Capture logs for analysis
tar czf installation-logs-$(date +%s).tar.gz /var/log/community-scripts/
```
### Production-like Testing
```bash
# Keep containers for manual verification
export dev_mode="keep,logs"
for i in {1..5}; do
bash -c "$(curl ...)"
done
# Inspect all created containers
pct list
pct enter 100
```
### Live Debugging
```bash
# SSH in early, step through installation, debug on error
export dev_mode="motd,pause,breakpoint,keep"
bash -c "$(curl ...)"
```
---
## Environment Variables Reference
### Dev Mode Variables
- `dev_mode` (string): Comma-separated list of modes
- Format: `"motd,keep,trace"`
- Default: Empty (no dev modes)
### Output Control
- `var_verbose="yes"`: Show all command output (disables silent mode)
- Pairs well with: `trace`, `pause`, `logs`
### Examples with vars
```bash
# Maximum verbosity and debugging
export var_verbose="yes"
export dev_mode="motd,trace,pause,logs"
bash -c "$(curl ...)"
# Silent debug (logs only)
export dev_mode="keep,logs"
bash -c "$(curl ...)"
# Interactive debugging
export var_verbose="yes"
export dev_mode="motd,breakpoint"
bash -c "$(curl ...)"
```
---
## Troubleshooting with Dev Mode
### "Installation failed at step X"
```bash
export dev_mode="pause,logs"
# Step through until the failure point
# Check container state between pauses
pct enter 107
```
### "Password/credentials not working"
```bash
export dev_mode="motd,keep,trace"
# With trace mode, see exact password handling (be careful with logs!)
# Use motd to SSH in and test manually
ssh root@container-ip
```
### "Permission denied errors"
```bash
export dev_mode="breakpoint,keep"
# Get shell at failure point
# Check file permissions, user context, SELinux status
ls -la /path/to/file
whoami
```
### "Networking issues"
```bash
export dev_mode="motd"
# SSH in with motd mode before main install
ssh root@container-ip
ping 8.8.8.8
nslookup example.com
```
### "Need to manually complete installation"
```bash
export dev_mode="motd,keep"
# Container accessible via SSH while installation runs
# After failure, SSH in and manually continue
ssh root@container-ip
# ... manual commands ...
exit
# Then use 'keep' mode to preserve container for inspection
```
---
## Log Files Locations
### Default (without `logs` mode)
- Host creation: `/tmp/create-lxc-<SESSION_ID>.log`
- Container install: Copied to `/tmp/install-lxc-<CTID>-<SESSION_ID>.log` on failure
### With `logs` mode
- Host creation: `/var/log/community-scripts/create-lxc-<SESSION_ID>-<TIMESTAMP>.log`
- Container install: `/var/log/community-scripts/install-<SESSION_ID>-<TIMESTAMP>.log`
### View logs
```bash
# Tail in real-time
tail -f /var/log/community-scripts/*.log
# Search for errors
grep -r "exit code [1-9]" /var/log/community-scripts/
# Filter by session
grep "ed563b19" /var/log/community-scripts/*.log
```
---
## Best Practices
### ✅ DO
- Use `logs` mode for CI/CD and automated testing
- Use `motd` for early SSH access during long installations
- Use `pause` when learning the installation flow
- Use `trace` when debugging logic issues (watch for secrets!)
- Combine modes for comprehensive debugging
- Archive logs after successful tests
### ❌ DON'T
- Use `trace` in production or with untrusted networks (exposes secrets)
- Leave `keep` mode enabled for unattended scripts (containers accumulate)
- Use `dryrun` and expect actual changes
- Commit `dev_mode` exports to production deployment scripts
- Use `breakpoint` in non-interactive environments (will hang)
---
## Examples
### Example 1: Debug a Failed Installation
```bash
# Initial test to see the failure
export dev_mode="keep,logs"
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/wallabag.sh)"
# Container 107 kept, check logs
tail /var/log/community-scripts/install-*.log
# SSH in to debug
pct enter 107
root@wallabag:~# cat /root/.install-*.log | tail -100
root@wallabag:~# apt-get update # Retry the failing command
root@wallabag:~# exit
# Re-run with manual step-through
export dev_mode="motd,pause,keep"
bash -c "$(curl ...)"
```
### Example 2: Verify Installation Steps
```bash
export dev_mode="pause,logs"
export var_verbose="yes"
bash -c "$(curl ...)"
# Press Enter through each step
# Monitor container in another terminal
# pct enter 107
# Review logs in real-time
```
### Example 3: CI/CD Pipeline Integration
```bash
#!/bin/bash
export dev_mode="logs"
export var_verbose="no"
for app in wallabag nextcloud wordpress; do
echo "Testing $app installation..."
APP="$app" bash -c "$(curl ...)" || {
echo "FAILED: $app"
tar czf logs-$app.tar.gz /var/log/community-scripts/
exit 1
}
echo "SUCCESS: $app"
done
echo "All installations successful"
tar czf all-logs.tar.gz /var/log/community-scripts/
```
---
## Advanced Usage
### Custom Log Analysis
```bash
# Extract all errors
grep "ERROR\|exit code [1-9]" /var/log/community-scripts/*.log
# Performance timeline
grep "^$(date +%Y-%m-%d)" /var/log/community-scripts/*.log | grep "msg_"
# Memory usage during install
grep "free\|available" /var/log/community-scripts/*.log
```
### Integration with External Tools
```bash
# Send logs to Elasticsearch
curl -X POST "localhost:9200/installation-logs/_doc" \
-H 'Content-Type: application/json' \
-d @/var/log/community-scripts/install-*.log
# Archive for compliance
tar czf installation-records-$(date +%Y%m).tar.gz \
/var/log/community-scripts/
gpg --encrypt installation-records-*.tar.gz
```
---
## Support & Issues
When reporting installation issues, always include:
```bash
# Collect all relevant information
export dev_mode="logs"
# Run the failing installation
# Then provide:
tar czf debug-logs.tar.gz /var/log/community-scripts/
```
Include the `debug-logs.tar.gz` when reporting issues for better diagnostics.

298
docs/EXIT_CODES.md Normal file
View File

@@ -0,0 +1,298 @@
# Exit Code Reference
Comprehensive documentation of all exit codes used in ProxmoxVE scripts.
## Table of Contents
- [Generic/Shell Errors (1-255)](#genericshell-errors)
- [Package Manager Errors (100-101, 255)](#package-manager-errors)
- [Node.js/npm Errors (243-254)](#nodejsnpm-errors)
- [Python/pip Errors (210-212)](#pythonpip-errors)
- [Database Errors (231-254)](#database-errors)
- [Proxmox Custom Codes (200-231)](#proxmox-custom-codes)
---
## Generic/Shell Errors
Standard Unix/Linux exit codes used across all scripts.
| Code | Description | Common Causes | Solutions |
| ------- | --------------------------------------- | ----------------------------------------- | ---------------------------------------------- |
| **1** | General error / Operation not permitted | Permission denied, general failure | Check user permissions, run as root if needed |
| **2** | Misuse of shell builtins | Syntax error in script | Review script syntax, check bash version |
| **126** | Command cannot execute | Permission problem, not executable | `chmod +x script.sh` or check file permissions |
| **127** | Command not found | Missing binary, wrong PATH | Install required package, check PATH variable |
| **128** | Invalid argument to exit | Invalid exit code passed | Use exit codes 0-255 only |
| **130** | Terminated by Ctrl+C (SIGINT) | User interrupted script | Expected behavior, no action needed |
| **137** | Killed (SIGKILL) | Out of memory, forced termination | Check memory usage, increase RAM allocation |
| **139** | Segmentation fault | Memory access violation, corrupted binary | Reinstall package, check system stability |
| **143** | Terminated (SIGTERM) | Graceful shutdown signal | Expected during container stops |
---
## Package Manager Errors
APT, DPKG, and package installation errors.
| Code | Description | Common Causes | Solutions |
| ------- | -------------------------- | --------------------------------------- | ------------------------------------------------- |
| **100** | APT: Package manager error | Broken packages, dependency conflicts | `apt --fix-broken install`, `dpkg --configure -a` |
| **101** | APT: Configuration error | Malformed sources.list, bad repo config | Check `/etc/apt/sources.list`, run `apt update` |
| **255** | DPKG: Fatal internal error | Corrupted package database | `dpkg --configure -a`, restore from backup |
---
## Node.js/npm Errors
Node.js runtime and package manager errors.
| Code | Description | Common Causes | Solutions |
| ------- | ------------------------------------------ | ------------------------------ | ---------------------------------------------- |
| **243** | Node.js: Out of memory | JavaScript heap exhausted | Increase `--max-old-space-size`, optimize code |
| **245** | Node.js: Invalid command-line option | Wrong Node.js flags | Check Node.js version, verify CLI options |
| **246** | Node.js: Internal JavaScript Parse Error | Syntax error in JS code | Review JavaScript syntax, check dependencies |
| **247** | Node.js: Fatal internal error | Node.js runtime crash | Update Node.js, check for known bugs |
| **248** | Node.js: Invalid C++ addon / N-API failure | Native module incompatibility | Rebuild native modules, update packages |
| **249** | Node.js: Inspector error | Debug/inspect protocol failure | Disable inspector, check port conflicts |
| **254** | npm/pnpm/yarn: Unknown fatal error | Package manager crash | Clear cache, reinstall package manager |
---
## Python/pip Errors
Python runtime and package installation errors.
| Code | Description | Common Causes | Solutions |
| ------- | ------------------------------------ | --------------------------------------- | -------------------------------------------------------- |
| **210** | Python: Virtualenv missing or broken | venv not created, corrupted environment | `python3 -m venv venv`, recreate virtualenv |
| **211** | Python: Dependency resolution failed | Conflicting package versions | Use `pip install --upgrade`, check requirements.txt |
| **212** | Python: Installation aborted | EXTERNALLY-MANAGED, permission denied | Use `--break-system-packages` or venv, check permissions |
---
## Database Errors
### PostgreSQL (231-234)
| Code | Description | Common Causes | Solutions |
| ------- | ----------------------- | ---------------------------------- | ----------------------------------------------------- |
| **231** | Connection failed | Server not running, wrong socket | `systemctl start postgresql`, check connection string |
| **232** | Authentication failed | Wrong credentials | Verify username/password, check `pg_hba.conf` |
| **233** | Database does not exist | Database not created | `CREATE DATABASE`, restore from backup |
| **234** | Fatal error in query | Syntax error, constraint violation | Review SQL syntax, check constraints |
### MySQL/MariaDB (241-244)
| Code | Description | Common Causes | Solutions |
| ------- | ----------------------- | ---------------------------------- | ---------------------------------------------------- |
| **241** | Connection failed | Server not running, wrong socket | `systemctl start mysql`, check connection parameters |
| **242** | Authentication failed | Wrong credentials | Verify username/password, grant privileges |
| **243** | Database does not exist | Database not created | `CREATE DATABASE`, restore from backup |
| **244** | Fatal error in query | Syntax error, constraint violation | Review SQL syntax, check constraints |
### MongoDB (251-254)
| Code | Description | Common Causes | Solutions |
| ------- | --------------------- | -------------------- | ------------------------------------------ |
| **251** | Connection failed | Server not running | `systemctl start mongod`, check port 27017 |
| **252** | Authentication failed | Wrong credentials | Verify username/password, create user |
| **253** | Database not found | Database not created | Database auto-created on first write |
| **254** | Fatal query error | Invalid query syntax | Review MongoDB query syntax |
---
## Proxmox Custom Codes
Custom exit codes specific to ProxmoxVE scripts.
### Container Creation Errors (200-209)
| Code | Description | Common Causes | Solutions |
| ------- | ---------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------- |
| **200** | Failed to create lock file | Permission denied, disk full | Check `/tmp` permissions, free disk space |
| **203** | Missing CTID variable | Script configuration error | Set CTID in script or via prompt |
| **204** | Missing PCT_OSTYPE variable | Template selection failed | Verify template availability |
| **205** | Invalid CTID (<100) | CTID below minimum value | Use CTID ≥ 100 (1-99 reserved for Proxmox) |
| **206** | CTID already in use | Container/VM with same ID exists | Check `pct list` and `/etc/pve/lxc/`, use different ID |
| **207** | Password contains unescaped special characters | Special chars like `-`, `/`, `\`, `*` at start/end | Avoid leading special chars, use alphanumeric passwords |
| **208** | Invalid configuration | DNS format (`.home` vs `home`), MAC format (`-` vs `:`) | Remove leading dots from DNS, use `:` in MAC addresses |
| **209** | Container creation failed | Multiple possible causes | Check logs in `/tmp/pct_create_*.log`, verify template |
### Cluster & Storage Errors (210, 214, 217)
| Code | Description | Common Causes | Solutions |
| ------- | --------------------------------- | ---------------------------------- | ----------------------------------------------------------- |
| **210** | Cluster not quorate | Cluster nodes down, network issues | Check cluster status: `pvecm status`, fix node connectivity |
| **211** | Timeout waiting for template lock | Concurrent download in progress | Wait for other download to complete (60s timeout) |
| **214** | Not enough storage space | Disk full, quota exceeded | Free disk space, increase storage allocation |
| **217** | Storage does not support rootdir | Wrong storage type selected | Use storage supporting containers (dir, zfspool, lvm-thin) |
### Container Verification Errors (215-216)
| Code | Description | Common Causes | Solutions |
| ------- | -------------------------------- | -------------------------------- | --------------------------------------------------------- |
| **215** | Container created but not listed | Ghost state, incomplete creation | Check `/etc/pve/lxc/CTID.conf`, remove manually if needed |
| **216** | RootFS entry missing in config | Incomplete container creation | Delete container, retry creation |
### Template Errors (218, 220-223, 225)
| Code | Description | Common Causes | Solutions |
| ------- | ----------------------------------------- | ------------------------------------------------ | ----------------------------------------------------------- |
| **218** | Template file corrupted or incomplete | Download interrupted, file <1MB, invalid archive | Delete template, run `pveam update && pveam download` |
| **220** | Unable to resolve template path | Template storage not accessible | Check storage availability, verify permissions |
| **221** | Template file exists but not readable | Permission denied | `chmod 644 template.tar.zst`, check storage permissions |
| **222** | Template download failed after 3 attempts | Network issues, storage problems | Check internet connectivity, verify storage space |
| **223** | Template not available after download | Storage sync issue, I/O delay | Wait a few seconds, verify storage is mounted |
| **225** | No template available for OS/Version | Unsupported OS version, catalog outdated | Run `pveam update`, check `pveam available -section system` |
### LXC Stack Errors (231)
| Code | Description | Common Causes | Solutions |
| ------- | ------------------------------ | ------------------------------------------- | -------------------------------------------- |
| **231** | LXC stack upgrade/retry failed | Outdated `pve-container`, Debian 13.1 issue | See [Debian 13.1 Fix Guide](#debian-131-fix) |
---
## Special Case: Debian 13.1 "unsupported version" Error
### Problem
```
TASK ERROR: unable to create CT 129 - unsupported debian version '13.1'
```
### Root Cause
Outdated `pve-container` package doesn't recognize Debian 13 (Trixie).
### Solutions
#### Option 1: Full System Upgrade (Recommended)
```bash
apt update
apt full-upgrade -y
reboot
```
Verify fix:
```bash
dpkg -l pve-container
# PVE 8: Should show 5.3.3+
# PVE 9: Should show 6.0.13+
```
#### Option 2: Update Only pve-container
```bash
apt update
apt install --only-upgrade pve-container -y
```
**Warning:** If Proxmox fails to boot after this, your system was inconsistent. Perform Option 1 instead.
#### Option 3: Verify Repository Configuration
Many users disable Enterprise repos but forget to add no-subscription repos.
**For PVE 9 (Trixie):**
```bash
cat /etc/apt/sources.list.d/pve-no-subscription.list
```
Should contain:
```
deb http://download.proxmox.com/debian/pve trixie pve-no-subscription
deb http://download.proxmox.com/debian/ceph-squid trixie no-subscription
```
**For PVE 8 (Bookworm):**
```
deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription
deb http://download.proxmox.com/debian/ceph-quincy bookworm no-subscription
```
Then:
```bash
apt update
apt full-upgrade -y
```
### Reference
Official discussion: [GitHub #8126](https://github.com/community-scripts/ProxmoxVE/discussions/8126)
---
## Troubleshooting Tips
### Finding Error Details
1. **Check logs:**
```bash
tail -n 50 /tmp/pct_create_*.log
```
2. **Enable verbose mode:**
```bash
bash -x script.sh # Shows every command executed
```
3. **Check container status:**
```bash
pct list
pct status CTID
```
4. **Verify storage:**
```bash
pvesm status
df -h
```
### Common Patterns
- **Exit 0 with error message:** Configuration validation failed (check DNS, MAC, password format)
- **Exit 206 but container not visible:** Ghost container state - check `/etc/pve/lxc/` manually
- **Exit 209 generic error:** Check `/tmp/pct_create_*.log` for specific `pct create` failure reason
- **Exit 218 or 222:** Template issues - delete and re-download template
---
## Quick Reference Chart
| Exit Code Range | Category | Typical Issue |
| --------------- | ------------------ | ------------------------------------------- |
| 1-2, 126-143 | Shell/System | Permissions, signals, missing commands |
| 100-101, 255 | Package Manager | APT/DPKG errors, broken packages |
| 200-209 | Container Creation | CTID, password, configuration |
| 210-217 | Storage/Cluster | Disk space, quorum, storage type |
| 218-225 | Templates | Download, corruption, availability |
| 231-254 | Databases/Runtime | PostgreSQL, MySQL, MongoDB, Node.js, Python |
---
## Contributing
Found an undocumented exit code or have a solution to share? Please:
1. Open an issue on [GitHub](https://github.com/community-scripts/ProxmoxVE/issues)
2. Include:
- Exit code number
- Error message
- Steps to reproduce
- Solution that worked for you
---
_Last updated: November 2025_
_ProxmoxVE Version: 2.x_

298
docs/README.md Normal file
View File

@@ -0,0 +1,298 @@
# 📚 ProxmoxVE Documentation
Complete guide to all ProxmoxVE documentation - quickly find what you need.
---
## 🎯 **Quick Navigation by Goal**
### 👤 **I want to...**
**Contribute a new application**
→ Start with: [contribution/README.md](contribution/README.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: [guides/DEFAULTS_SYSTEM_GUIDE.md](guides/DEFAULTS_SYSTEM_GUIDE.md)
**Deploy containers automatically**
→ Read: [guides/UNATTENDED_DEPLOYMENTS.md](guides/UNATTENDED_DEPLOYMENTS.md)
**Develop a function library**
→ Study: [misc/](misc/) documentation
---
## 👤 **Quick Start by Role**
### **I'm a...**
**New Contributor**
→ Start: [contribution/README.md](contribution/README.md)
→ Then: Choose your path below
**Container Creator**
→ Read: [ct/README.md](ct/README.md)
→ Deep Dive: [ct/DETAILED_GUIDE.md](ct/DETAILED_GUIDE.md)
→ Reference: [misc/build.func/](misc/build.func/)
**Installation Script Developer**
→ Read: [install/README.md](install/README.md)
→ Deep Dive: [install/DETAILED_GUIDE.md](install/DETAILED_GUIDE.md)
→ Reference: [misc/tools.func/](misc/tools.func/)
**VM Provisioner**
→ Read: [vm/README.md](vm/README.md)
→ Reference: [misc/cloud-init.func/](misc/cloud-init.func/)
**Tools Developer**
→ Read: [tools/README.md](tools/README.md)
→ Reference: [misc/build.func/](misc/build.func/)
**API Integrator**
→ Read: [api/README.md](api/README.md)
→ Reference: [misc/api.func/](misc/api.func/)
**System Operator**
→ Start: [EXIT_CODES.md](EXIT_CODES.md)
→ Then: [guides/DEFAULTS_SYSTEM_GUIDE.md](guides/DEFAULTS_SYSTEM_GUIDE.md)
→ Automate: [guides/UNATTENDED_DEPLOYMENTS.md](guides/UNATTENDED_DEPLOYMENTS.md)
→ Debug: [DEV_MODE.md](DEV_MODE.md)
**Architect**
→ Read: [TECHNICAL_REFERENCE.md](TECHNICAL_REFERENCE.md)
→ Deep Dive: [misc/README.md](misc/README.md)
---
## 📂 **Documentation Structure**
### Project-Mirrored Directories
Each major project directory has documentation:
```
ProxmoxVE/
├─ ct/ ↔ docs/ct/ (README.md + DETAILED_GUIDE.md)
├─ install/ ↔ docs/install/ (README.md + DETAILED_GUIDE.md)
├─ vm/ ↔ docs/vm/ (README.md)
├─ tools/ ↔ docs/tools/ (README.md)
├─ api/ ↔ docs/api/ (README.md)
├─ misc/ ↔ docs/misc/ (9 function libraries)
└─ [system-wide] ↔ docs/guides/ (configuration & deployment guides)
```
### Core Documentation
| Document | Purpose | Audience |
|----------|---------|----------|
| [contribution/README.md](contribution/README.md) | How to contribute | Contributors |
| [ct/DETAILED_GUIDE.md](ct/DETAILED_GUIDE.md) | Create ct scripts | Container 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 |
| [guides/DEFAULTS_SYSTEM_GUIDE.md](guides/DEFAULTS_SYSTEM_GUIDE.md) | Configuration system | Operators, power users |
| [guides/CONFIGURATION_REFERENCE.md](guides/CONFIGURATION_REFERENCE.md) | Configuration options reference | Advanced users |
| [guides/UNATTENDED_DEPLOYMENTS.md](guides/UNATTENDED_DEPLOYMENTS.md) | Automated deployments | DevOps, automation |
| [EXIT_CODES.md](EXIT_CODES.md) | Exit code reference | Troubleshooters |
| [DEV_MODE.md](DEV_MODE.md) | Debugging tools | Developers |
---
## 📂 **Directory Guide**
### [ct/](ct/) - Container Scripts
Documentation for `/ct` - Container creation scripts that run on the Proxmox host.
**Includes**:
- Overview of container creation process
- Deep dive: [DETAILED_GUIDE.md](ct/DETAILED_GUIDE.md) - Complete reference with examples
- Reference to [misc/build.func/](misc/build.func/)
- Quick start for creating new containers
### [install/](install/) - Installation Scripts
Documentation for `/install` - Scripts that run inside containers to install applications.
**Includes**:
- Overview of 10-phase installation pattern
- Deep dive: [DETAILED_GUIDE.md](install/DETAILED_GUIDE.md) - Complete reference with examples
- Reference to [misc/tools.func/](misc/tools.func/)
- Alpine vs Debian differences
### [vm/](vm/) - Virtual Machine Scripts
Documentation for `/vm` - VM creation scripts using cloud-init provisioning.
**Includes**:
- Overview of VM provisioning
- Link to [misc/cloud-init.func/](misc/cloud-init.func/)
- VM vs Container comparison
- Cloud-init examples
### [tools/](tools/) - Tools & Utilities
Documentation for `/tools` - Management tools and add-ons.
**Includes**:
- Overview of tools structure
- Integration points
- Contributing new tools
- Common operations
### [api/](api/) - API Integration
Documentation for `/api` - Telemetry and API backend.
**Includes**:
- API overview
- Integration methods
- API endpoints
- Privacy information
### [misc/](misc/) - Function Libraries
Documentation for `/misc` - 9 core function libraries with complete references.
**Contains**:
- **build.func/** - Container orchestration (7 files)
- **core.func/** - Utilities and messaging (5 files)
- **error_handler.func/** - Error handling (5 files)
- **api.func/** - API integration (5 files)
- **install.func/** - Container setup (5 files)
- **tools.func/** - Package installation (6 files)
- **alpine-install.func/** - Alpine setup (5 files)
- **alpine-tools.func/** - Alpine tools (5 files)
- **cloud-init.func/** - VM provisioning (5 files)
---
## 🎓 **Learning Paths**
### Path 1: First-Time Contributor (2-3 hours)
1. [contribution/README.md](contribution/README.md) - Quick Start
2. Pick your area:
- Containers → [ct/README.md](ct/README.md) + [ct/DETAILED_GUIDE.md](ct/DETAILED_GUIDE.md)
- Installation → [install/README.md](install/README.md) + [install/DETAILED_GUIDE.md](install/DETAILED_GUIDE.md)
- VMs → [vm/README.md](vm/README.md)
3. Study existing similar script
4. Create your contribution
5. Submit PR
### Path 2: Intermediate Developer (4-6 hours)
1. [TECHNICAL_REFERENCE.md](TECHNICAL_REFERENCE.md)
2. Dive into function libraries:
- [misc/build.func/README.md](misc/build.func/README.md)
- [misc/tools.func/README.md](misc/tools.func/README.md)
- [misc/install.func/README.md](misc/install.func/README.md)
3. Study advanced examples
4. Create complex applications
### Path 3: Advanced Architect (8+ hours)
1. All of Intermediate Path
2. Study all 9 function libraries in depth
3. [guides/DEFAULTS_SYSTEM_GUIDE.md](guides/DEFAULTS_SYSTEM_GUIDE.md) - Configuration system
4. [DEV_MODE.md](DEV_MODE.md) - Debugging and development
5. Design new features or function libraries
### Path 4: Troubleshooter (30 minutes - 1 hour)
1. [EXIT_CODES.md](EXIT_CODES.md) - Find error code
2. [DEV_MODE.md](DEV_MODE.md) - Run with debugging
3. Check relevant function library docs
4. Review logs and fix
---
## 📊 **By the Numbers**
| Metric | Count |
|--------|:---:|
| **Documentation Files** | 63 |
| **Total Lines** | 15,000+ |
| **Function Libraries** | 9 |
| **Functions Documented** | 150+ |
| **Code Examples** | 50+ |
| **Flowcharts** | 15+ |
| **Do/Don't Sections** | 20+ |
| **Real-World Examples** | 30+ |
---
## 🔍 **Find It Fast**
### By Feature
- **How do I create a container?** → [ct/DETAILED_GUIDE.md](ct/DETAILED_GUIDE.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 install Node.js?** → [misc/tools.func/](misc/tools.func/)
- **How do I debug?** → [DEV_MODE.md](DEV_MODE.md)
### By Error
- **Exit code 206?** → [EXIT_CODES.md](EXIT_CODES.md)
- **Network failed?** → [misc/install.func/](misc/install.func/)
- **Package error?** → [misc/tools.func/](misc/tools.func/)
### By Role
- **Contributor** → [contribution/README.md](contribution/README.md)
- **Operator** → [guides/DEFAULTS_SYSTEM_GUIDE.md](guides/DEFAULTS_SYSTEM_GUIDE.md)
- **Automation** → [guides/UNATTENDED_DEPLOYMENTS.md](guides/UNATTENDED_DEPLOYMENTS.md)
- **Developer** → [TECHNICAL_REFERENCE.md](TECHNICAL_REFERENCE.md)
- **Architect** → [misc/README.md](misc/README.md)
---
## ✅ **Documentation Features**
-**Project-mirrored structure** - Organized like the actual project
-**Complete function references** - Every function documented
-**Real-world examples** - Copy-paste ready code
-**Visual flowcharts** - ASCII diagrams of workflows
-**Integration guides** - How components connect
-**Troubleshooting** - Common issues and solutions
-**Best practices** - DO/DON'T sections throughout
-**Learning paths** - Structured curriculum by role
-**Quick references** - Fast lookup by error code
-**Comprehensive navigation** - This page
---
## 🚀 **Start Here**
**New to ProxmoxVE?** → [contribution/README.md](contribution/README.md)
**Looking for something specific?** → Choose your role above or browse by directory
**Need to debug?** → [EXIT_CODES.md](EXIT_CODES.md)
**Want to understand architecture?** → [TECHNICAL_REFERENCE.md](TECHNICAL_REFERENCE.md)
---
## 🤝 **Contributing Documentation**
Found an error? Want to improve docs?
1. See: [contribution/README.md](contribution/README.md) for full contribution guide
2. Open issue: [GitHub Issues](https://github.com/community-scripts/ProxmoxVE/issues)
3. Or submit PR with improvements
---
## 📝 **Status**
- **Last Updated**: December 2025
- **Version**: 2.3 (Consolidated & Reorganized)
- **Completeness**: ✅ 100% - All components documented
- **Quality**: ✅ Production-ready
- **Structure**: ✅ Clean and organized
---
**Welcome to ProxmoxVE! Start with [CONTRIBUTION_GUIDE.md](CONTRIBUTION_GUIDE.md) or choose your role above.** 🚀

897
docs/TECHNICAL_REFERENCE.md Normal file
View File

@@ -0,0 +1,897 @@
# Technical Reference: Configuration System Architecture
> **For Developers and Advanced Users**
>
> _Deep dive into how the defaults and configuration system works_
---
## Table of Contents
1. [System Architecture](#system-architecture)
2. [File Format Specifications](#file-format-specifications)
3. [Function Reference](#function-reference)
4. [Variable Precedence](#variable-precedence)
5. [Data Flow Diagrams](#data-flow-diagrams)
6. [Security Model](#security-model)
7. [Implementation Details](#implementation-details)
---
## System Architecture
### Component Overview
```
┌─────────────────────────────────────────────────────────────┐
│ Installation Script │
│ (pihole-install.sh, docker-install.sh, etc.) │
└────────────────────┬────────────────────────────────────────┘
v
┌─────────────────────────────────────────────────────────────┐
│ build.func Library │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ variables() │ │
│ │ - Initialize NSAPP, var_install, etc. │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ install_script() │ │
│ │ - Display mode menu │ │
│ │ - Route to appropriate workflow │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ base_settings() │ │
│ │ - Apply built-in defaults │ │
│ │ - Read environment variables (var_*) │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ load_vars_file() │ │
│ │ - Safe file parsing (NO source/eval) │ │
│ │ - Whitelist validation │ │
│ │ - Value sanitization │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ default_var_settings() │ │
│ │ - Load user defaults │ │
│ │ - Display summary │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ maybe_offer_save_app_defaults() │ │
│ │ - Offer to save current settings │ │
│ │ - Handle updates vs. new saves │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
v
┌─────────────────────────────────────────────────────────────┐
│ Configuration Files (on Disk) │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ /usr/local/community-scripts/default.vars │ │
│ │ (User global defaults) │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ /usr/local/community-scripts/defaults/*.vars │ │
│ │ (App-specific defaults) │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
---
## File Format Specifications
### User Defaults: `default.vars`
**Location**: `/usr/local/community-scripts/default.vars`
**MIME Type**: `text/plain`
**Encoding**: UTF-8 (no BOM)
**Format Specification**:
```
# File Format: Simple key=value pairs
# Purpose: Store global user defaults
# Security: Sanitized values, whitelist validation
# Comments and blank lines are ignored
# Line format: var_name=value
# No spaces around the equals sign
# String values do not need quoting (but may be quoted)
[CONTENT]
var_cpu=4
var_ram=2048
var_disk=20
var_hostname=mydefault
var_brg=vmbr0
var_gateway=192.168.1.1
```
**Formal Grammar**:
```
FILE := (BLANK_LINE | COMMENT_LINE | VAR_LINE)*
BLANK_LINE := \n
COMMENT_LINE := '#' [^\n]* \n
VAR_LINE := VAR_NAME '=' VAR_VALUE \n
VAR_NAME := 'var_' [a-z_]+
VAR_VALUE := [^\n]* # Any printable characters except newline
```
**Constraints**:
| Constraint | Value |
| ----------------- | ------------------------ |
| Max file size | 64 KB |
| Max line length | 1024 bytes |
| Max variables | 100 |
| Allowed var names | `var_[a-z_]+` |
| Value validation | Whitelist + Sanitization |
**Example Valid File**:
```bash
# Global User Defaults
# Created: 2024-11-28
# Resource defaults
var_cpu=4
var_ram=2048
var_disk=20
# Network defaults
var_brg=vmbr0
var_gateway=192.168.1.1
var_mtu=1500
var_vlan=100
# System defaults
var_timezone=Europe/Berlin
var_hostname=default-container
# Storage
var_container_storage=local
var_template_storage=local
# Security
var_ssh=yes
var_protection=0
var_unprivileged=1
```
### App Defaults: `<app>.vars`
**Location**: `/usr/local/community-scripts/defaults/<appname>.vars`
**Format**: Identical to `default.vars`
**Naming Convention**: `<nsapp>.vars`
- `nsapp` = lowercase app name with spaces removed
- Examples:
- `pihole``pihole.vars`
- `opnsense``opnsense.vars`
- `docker compose``dockercompose.vars`
**Example App Defaults**:
```bash
# App-specific defaults for PiHole (pihole)
# Generated on 2024-11-28T15:32:00Z
# These override user defaults when installing pihole
var_unprivileged=1
var_cpu=2
var_ram=1024
var_disk=10
var_brg=vmbr0
var_net=veth
var_gateway=192.168.1.1
var_hostname=pihole
var_timezone=Europe/Berlin
var_container_storage=local
var_template_storage=local
var_tags=dns,pihole
```
---
## Function Reference
### `load_vars_file()`
**Purpose**: Safely load variables from .vars files without using `source` or `eval`
**Signature**:
```bash
load_vars_file(filepath)
```
**Parameters**:
| Param | Type | Required | Example |
| -------- | ------ | -------- | ------------------------------------------- |
| filepath | String | Yes | `/usr/local/community-scripts/default.vars` |
**Returns**:
- `0` on success
- `1` on error (file missing, parse error, etc.)
**Environment Side Effects**:
- Sets all parsed `var_*` variables as shell variables
- Does NOT unset variables if file missing (safe)
- Does NOT affect other variables
**Implementation Pattern**:
```bash
load_vars_file() {
local file="$1"
# File must exist
[ -f "$file" ] || return 0
# Parse line by line (not with source/eval)
local line key val
while IFS='=' read -r key val || [ -n "$key" ]; do
# Skip comments and empty lines
[[ "$key" =~ ^[[:space:]]*# ]] && continue
[[ -z "$key" ]] && continue
# Validate key is in whitelist
_is_whitelisted_key "$key" || continue
# Sanitize and export value
val="$(_sanitize_value "$val")"
[ $? -eq 0 ] && export "$key=$val"
done < "$file"
return 0
}
```
**Usage Examples**:
```bash
# Load user defaults
load_vars_file "/usr/local/community-scripts/default.vars"
# Load app-specific defaults
load_vars_file "$(get_app_defaults_path)"
# Check if successful
if load_vars_file "$vars_path"; then
echo "Settings loaded successfully"
else
echo "Failed to load settings"
fi
# Values are now available as variables
echo "Using $var_cpu cores"
echo "Allocating ${var_ram} MB RAM"
```
---
### `get_app_defaults_path()`
**Purpose**: Get the full path for app-specific defaults file
**Signature**:
```bash
get_app_defaults_path()
```
**Parameters**: None
**Returns**:
- String: Full path to app defaults file
**Implementation**:
```bash
get_app_defaults_path() {
local n="${NSAPP:-${APP,,}}"
echo "/usr/local/community-scripts/defaults/${n}.vars"
}
```
**Usage Examples**:
```bash
# Get app defaults path
app_defaults="$(get_app_defaults_path)"
echo "App defaults at: $app_defaults"
# Check if app defaults exist
if [ -f "$(get_app_defaults_path)" ]; then
echo "App defaults available"
fi
# Load app defaults
load_vars_file "$(get_app_defaults_path)"
```
---
### `default_var_settings()`
**Purpose**: Load and display user global defaults
**Signature**:
```bash
default_var_settings()
```
**Parameters**: None
**Returns**:
- `0` on success
- `1` on error
**Workflow**:
```
1. Find default.vars location
(usually /usr/local/community-scripts/default.vars)
2. Create if missing
3. Load variables from file
4. Map var_verbose → VERBOSE variable
5. Call base_settings (apply to container config)
6. Call echo_default (display summary)
```
**Implementation Pattern**:
```bash
default_var_settings() {
local VAR_WHITELIST=(
var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_gpu
var_gateway var_hostname var_ipv6_method var_mac var_mtu
var_net var_ns var_pw var_ram var_tags var_tun var_unprivileged
var_verbose var_vlan var_ssh var_ssh_authorized_key
var_container_storage var_template_storage
)
# Ensure file exists
_ensure_default_vars
# Find and load
local dv="$(_find_default_vars)"
load_vars_file "$dv"
# Map verbose flag
if [[ -n "${var_verbose:-}" ]]; then
case "${var_verbose,,}" in
1 | yes | true | on) VERBOSE="yes" ;;
*) VERBOSE="${var_verbose}" ;;
esac
fi
# Apply and display
base_settings "$VERBOSE"
echo_default
}
```
---
### `maybe_offer_save_app_defaults()`
**Purpose**: Offer to save current settings as app-specific defaults
**Signature**:
```bash
maybe_offer_save_app_defaults()
```
**Parameters**: None
**Returns**: None (side effects only)
**Behavior**:
1. After advanced installation completes
2. Offers user: "Save as App Defaults for <APP>?"
3. If yes:
- Saves to `/usr/local/community-scripts/defaults/<app>.vars`
- Only whitelisted variables included
- Previous defaults backed up (if exists)
4. If no:
- No action taken
**Flow**:
```bash
maybe_offer_save_app_defaults() {
local app_vars_path="$(get_app_defaults_path)"
# Build current settings from memory
local new_tmp="$(_build_current_app_vars_tmp)"
# Check if already exists
if [ -f "$app_vars_path" ]; then
# Show diff and ask: Update? Keep? View Diff?
_show_app_defaults_diff_menu "$new_tmp" "$app_vars_path"
else
# New defaults - just save
if whiptail --yesno "Save as App Defaults for $APP?" 10 60; then
mv "$new_tmp" "$app_vars_path"
chmod 644 "$app_vars_path"
fi
fi
}
```
---
### `_sanitize_value()`
**Purpose**: Remove dangerous characters/patterns from configuration values
**Signature**:
```bash
_sanitize_value(value)
```
**Parameters**:
| Param | Type | Required |
| ----- | ------ | -------- |
| value | String | Yes |
**Returns**:
- `0` (success) + sanitized value on stdout
- `1` (failure) + nothing if dangerous
**Dangerous Patterns**:
| Pattern | Threat | Example |
| --------- | -------------------- | -------------------- |
| `$(...)` | Command substitution | `$(rm -rf /)` |
| `` ` ` `` | Command substitution | `` `whoami` `` |
| `;` | Command separator | `value; rm -rf /` |
| `&` | Background execution | `value & malicious` |
| `<(` | Process substitution | `<(cat /etc/passwd)` |
**Implementation**:
```bash
_sanitize_value() {
case "$1" in
*'$('* | *'`'* | *';'* | *'&'* | *'<('*)
echo ""
return 1 # Reject dangerous value
;;
esac
echo "$1"
return 0
}
```
**Usage Examples**:
```bash
# Safe value
_sanitize_value "192.168.1.1" # Returns: 192.168.1.1 (status: 0)
# Dangerous value
_sanitize_value "$(whoami)" # Returns: (empty) (status: 1)
# Usage in code
if val="$(_sanitize_value "$user_input")"; then
export var_hostname="$val"
else
msg_error "Invalid value: contains dangerous characters"
fi
```
---
### `_is_whitelisted_key()`
**Purpose**: Check if variable name is in allowed whitelist
**Signature**:
```bash
_is_whitelisted_key(key)
```
**Parameters**:
| Param | Type | Required | Example |
| ----- | ------ | -------- | --------- |
| key | String | Yes | `var_cpu` |
**Returns**:
- `0` if key is whitelisted
- `1` if key is NOT whitelisted
**Implementation**:
```bash
_is_whitelisted_key() {
local k="$1"
local w
for w in "${VAR_WHITELIST[@]}"; do
[ "$k" = "$w" ] && return 0
done
return 1
}
```
**Usage Examples**:
```bash
# Check if variable can be saved
if _is_whitelisted_key "var_cpu"; then
echo "var_cpu can be saved"
fi
# Reject unknown variables
if ! _is_whitelisted_key "var_custom"; then
msg_error "var_custom is not supported"
fi
```
---
## Variable Precedence
### Loading Order
When a container is being created, variables are resolved in this order:
```
Step 1: Read ENVIRONMENT VARIABLES
├─ Check if var_cpu is already set in shell environment
├─ Check if var_ram is already set
└─ ...all var_* variables
Step 2: Load APP-SPECIFIC DEFAULTS
├─ Check if /usr/local/community-scripts/defaults/pihole.vars exists
├─ Load all var_* from that file
└─ These override built-ins but NOT environment variables
Step 3: Load USER GLOBAL DEFAULTS
├─ Check if /usr/local/community-scripts/default.vars exists
├─ Load all var_* from that file
└─ These override built-ins but NOT app-specific
Step 4: Use BUILT-IN DEFAULTS
└─ Hardcoded in script (lowest priority)
```
### Precedence Examples
**Example 1: Environment Variable Wins**
```bash
# Shell environment has highest priority
$ export var_cpu=16
$ bash pihole-install.sh
# Result: Container gets 16 cores
# (ignores app defaults, user defaults, built-ins)
```
**Example 2: App Defaults Override User Defaults**
```bash
# User Defaults: var_cpu=4
# App Defaults: var_cpu=2
$ bash pihole-install.sh
# Result: Container gets 2 cores
# (app-specific setting takes precedence)
```
**Example 3: All Defaults Missing (Built-ins Used)**
```bash
# No environment variables set
# No app defaults file
# No user defaults file
$ bash pihole-install.sh
# Result: Uses built-in defaults
# (var_cpu might be 2 by default)
```
### Implementation in Code
```bash
# Typical pattern in build.func
base_settings() {
# Priority 1: Environment variables (already set if export used)
CT_TYPE=${var_unprivileged:-"1"} # Use existing or default
# Priority 2: Load app defaults (may override above)
if [ -f "$(get_app_defaults_path)" ]; then
load_vars_file "$(get_app_defaults_path)"
fi
# Priority 3: Load user defaults
if [ -f "/usr/local/community-scripts/default.vars" ]; then
load_vars_file "/usr/local/community-scripts/default.vars"
fi
# Priority 4: Apply built-in defaults (lowest)
CORE_COUNT=${var_cpu:-"${APP_CPU_DEFAULT:-2}"}
RAM_SIZE=${var_ram:-"${APP_RAM_DEFAULT:-1024}"}
# Result: var_cpu has been set through precedence chain
}
```
---
## Data Flow Diagrams
### Installation Flow: Advanced Settings
```
┌──────────────┐
│ Start Script│
└──────┬───────┘
v
┌──────────────────────────────┐
│ Display Installation Mode │
│ Menu (5 options) │
└──────┬───────────────────────┘
│ User selects "Advanced Settings"
v
┌──────────────────────────────────┐
│ Call: base_settings() │
│ (Apply built-in defaults) │
└──────┬───────────────────────────┘
v
┌──────────────────────────────────┐
│ Call: advanced_settings() │
│ (Show 19-step wizard) │
│ - Ask CPU, RAM, Disk, Network... │
└──────┬───────────────────────────┘
v
┌──────────────────────────────────┐
│ Show Summary │
│ Review all chosen values │
└──────┬───────────────────────────┘
│ User confirms
v
┌──────────────────────────────────┐
│ Create Container │
│ Using current variable values │
└──────┬───────────────────────────┘
v
┌──────────────────────────────────┐
│ Installation Complete │
└──────┬───────────────────────────┘
v
┌──────────────────────────────────────┐
│ Offer: Save as App Defaults? │
│ (Save current settings) │
└──────┬───────────────────────────────┘
├─ YES → Save to defaults/<app>.vars
└─ NO → Exit
```
### Variable Resolution Flow
```
CONTAINER CREATION STARTED
v
┌─────────────────────┐
│ Check ENVIRONMENT │
│ for var_cpu, var_..│
└──────┬──────────────┘
│ Found? Use them (Priority 1)
│ Not found? Continue...
v
┌──────────────────────────┐
│ Load App Defaults │
│ /defaults/<app>.vars │
└──────┬───────────────────┘
│ File exists? Parse & load (Priority 2)
│ Not found? Continue...
v
┌──────────────────────────┐
│ Load User Defaults │
│ /default.vars │
└──────┬───────────────────┘
│ File exists? Parse & load (Priority 3)
│ Not found? Continue...
v
┌──────────────────────────┐
│ Use Built-in Defaults │
│ (Hardcoded values) │
└──────┬───────────────────┘
v
┌──────────────────────────┐
│ All Variables Resolved │
│ Ready for container │
│ creation │
└──────────────────────────┘
```
---
## Security Model
### Threat Model
| Threat | Mitigation |
| ---------------------------- | ------------------------------------------------- |
| **Arbitrary Code Execution** | No `source` or `eval`; manual parsing only |
| **Variable Injection** | Whitelist of allowed variable names |
| **Command Substitution** | `_sanitize_value()` blocks `$()`, backticks, etc. |
| **Path Traversal** | Files locked to `/usr/local/community-scripts/` |
| **Permission Escalation** | Files created with restricted permissions |
| **Information Disclosure** | Sensitive variables not logged |
### Security Controls
#### 1. Input Validation
```bash
# Only specific variables allowed
if ! _is_whitelisted_key "$key"; then
skip_this_variable
fi
# Values sanitized
if ! val="$(_sanitize_value "$value")"; then
reject_entire_line
fi
```
#### 2. Safe File Parsing
```bash
# ❌ DANGEROUS (OLD)
source /path/to/config.conf
# Could execute: rm -rf / or any code
# ✅ SAFE (NEW)
load_vars_file "/path/to/config.conf"
# Only reads var_name=value pairs, no execution
```
#### 3. Whitelisting
```bash
# Only these variables can be configured
var_cpu, var_ram, var_disk, var_brg, ...
var_hostname, var_pw, var_ssh, ...
# NOT allowed:
var_malicious, var_hack, custom_var, ...
```
#### 4. Value Constraints
```bash
# No command injection patterns
if [[ "$value" =~ ($|`|;|&|<\() ]]; then
reject_value
fi
```
---
## Implementation Details
### Module: `build.func`
**Load Order** (in actual scripts):
1. `#!/usr/bin/env bash` - Shebang
2. `source /dev/stdin <<<$(curl ... api.func)` - API functions
3. `source /dev/stdin <<<$(curl ... build.func)` - Build functions
4. `variables()` - Initialize variables
5. `check_root()` - Security check
6. `install_script()` - Main flow
**Key Sections**:
```bash
# Section 1: Initialization & Variables
- variables()
- NSAPP, var_install, INTEGER pattern, etc.
# Section 2: Storage Management
- storage_selector()
- ensure_storage_selection_for_vars_file()
# Section 3: Base Settings
- base_settings() # Apply defaults to all var_*
- echo_default() # Display current settings
# Section 4: Variable Loading
- load_vars_file() # Safe parsing
- _is_whitelisted_key() # Validation
- _sanitize_value() # Threat mitigation
# Section 5: Defaults Management
- default_var_settings() # Load user defaults
- get_app_defaults_path() # Get app defaults path
- maybe_offer_save_app_defaults() # Save option
# Section 6: Installation Flow
- install_script() # Main entry point
- advanced_settings() # 20-step wizard
```
### Regex Patterns Used
| Pattern | Purpose | Example Match |
| ---------------------- | --------------------- | ----------------------- |
| `^[0-9]+([.][0-9]+)?$` | Integer validation | `4`, `192.168` |
| `^var_[a-z_]+$` | Variable name | `var_cpu`, `var_ssh` |
| `*'$('*` | Command substitution | `$(whoami)` |
| `*\`\*` | Backtick substitution | `` `cat /etc/passwd` `` |
---
## Appendix: Migration Reference
### Old Pattern (Deprecated)
```bash
# ❌ OLD: config-file.func
source config-file.conf # Executes arbitrary code
if [ "$USE_DEFAULTS" = "yes" ]; then
apply_settings_directly
fi
```
### New Pattern (Current)
```bash
# ✅ NEW: load_vars_file()
if load_vars_file "$(get_app_defaults_path)"; then
echo "Settings loaded securely"
fi
```
### Function Mapping
| Old | New | Location |
| ---------------- | --------------------------------- | ---------- |
| `read_config()` | `load_vars_file()` | build.func |
| `write_config()` | `_build_current_app_vars_tmp()` | build.func |
| None | `maybe_offer_save_app_defaults()` | build.func |
| None | `get_app_defaults_path()` | build.func |
---
**End of Technical Reference**

146
docs/api/README.md Normal file
View File

@@ -0,0 +1,146 @@
# API Integration Documentation (/api)
This directory contains comprehensive documentation for API integration and the `/api` directory.
## Overview
The `/api` directory contains the Proxmox Community Scripts API backend for diagnostic reporting, telemetry, and analytics integration.
## Key Components
### Main API Service
Located in `/api/main.go`:
- RESTful API for receiving telemetry data
- Installation statistics tracking
- Error reporting and analytics
- Performance monitoring
### Integration with Scripts
The API is integrated into all installation scripts via `api.func`:
- Sends installation start/completion events
- Reports errors and exit codes
- Collects anonymous usage statistics
- Enables project analytics
## Documentation Structure
API documentation covers:
- API endpoint specifications
- Integration methods
- Data formats and schemas
- Error handling
- Privacy and data handling
## Key Resources
- **[misc/api.func/](../misc/api.func/)** - API function library documentation
- **[misc/api.func/README.md](../misc/api.func/README.md)** - Quick reference
- **[misc/api.func/API_FUNCTIONS_REFERENCE.md](../misc/api.func/API_FUNCTIONS_REFERENCE.md)** - Complete function reference
## API Functions
The `api.func` library provides:
### `post_to_api()`
Send container installation data to API.
**Usage**:
```bash
post_to_api CTID STATUS APP_NAME
```
### `post_update_to_api()`
Report application update status.
**Usage**:
```bash
post_update_to_api CTID APP_NAME VERSION
```
### `get_error_description()`
Get human-readable error description from exit code.
**Usage**:
```bash
ERROR_DESC=$(get_error_description EXIT_CODE)
```
## API Integration Points
### In Container Creation (`ct/AppName.sh`)
- Called by build.func to report container creation
- Sends initial container setup data
- Reports success or failure
### In Installation Scripts (`install/appname-install.sh`)
- Called at start of installation
- Called on installation completion
- Called on error conditions
### Data Collected
- Container/VM ID
- Application name and version
- Installation duration
- Success/failure status
- Error codes (if failure)
- Anonymous usage metrics
## Privacy
All API data:
- ✅ Anonymous (no personal data)
- ✅ Aggregated for statistics
- ✅ Used only for project improvement
- ✅ No tracking of user identities
- ✅ Can be disabled if desired
## API Architecture
```
Installation Scripts
├─ Call: api.func functions
└─ POST to: https://api.community-scripts.org
├─ Receives data
├─ Validates format
├─ Stores metrics
└─ Aggregates statistics
└─ Used for:
├─ Download tracking
├─ Error trending
├─ Feature usage stats
└─ Project health monitoring
```
## Common API Tasks
- **Enable API reporting** → Built-in by default, no configuration needed
- **Disable API** → Set `api_disable="yes"` before running
- **View API data** → Visit https://community-scripts.org/stats
- **Report API errors** → [GitHub Issues](https://github.com/community-scripts/ProxmoxVE/issues)
## Debugging API Issues
If API calls fail:
1. Check internet connectivity
2. Verify API endpoint availability
3. Review error codes in [EXIT_CODES.md](../EXIT_CODES.md)
4. Check API function logs
5. Report issues on GitHub
## API Endpoint
**Base URL**: `https://api.community-scripts.org`
**Endpoints**:
- `POST /install` - Report container installation
- `POST /update` - Report application update
- `GET /stats` - Public statistics
---
**Last Updated**: December 2025
**Maintainers**: community-scripts team

868
docs/contribution/AI.md Normal file
View File

@@ -0,0 +1,868 @@
# 🤖 AI Contribution Guidelines for ProxmoxVE
> **This documentation is intended for all AI assistants (GitHub Copilot, Claude, ChatGPT, etc.) contributing to this project.**
## 🎯 Core Principles
### 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!
### 2. **No Pointless Variables**
Only create variables when they:
- Are used multiple times
- Improve readability
- Are intended for configuration
### 3. **Consistent Script Structure**
All scripts follow an identical structure. Deviations are not acceptable.
### 4. **Bare-Metal Installation**
We do **NOT use Docker** for our installation scripts. All applications are installed directly on the system.
---
## 📁 Script Types and Their Structure
### CT Script (`ct/AppName.sh`)
```bash
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: AuthorName (GitHubUsername)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://application-url.com
APP="AppName"
var_tags="${var_tags:-tag1;tag2;tag3}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/appname ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "appname" "YourUsername/YourRepo"; then
msg_info "Stopping Service"
systemctl stop appname
msg_ok "Stopped Service"
msg_info "Backing up Data"
cp -r /opt/appname/data /opt/appname_data_backup
msg_ok "Backed up Data"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" "latest" "/opt/appname"
# Build steps...
msg_info "Restoring Data"
cp -r /opt/appname_data_backup/. /opt/appname/data
rm -rf /opt/appname_data_backup
msg_ok "Restored Data"
msg_info "Starting Service"
systemctl start appname
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:PORT${CL}"
```
### Install Script (`install/AppName-install.sh`)
```bash
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: AuthorName (GitHubUsername)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://application-url.com
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt-get install -y \
dependency1 \
dependency2
msg_ok "Installed Dependencies"
# Runtime Setup (ALWAYS use our functions!)
NODE_VERSION="22" setup_nodejs
# or
PG_VERSION="16" setup_postgresql
# or
setup_uv
# etc.
fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" "latest" "/opt/appname"
msg_info "Setting up Application"
cd /opt/appname
# Build/Setup Schritte...
msg_ok "Set up Application"
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
ExecStart=/path/to/executable
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now appname
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc
```
---
## 🔧 Available Helper Functions
### Release Management
| Function | Description | Example |
| ----------------------------- | ----------------------------------- | ------------------------------------------------------------- |
| `fetch_and_deploy_gh_release` | Fetches and installs GitHub Release | `fetch_and_deploy_gh_release "app" "owner/repo"` |
| `check_for_gh_release` | Checks for new version | `if check_for_gh_release "app" "YourUsername/YourRepo"; then` |
**Modes for `fetch_and_deploy_gh_release`:**
```bash
# Tarball/Source (Standard)
fetch_and_deploy_gh_release "appname" "owner/repo"
# Binary (.deb)
fetch_and_deploy_gh_release "appname" "owner/repo" "binary"
# Prebuilt Archive
fetch_and_deploy_gh_release "appname" "owner/repo" "prebuild" "latest" "/opt/appname" "filename.tar.gz"
# Single Binary
fetch_and_deploy_gh_release "appname" "owner/repo" "singlefile" "latest" "/opt/appname" "binary-linux-amd64"
```
**Clean Install Flag:**
```bash
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo"
```
### Runtime/Language Setup
| Function | Variable(s) | Example |
| -------------- | ----------------------------- | ---------------------------------------------------- |
| `setup_nodejs` | `NODE_VERSION`, `NODE_MODULE` | `NODE_VERSION="22" setup_nodejs` |
| `setup_uv` | `PYTHON_VERSION` | `PYTHON_VERSION="3.12" setup_uv` |
| `setup_go` | `GO_VERSION` | `GO_VERSION="1.22" setup_go` |
| `setup_rust` | `RUST_VERSION`, `RUST_CRATES` | `RUST_CRATES="monolith" setup_rust` |
| `setup_ruby` | `RUBY_VERSION` | `RUBY_VERSION="3.3" setup_ruby` |
| `setup_java` | `JAVA_VERSION` | `JAVA_VERSION="21" setup_java` |
| `setup_php` | `PHP_VERSION`, `PHP_MODULES` | `PHP_VERSION="8.3" PHP_MODULES="redis,gd" setup_php` |
### Database Setup
| Function | Variable(s) | Example |
| --------------------- | ------------------------------------ | ----------------------------------------------------------- |
| `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_mariadb_db` | `MARIADB_DB_NAME`, `MARIADB_DB_USER` | `MARIADB_DB_NAME="mydb" setup_mariadb_db` |
| `setup_mysql` | `MYSQL_VERSION` | `setup_mysql` |
| `setup_mongodb` | `MONGO_VERSION` | `setup_mongodb` |
| `setup_clickhouse` | - | `setup_clickhouse` |
### Tools & Utilities
| Function | Description |
| ------------------- | ---------------------------------- |
| `setup_adminer` | Installs Adminer for DB management |
| `setup_composer` | Install PHP Composer |
| `setup_ffmpeg` | Install FFmpeg |
| `setup_imagemagick` | Install ImageMagick |
| `setup_gs` | Install Ghostscript |
| `setup_hwaccel` | Configure hardware acceleration |
### Helper Utilities
| Function | Description | Example |
| ----------------------------- | ---------------------------- | ----------------------------------------- |
| `import_local_ip` | Sets `$LOCAL_IP` variable | `import_local_ip` |
| `ensure_dependencies` | Checks/installs dependencies | `ensure_dependencies curl jq` |
| `install_packages_with_retry` | APT install with retry | `install_packages_with_retry nginx redis` |
---
## ❌ Anti-Patterns (NEVER use!)
### 1. Pointless Variables
```bash
# ❌ WRONG - unnecessary variables
APP_NAME="myapp"
APP_DIR="/opt/${APP_NAME}"
APP_USER="root"
APP_PORT="3000"
cd $APP_DIR
# ✅ CORRECT - use directly
cd /opt/myapp
```
### 2. Custom Download Logic
```bash
# ❌ WRONG - custom wget/curl logic
RELEASE=$(curl -s https://api.github.com/repos/YourUsername/YourRepo/releases/latest | jq -r '.tag_name')
wget https://github.com/YourUsername/YourRepo/archive/${RELEASE}.tar.gz
tar -xzf ${RELEASE}.tar.gz
mv repo-${RELEASE} /opt/myapp
# ✅ CORRECT - use our function
fetch_and_deploy_gh_release "myapp" "YourUsername/YourRepo" "tarball" "latest" "/opt/myapp"
```
### 3. Custom Version-Check Logic
```bash
# ❌ WRONG - custom version check
CURRENT=$(cat /opt/myapp/version.txt)
LATEST=$(curl -s https://api.github.com/repos/YourUsername/YourRepo/releases/latest | jq -r '.tag_name')
if [[ "$CURRENT" != "$LATEST" ]]; then
# update...
fi
# ✅ CORRECT - use our function
if check_for_gh_release "myapp" "YourUsername/YourRepo"; then
# update...
fi
```
### 4. Docker-based Installation
```bash
# ❌ WRONG - using Docker
docker pull myapp/myapp:latest
docker run -d --name myapp myapp/myapp:latest
# ✅ CORRECT - Bare-Metal Installation
fetch_and_deploy_gh_release "myapp" "YourUsername/YourRepo"
npm install && npm run build
```
### 5. Custom Runtime Installation
```bash
# ❌ WRONG - custom Node.js installation
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt install -y nodejs
# ✅ CORRECT - use our function
NODE_VERSION="22" setup_nodejs
```
### 6. Redundant echo Statements
```bash
# ❌ WRONG - custom logging messages
echo "Installing dependencies..."
apt install -y curl
echo "Done!"
# ✅ CORRECT - use msg_info/msg_ok
msg_info "Installing Dependencies"
$STD apt install -y curl
msg_ok "Installed Dependencies"
```
### 7. Missing $STD Usage
```bash
# ❌ WRONG - apt without $STD
apt install -y nginx
# ✅ CORRECT - with $STD for silent output
$STD apt install -y nginx
```
### 8. Wrapping `tools.func` Functions in msg Blocks
```bash
# ❌ WRONG - tools.func functions have their own msg_info/msg_ok!
msg_info "Installing Node.js"
NODE_VERSION="22" setup_nodejs
msg_ok "Installed Node.js"
msg_info "Updating Application"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" "latest" "/opt/appname"
msg_ok "Updated Application"
# ✅ CORRECT - call directly without msg wrapper
NODE_VERSION="22" setup_nodejs
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" "latest" "/opt/appname"
```
**Functions with built-in messages (NEVER wrap in msg blocks):**
- `fetch_and_deploy_gh_release`
- `check_for_gh_release`
- `setup_nodejs`
- `setup_postgresql` / `setup_postgresql_db`
- `setup_mariadb` / `setup_mariadb_db`
- `setup_mongodb`
- `setup_mysql`
- `setup_ruby`
- `setup_go`
- `setup_java`
- `setup_php`
- `setup_uv`
- `setup_rust`
- `setup_composer`
- `setup_ffmpeg`
- `setup_imagemagick`
- `setup_gs`
- `setup_adminer`
- `setup_hwaccel`
### 9. Creating Unnecessary System Users
```bash
# ❌ WRONG - LXC containers run as root, no separate user needed
useradd -m -s /usr/bin/bash appuser
chown -R appuser:appuser /opt/appname
sudo -u appuser npm install
# ✅ CORRECT - run directly as root
cd /opt/appname
$STD npm install
```
### 10. Using `export` in .env Files
```bash
# ❌ WRONG - export is unnecessary in .env files
cat <<EOF >/opt/appname/.env
export DATABASE_URL=postgres://...
export SECRET_KEY=abc123
export NODE_ENV=production
EOF
# ✅ CORRECT - simple KEY=VALUE format (files are sourced with set -a)
cat <<EOF >/opt/appname/.env
DATABASE_URL=postgres://...
SECRET_KEY=abc123
NODE_ENV=production
EOF
```
### 11. Using External Shell Scripts
```bash
# ❌ WRONG - external script that gets executed
cat <<'EOF' >/opt/appname/install_script.sh
#!/bin/bash
cd /opt/appname
npm install
npm run build
EOF
chmod +x /opt/appname/install_script.sh
$STD bash /opt/appname/install_script.sh
rm -f /opt/appname/install_script.sh
# ✅ CORRECT - run commands directly
cd /opt/appname
$STD npm install
$STD npm run build
```
### 12. Using `sudo` in LXC Containers
```bash
# ❌ WRONG - sudo is unnecessary in LXC (already root)
sudo -u postgres psql -c "CREATE DATABASE mydb;"
sudo -u appuser npm install
# ✅ CORRECT - use functions or run directly as root
PG_DB_NAME="mydb" PG_DB_USER="myuser" setup_postgresql_db
cd /opt/appname
$STD npm install
```
### 13. Unnecessary `systemctl daemon-reload`
```bash
# ❌ WRONG - daemon-reload is only needed when MODIFYING existing services
cat <<EOF >/etc/systemd/system/appname.service
# ... service config ...
EOF
systemctl daemon-reload # Unnecessary for new services!
systemctl enable -q --now appname
# ✅ CORRECT - new services don't need daemon-reload
cat <<EOF >/etc/systemd/system/appname.service
# ... service config ...
EOF
systemctl enable -q --now appname
```
### 14. Creating Custom Credentials Files
```bash
# ❌ WRONG - custom credentials file is not part of the standard template
msg_info "Saving Credentials"
cat <<EOF >~/appname.creds
Database User: ${DB_USER}
Database Pass: ${DB_PASS}
EOF
msg_ok "Saved Credentials"
# ✅ CORRECT - credentials are stored in .env or shown in final message only
# If you use setup_postgresql_db / setup_mariadb_db, a standard ~/[appname].creds is created automatically
```
### 15. Wrong Footer Pattern
```bash
# ❌ WRONG - old cleanup pattern with msg blocks
motd_ssh
customize
msg_info "Cleaning up"
$STD apt-get -y autoremove
$STD apt-get -y autoclean
msg_ok "Cleaned"
# ✅ CORRECT - use cleanup_lxc function
motd_ssh
customize
cleanup_lxc
```
### 16. Manual Database Creation Instead of Functions
```bash
# ❌ WRONG - manual database creation
DB_USER="myuser"
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)
$STD sudo -u postgres psql -c "CREATE ROLE $DB_USER WITH LOGIN PASSWORD '$DB_PASS';"
$STD sudo -u postgres psql -c "CREATE DATABASE mydb WITH OWNER $DB_USER;"
$STD sudo -u postgres psql -d mydb -c "CREATE EXTENSION IF NOT EXISTS postgis;"
# ✅ CORRECT - use setup_postgresql_db function
# This sets PG_DB_USER, PG_DB_PASS, PG_DB_NAME automatically
PG_DB_NAME="mydb" PG_DB_USER="myuser" PG_DB_EXTENSIONS="postgis" setup_postgresql_db
```
### 17. Writing Files Without Heredocs
```bash
# ❌ WRONG - echo / printf / tee
echo "# Config" > /opt/app/config.yml
echo "port: 3000" >> /opt/app/config.yml
printf "# Config\nport: 3000\n" > /opt/app/config.yml
cat config.yml | tee /opt/app/config.yml
```
```bash
# ✅ CORRECT - always use a single heredoc
cat <<EOF >/opt/app/config.yml
# Config
port: 3000
EOF
```
---
## 📝 Important Rules
### Variable Declarations (CT Script)
```bash
# Standard declarations (ALWAYS present)
APP="AppName"
var_tags="${var_tags:-tag1;tag2}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
```
### Update-Script Pattern
```bash
function update_script() {
header_info
check_container_storage
check_container_resources
# 1. Check if installation exists
if [[ ! -d /opt/appname ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
# 2. Check for update
if check_for_gh_release "appname" "YourUsername/YourRepo"; then
# 3. Stop service
msg_info "Stopping Service"
systemctl stop appname
msg_ok "Stopped Service"
# 4. Backup data (if present)
msg_info "Backing up Data"
cp -r /opt/appname/data /opt/appname_data_backup
msg_ok "Backed up Data"
# 5. Perform clean install
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" "latest" "/opt/appname"
# 6. Rebuild (if needed)
cd /opt/appname
$STD npm install
$STD npm run build
# 7. Restore data
msg_info "Restoring Data"
cp -r /opt/appname_data_backup/. /opt/appname/data
rm -rf /opt/appname_data_backup
msg_ok "Restored Data"
# 8. Start service
msg_info "Starting Service"
systemctl start appname
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
exit # IMPORTANT: Always end with exit!
}
```
### Systemd Service Pattern
```bash
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"
```
### Installation Script Footer
```bash
# ALWAYS at the end of the install script:
motd_ssh
customize
cleanup_lxc
```
---
## 📖 Reference: Good Example Scripts
Look at these recent well-implemented applications as reference:
### 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
### 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
**Key things to notice:**
- Proper error handling with `catch_errors`
- Use of `check_for_gh_release` and `fetch_and_deploy_gh_release`
- Correct backup/restore patterns in `update_script`
- Footer always ends with `motd_ssh`, `customize`, `cleanup_lxc`
- Website metadata requested via the website (Report issue on script page) if needed
---
## Website Metadata (Reference)
Website metadata (name, slug, description, logo, categories, etc.) is **not** added as files in the repo. Contributors request or update it via the **website**: go to the script's page and use the **Report issue** button; the flow will guide you. The structure below is a **reference** for what metadata exists (e.g. for the form or when describing what you need).
### JSON Structure (Reference)
```json
{
"name": "AppName",
"slug": "appname",
"categories": [1],
"date_created": "2026-01-16",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://docs.appname.com/",
"website": "https://appname.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/appname.webp",
"config_path": "/opt/appname/.env",
"description": "Short description of the application and its purpose.",
"install_methods": [
{
"type": "default",
"script": "ct/appname.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}
```
### Required Fields
| Field | Type | Description |
| --------------------- | ------- | -------------------------------------------------- |
| `name` | string | Display name of the application |
| `slug` | string | Lowercase, no spaces, used for filenames |
| `categories` | array | Category ID(s) - see category list below |
| `date_created` | string | Creation date (YYYY-MM-DD) |
| `type` | string | `ct` for container, `vm` for virtual machine |
| `updateable` | boolean | Whether update_script is implemented |
| `privileged` | boolean | Whether container needs privileged mode |
| `interface_port` | number | Primary web interface port (or `null`) |
| `documentation` | string | Link to official docs |
| `website` | string | Link to official website |
| `logo` | string | URL to application logo (preferably selfhst icons) |
| `config_path` | string | Path to main config file (or empty string) |
| `description` | string | Brief description of the application |
| `install_methods` | array | Installation configurations |
| `default_credentials` | object | Default username/password (or null) |
| `notes` | array | Additional notes/warnings |
### Categories
| ID | Category |
| --- | ------------------------- |
| 0 | Miscellaneous |
| 1 | Proxmox & Virtualization |
| 2 | Operating Systems |
| 3 | Containers & Docker |
| 4 | Network & Firewall |
| 5 | Adblock & DNS |
| 6 | Authentication & Security |
| 7 | Backup & Recovery |
| 8 | Databases |
| 9 | Monitoring & Analytics |
| 10 | Dashboards & Frontends |
| 11 | Files & Downloads |
| 12 | Documents & Notes |
| 13 | Media & Streaming |
| 14 | \*Arr Suite |
| 15 | NVR & Cameras |
| 16 | IoT & Smart Home |
| 17 | ZigBee, Z-Wave & Matter |
| 18 | MQTT & Messaging |
| 19 | Automation & Scheduling |
| 20 | AI / Coding & Dev-Tools |
| 21 | Webservers & Proxies |
| 22 | Bots & ChatOps |
| 23 | Finance & Budgeting |
| 24 | Gaming & Leisure |
| 25 | Business & ERP |
### Notes Format
```json
"notes": [
{
"text": "Change the default password after first login!",
"type": "warning"
},
{
"text": "Requires at least 4GB RAM for optimal performance.",
"type": "info"
}
]
```
**Note types:** `info`, `warning`, `error`
### Examples with Credentials
```json
"default_credentials": {
"username": "admin",
"password": "admin"
}
```
Or no credentials:
```json
"default_credentials": {
"username": null,
"password": null
}
```
---
## 🔍 Checklist Before PR Creation
- [ ] No Docker installation used
- [ ] `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`!)
- [ ] Website metadata requested via the website (Report issue) if needed
- [ ] 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
4. **Test via GitHub** - push to your fork and test with curl (not local bash)
```bash
bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"
# Wait 10-30 seconds after pushing - GitHub takes time to update files
```
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
---
## 🍒 Important: Cherry-Picking Your Files for PR Submission
⚠️ **CRITICAL**: When you submit your PR, you must use git cherry-pick to send ONLY your 2 files!
Why? Because `setup-fork.sh` modifies 600+ files to update links. If you commit all changes, your PR will be impossible to merge.
**See**: [README.md - Cherry-Pick Section](README.md#-cherry-pick-submitting-only-your-changes) for complete instructions on:
- Creating a clean submission branch
- Cherry-picking only your files (ct/myapp.sh, install/myapp-install.sh)
- Verifying your PR has only 2 file changes (not 600+)
**Quick reference**:
```bash
# Create clean branch from upstream
git fetch upstream
git checkout -b submit/myapp upstream/main
# Cherry-pick your commit(s) or manually add your 2 files
# Then push to your fork and create PR
```
---
## 📚 Further Documentation
- [CONTRIBUTING.md](CONTRIBUTING.md) - General contribution guidelines
- [GUIDE.md](GUIDE.md) - Detailed developer documentation
- [HELPER_FUNCTIONS.md](HELPER_FUNCTIONS.md) - Complete tools.func reference
- [README.md](README.md) - Cherry-pick guide and workflow instructions
- [../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/) - Metadata structure reference; submit via website

View File

@@ -0,0 +1,41 @@
# 🧪 Code Audit: LXC Script Flow
This guide explains the current execution flow and what to verify during reviews.
## Execution Flow (CT + Install)
1. `ct/appname.sh` runs on the Proxmox host and sources `misc/build.func`.
2. `build.func` orchestrates prompts, container creation, and invokes the install script.
3. Inside the container, `misc/install.func` exposes helper functions via `$FUNCTIONS_FILE_PATH`.
4. `install/appname-install.sh` performs the application install.
5. The CT script prints the completion message.
## Audit Checklist
### CT Script (ct/)
- Sources `misc/build.func` from `community-scripts/ProxmoxVE/main` (setup-fork.sh updates for forks).
- Uses `check_for_gh_release` + `fetch_and_deploy_gh_release` for updates.
- No Docker-based installs.
### Install Script (install/)
- Sources `$FUNCTIONS_FILE_PATH`.
- Uses `tools.func` helpers (setup\_\*).
- Ends with `motd_ssh`, `customize`, `cleanup_lxc`.
### Website Metadata
- Website metadata for new/updated scripts is requested via the website (Report issue on script page) where applicable.
### Testing
- Test via curl from your fork (CT script only).
- Wait 10-30 seconds after push.
## References
- `docs/contribution/templates_ct/AppName.sh`
- `docs/contribution/templates_install/AppName-install.sh`
- `docs/contribution/templates_json/AppName.json`
- `docs/contribution/GUIDE.md`

View File

@@ -0,0 +1,176 @@
# Community Scripts Contribution Guide
## **Welcome to the communty-scripts Repository!**
📜 These documents outline the essential coding standards for all our scripts and JSON files. Adhering to these standards ensures that our codebase remains consistent, readable, and maintainable. By following these guidelines, we can improve collaboration, reduce errors, and enhance the overall quality of our project.
### Why Coding Standards Matter
Coding standards are crucial for several reasons:
1. **Consistency**: Consistent code is easier to read, understand, and maintain. It helps new team members quickly get up to speed and reduces the learning curve.
2. **Readability**: Clear and well-structured code is easier to debug and extend. It allows developers to quickly identify and fix issues.
3. **Maintainability**: Code that follows a standard structure is easier to refactor and update. It ensures that changes can be made with minimal risk of introducing new bugs.
4. **Collaboration**: When everyone follows the same standards, it becomes easier to collaborate on code. It reduces friction and misunderstandings during code reviews and merges.
### Scope of These Documents
These documents cover the coding standards for the following types of files in our project:
- **`install/$AppName-install.sh` Scripts**: These scripts are responsible for the installation of applications.
- **`ct/$AppName.sh` Scripts**: These scripts handle the creation and updating of containers.
- **Website metadata**: Display data (name, description, logo, etc.) is requested via the website (Report issue on the script page), not via files in the repo.
Each section provides detailed guidelines on various aspects of coding, including shebang usage, comments, variable naming, function naming, indentation, error handling, command substitution, quoting, script structure, and logging. Additionally, examples are provided to illustrate the application of these standards.
By following the coding standards outlined in this document, we ensure that our scripts and JSON files are of high quality, making our project more robust and easier to manage. Please refer to this guide whenever you create or update scripts and JSON files to maintain a high standard of code quality across the project. 📚🔍
Let's work together to keep our codebase clean, efficient, and maintainable! 💪🚀
## Getting Started
Before contributing, please ensure that you have the following setup:
1. **Visual Studio Code** (recommended for script development)
2. **Recommended VS Code Extensions:**
- [Shell Syntax](https://marketplace.visualstudio.com/items?itemName=bmalehorn.shell-syntax)
- [ShellCheck](https://marketplace.visualstudio.com/items?itemName=timonwong.shellcheck)
- [Shell Format](https://marketplace.visualstudio.com/items?itemName=foxundermoon.shell-format)
### Important Notes
- Use [AppName.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/docs/contribution/templates_ct/AppName.sh) and [AppName-install.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/docs/contribution/templates_install/AppName-install.sh) as templates when creating new scripts.
---
# 🚀 The Application Script (ct/AppName.sh)
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVE/blob/main/docs/contribution/templates_ct/AppName.md).
- These scripts are responsible for container creation, setting the necessary variables and handling the update of the application once installed.
---
# 🛠 The Installation Script (install/AppName-install.sh)
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVE/blob/main/docs/contribution/templates_install/AppName-install.md).
- These scripts are responsible for the installation of the application.
---
## 🚀 Building Your Own Scripts
Start with the [template script](https://github.com/community-scripts/ProxmoxVE/blob/main/docs/contribution/templates_install/AppName-install.sh)
---
## 🤝 Contribution Process
### 1. Fork the repository
Fork to your GitHub account
### 2. Clone your fork on your local environment
```bash
git clone https://github.com/yourUserName/ForkName
```
### 3. Create a new branch
```bash
git switch -c your-feature-branch
```
### 4. Run setup-fork.sh to auto-configure your fork
```bash
bash docs/contribution/setup-fork.sh --full
```
This script automatically:
- Detects your GitHub username
- Updates ALL curl URLs to point to your fork (for testing)
- Creates `.git-setup-info` with your config
- Backs up all modified files (\*.backup)
**IMPORTANT**: This modifies 600+ files! Use cherry-pick when submitting your PR (see below).
### 5. Commit ONLY your new application files
```bash
git commit -m "Your commit message"
```
### 5. Push to your fork
```bash
git push origin your-feature-branch
```
### 6. Cherry-Pick: Submit Only Your Files for PR
⚠️ **IMPORTANT**: setup-fork.sh modified 600+ files. You MUST only submit your 2 new files!
See [README.md - Cherry-Pick Guide](README.md#-cherry-pick-submitting-only-your-changes) for step-by-step instructions.
Quick version:
```bash
# Create clean branch from upstream
git fetch upstream
git checkout -b submit/myapp upstream/main
# Copy only your files
cp ../your-work-branch/ct/myapp.sh ct/myapp.sh
cp ../your-work-branch/install/myapp-install.sh install/myapp-install.sh
# Commit and verify
git add ct/myapp.sh install/myapp-install.sh
git commit -m "feat: add MyApp"
git diff upstream/main --name-only # Should show ONLY your 2 files
# Push and create PR
git push origin submit/myapp
```
### 7. Create a Pull Request
Open a Pull Request from `submit/myapp``community-scripts/ProxmoxVE/main`.
Verify the PR shows ONLY these 2 files:
- `ct/myapp.sh`
- `install/myapp-install.sh`
---
# 🛠️ Developer Mode & Debugging
When building or testing scripts, you can use the `dev_mode` variable to enable powerful debugging features. These flags can be combined (comma-separated).
**Usage**:
```bash
# Example: Run with trace and keep the container even if it fails
dev_mode="trace,keep" bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/myapp.sh)"
```
### Available Flags:
| Flag | Description |
| :--- | :--- |
| `trace` | Enables `set -x` for maximum verbosity during execution. |
| `keep` | Prevents the container from being deleted if the build fails. |
| `pause` | Pauses execution at key points (e.g., before customization). |
| `breakpoint` | Allows hardcoded `breakpoint` calls in scripts to drop to a shell. |
| `logs` | Saves detailed build logs to `/var/log/community-scripts/`. |
| `dryrun` | Bypasses actual container creation (limited support). |
| `motd` | Forces an update of the Message of the Day (MOTD). |
---
## 📚 Pages
- [CT Template: AppName.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/docs/contribution/templates_ct/AppName.sh)
- [Install Template: AppName-install.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/docs/contribution/templates_install/AppName-install.sh)
- [JSON Template: AppName.json](https://github.com/community-scripts/ProxmoxVE/blob/main/docs/contribution/templates_json/AppName.json) — metadata structure reference; submit via the website (Report issue on script page)

View File

@@ -0,0 +1,231 @@
# 🍴 Fork Setup Guide
**Just forked ProxmoxVE? Run this first!**
## Quick Start
```bash
# Clone your fork
git clone https://github.com/YOUR_USERNAME/ProxmoxVE.git
cd ProxmoxVE
# Run setup script (auto-detects your username from git)
bash docs/contribution/setup-fork.sh --full
```
That's it! ✅
---
## What Does It Do?
The `setup-fork.sh` script automatically:
1. **Detects** your GitHub username from git config
2. **Updates ALL hardcoded links** to point to your fork:
- Documentation links pointing to `community-scripts/ProxmoxVE`
- **Curl download URLs** in scripts (e.g., `curl ... github.com/community-scripts/ProxmoxVE/main/...`)
3. **Creates** `.git-setup-info` with your configuration details
4. **Backs up** all modified files (\*.backup for safety)
### Why Updating Curl Links Matters
Your scripts contain `curl` commands that download dependencies from GitHub (build.func, tools.func, etc.):
```bash
# First line of ct/myapp.sh
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
```
**WITHOUT setup-fork.sh:**
- Script URLs still point to `community-scripts/ProxmoxVE/main`
- If you test locally with `bash ct/myapp.sh`, you're testing local files, but the script's curl commands would download from **upstream** repo
- Your modifications aren't actually being tested via the curl commands! ❌
**AFTER setup-fork.sh:**
- Script URLs are updated to `YourUsername/ProxmoxVE/main`
- When you test via curl from GitHub: `bash -c "$(curl ... YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"`, it downloads from **your fork**
- The script's curl commands also point to your fork, so you're actually testing your changes! ✅
- ⏱️ **Important:** GitHub takes 10-30 seconds to recognize pushed files - wait before testing!
```bash
# Example: What setup-fork.sh changes
# BEFORE (points to upstream):
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# AFTER (points to your fork):
source <(curl -fsSL https://raw.githubusercontent.com/john/ProxmoxVE/main/misc/build.func)
```
---
## Usage
### Auto-Detect (Recommended)
```bash
bash docs/contribution/setup-fork.sh --full
```
Automatically reads your GitHub username from `git remote origin url`
### Specify Username
```bash
bash docs/contribution/setup-fork.sh --full john
```
Updates links to `github.com/john/ProxmoxVE`
### Custom Repository Name
```bash
bash docs/contribution/setup-fork.sh --full john my-fork
```
Updates links to `github.com/john/my-fork`
---
## What Gets Updated?
The script updates hardcoded links in these areas when using `--full`:
- `ct/`, `install/`, `vm/` scripts
- `misc/` function libraries
- `docs/` (including `docs/contribution/`)
- Code examples in documentation
---
## After Setup
1. **Review changes**
```bash
git diff docs/
```
2. **Read git workflow tips**
```bash
cat .git-setup-info
```
3. **Start contributing**
```bash
git checkout -b feature/my-app
# Make your changes...
git commit -m "feat: add my awesome app"
```
4. **Follow the guide**
```bash
cat docs/contribution/GUIDE.md
```
---
## Common Workflows
### Keep Your Fork Updated
```bash
# Add upstream if you haven't already
git remote add upstream https://github.com/community-scripts/ProxmoxVE.git
# Get latest from upstream
git fetch upstream
git rebase upstream/main
git push origin main
```
### Create a Feature Branch
```bash
git checkout -b feature/docker-improvements
# Make changes...
git push origin feature/docker-improvements
# Then create PR on GitHub
```
### Sync Before Contributing
```bash
git fetch upstream
git rebase upstream/main
git push -f origin main # Update your fork's main
git checkout -b feature/my-feature
```
---
## Troubleshooting
### "Git is not installed" or "not a git repository"
```bash
# Make sure you cloned the repo first
git clone https://github.com/YOUR_USERNAME/ProxmoxVE.git
cd ProxmoxVE
bash docs/contribution/setup-fork.sh --full
```
### "Could not auto-detect GitHub username"
```bash
# Your git origin URL isn't set up correctly
git remote -v
# Should show your fork URL, not community-scripts
# Fix it:
git remote set-url origin https://github.com/YOUR_USERNAME/ProxmoxVE.git
bash docs/contribution/setup-fork.sh --full
```
### "Permission denied"
```bash
# Make script executable
chmod +x docs/contribution/setup-fork.sh
bash docs/contribution/setup-fork.sh --full
```
### Reverted Changes by Accident?
```bash
# Backups are created automatically
git checkout docs/*.backup
# Or just re-run setup-fork.sh
bash docs/contribution/setup-fork.sh --full
```
---
## Next Steps
1. ✅ Run `bash docs/contribution/setup-fork.sh --full`
2. 📖 Read [docs/contribution/GUIDE.md](GUIDE.md)
3. 🍴 Choose your contribution path:
- **Containers** → [docs/ct/README.md](docs/ct/README.md)
- **Installation** → [docs/install/README.md](docs/install/README.md)
- **VMs** → [docs/vm/README.md](docs/vm/README.md)
- **Tools** → [docs/tools/README.md](docs/tools/README.md)
4. 💻 Create your feature branch and contribute!
---
## Questions?
- **Fork Setup Issues?** → See [Troubleshooting](#troubleshooting) above
- **How to Contribute?** → [docs/contribution/GUIDE.md](GUIDE.md)
- **Git Workflows?** → `cat .git-setup-info`
- **Project Structure?** → [docs/README.md](docs/README.md)
---
## Happy Contributing! 🚀

1077
docs/contribution/GUIDE.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,753 @@
# 🛠️ Helper Functions Reference
**Quick reference for all helper functions available in `tools.func`**
> These functions are automatically available in install scripts via `$FUNCTIONS_FILE_PATH`
---
## 📋 Table of Contents
- [Scripts to Watch](#scripts-to-watch)
- [Runtime & Language Setup](#runtime--language-setup)
- [Database Setup](#database-setup)
- [GitHub Release Helpers](#github-release-helpers)
- [Tools & Utilities](#tools--utilities)
- [SSL/TLS](#ssltls)
- [Utility Functions](#utility-functions)
- [Package Management](#package-management)
---
## 📚 Scripts to Watch
**Learn from real, well-implemented scripts. Each app requires TWO files that work together:**
| File | Location | Purpose |
| ------------------ | ---------------------------- | ------------------------------------------------------------------------ |
| **CT Script** | `ct/appname.sh` | Runs on **Proxmox host** - creates container, contains `update_script()` |
| **Install Script** | `install/appname-install.sh` | Runs **inside container** - installs and configures the app |
> ⚠️ **Both files are ALWAYS required!** The CT script calls the install script automatically during container creation.
Install scripts are **not** run directly by users; they are invoked by the CT script inside the container.
### Node.js + PostgreSQL
**Koel** - Music streaming with PHP + Node.js + PostgreSQL
| File | Link |
| ----------------- | -------------------------------------------------------- |
| CT (update logic) | [ct/koel.sh](../../ct/koel.sh) |
| Install | [install/koel-install.sh](../../install/koel-install.sh) |
**Actual Budget** - Finance app with npm global install
| File | Link |
| ----------------- | ------------------------------------------------------------------------ |
| CT (update logic) | [ct/actualbudget.sh](../../ct/actualbudget.sh) |
| Install | [install/actualbudget-install.sh](../../install/actualbudget-install.sh) |
### Python + uv
**MeTube** - YouTube downloader with Python uv + Node.js + Deno
| File | Link |
| ----------------- | ------------------------------------------------------------ |
| CT (update logic) | [ct/metube.sh](../../ct/metube.sh) |
| Install | [install/metube-install.sh](../../install/metube-install.sh) |
**Endurain** - Fitness tracker with Python uv + PostgreSQL/PostGIS
| File | Link |
| ----------------- | ---------------------------------------------------------------- |
| CT (update logic) | [ct/endurain.sh](../../ct/endurain.sh) |
| Install | [install/endurain-install.sh](../../install/endurain-install.sh) |
### Java + Gradle
**BookLore** - Book management with Java 21 + Gradle + MariaDB + Nginx
| File | Link |
| ----------------- | -------------------------------------------------------------- |
| CT (update logic) | [ct/booklore.sh](../../ct/booklore.sh) |
| Install | [install/booklore-install.sh](../../install/booklore-install.sh) |
### Pnpm + Meilisearch
**KaraKeep** - Bookmark manager with Pnpm + Meilisearch + Puppeteer
| File | Link |
| ----------------- | -------------------------------------------------------------- |
| CT (update logic) | [ct/karakeep.sh](../../ct/karakeep.sh) |
| Install | [install/karakeep-install.sh](../../install/karakeep-install.sh) |
### PHP + MariaDB/MySQL
**Wallabag** - Read-it-later with PHP + MariaDB + Redis + Nginx
| File | Link |
| ----------------- | ---------------------------------------------------------------- |
| CT (update logic) | [ct/wallabag.sh](../../ct/wallabag.sh) |
| Install | [install/wallabag-install.sh](../../install/wallabag-install.sh) |
**InvoiceNinja** - Invoicing with PHP + MariaDB + Supervisor
| File | Link |
| ----------------- | ------------------------------------------------------------------------ |
| CT (update logic) | [ct/invoiceninja.sh](../../ct/invoiceninja.sh) |
| Install | [install/invoiceninja-install.sh](../../install/invoiceninja-install.sh) |
**BookStack** - Wiki/Docs with PHP + MariaDB + Apache
| File | Link |
| ----------------- | ------------------------------------------------------------------ |
| CT (update logic) | [ct/bookstack.sh](../../ct/bookstack.sh) |
| Install | [install/bookstack-install.sh](../../install/bookstack-install.sh) |
### PHP + SQLite (Simple)
**Speedtest Tracker** - Speedtest with PHP + SQLite + Nginx
| File | Link |
| ----------------- | ---------------------------------------------------------------------------------- |
| CT (update logic) | [ct/speedtest-tracker.sh](../../ct/speedtest-tracker.sh) |
| Install | [install/speedtest-tracker-install.sh](../../install/speedtest-tracker-install.sh) |
---
## Runtime & Language Setup
### `setup_nodejs`
Install Node.js from NodeSource repository.
```bash
# Default (Node.js 24)
setup_nodejs
# Specific version
NODE_VERSION="20" setup_nodejs
NODE_VERSION="22" setup_nodejs
NODE_VERSION="24" setup_nodejs
```
### `setup_go`
Install Go programming language (latest stable).
```bash
setup_go
# Use in script
setup_go
cd /opt/myapp
$STD go build -o myapp .
```
### `setup_rust`
Install Rust via rustup.
```bash
setup_rust
# Use in script
setup_rust
source "$HOME/.cargo/env"
$STD cargo build --release
```
### `setup_uv`
Install Python uv package manager (fast pip/venv replacement).
```bash
# Default
setup_uv
# Install a specific Python version
PYTHON_VERSION="3.12" setup_uv
# Use in script
setup_uv
cd /opt/myapp
$STD uv sync --locked
```
### `setup_ruby`
Install Ruby from official repositories.
```bash
setup_ruby
```
### `setup_php`
Install PHP with configurable modules and FPM/Apache support.
```bash
# Basic PHP
setup_php
# Full configuration
PHP_VERSION="8.4" \
PHP_MODULE="mysqli,gd,curl,mbstring,xml,zip,ldap" \
PHP_FPM="YES" \
PHP_APACHE="YES" \
setup_php
```
**Environment Variables:**
| Variable | Default | Description |
| ------------- | ------- | ------------------------------- |
| `PHP_VERSION` | `8.4` | PHP version to install |
| `PHP_MODULE` | `""` | Comma-separated list of modules |
| `PHP_FPM` | `NO` | Install PHP-FPM |
| `PHP_APACHE` | `NO` | Install Apache module |
### `setup_composer`
Install PHP Composer package manager.
```bash
setup_php
setup_composer
# Use in script
$STD composer install --no-dev
```
### `setup_java`
Install Java (OpenJDK).
```bash
# Default (Java 21)
setup_java
# Specific version
JAVA_VERSION="17" setup_java
JAVA_VERSION="21" setup_java
```
---
## Database Setup
### `setup_mariadb`
Install MariaDB server.
```bash
setup_mariadb
```
### `setup_mariadb_db`
Create a MariaDB database and user. Sets `$MARIADB_DB_PASS` with the generated password.
```bash
setup_mariadb
MARIADB_DB_NAME="myapp_db" MARIADB_DB_USER="myapp_user" setup_mariadb_db
# After calling, these variables are available:
# $MARIADB_DB_NAME - Database name
# $MARIADB_DB_USER - Database user
# $MARIADB_DB_PASS - Generated password (saved to ~/[appname].creds)
```
### `setup_mysql`
Install MySQL server.
```bash
setup_mysql
```
### `setup_postgresql`
Install PostgreSQL server.
```bash
# Default (PostgreSQL 16)
setup_postgresql
# Specific version
PG_VERSION="16" setup_postgresql
PG_VERSION="16" setup_postgresql
```
### `setup_postgresql_db`
Create a PostgreSQL database and user. Sets `$PG_DB_PASS` with the generated password.
```bash
PG_VERSION="17" setup_postgresql
PG_DB_NAME="myapp_db" PG_DB_USER="myapp_user" setup_postgresql_db
# After calling, these variables are available:
# $PG_DB_NAME - Database name
# $PG_DB_USER - Database user
# $PG_DB_PASS - Generated password (saved to ~/[appname].creds)
```
### `setup_mongodb`
Install MongoDB server.
```bash
setup_mongodb
```
### `setup_clickhouse`
Install ClickHouse analytics database.
```bash
setup_clickhouse
```
---
## Advanced Repository Management
### `setup_deb822_repo`
The modern standard (Debian 12+) for adding external repositories. Automatically handles GPG keys and sources.
```bash
setup_deb822_repo \
"nodejs" \
"https://deb.nodesource.com/gpgkey/nodesource.gpg.key" \
"https://deb.nodesource.com/node_22.x" \
"bookworm" \
"main"
```
### `prepare_repository_setup`
A high-level helper that performs three critical tasks before adding a new repo:
1. Cleans up old repo files matching the names provided.
2. Removes old GPG keyrings from all standard locations.
3. Ensures APT is in a working state (fixes locks, runs update).
```bash
# Clean up old mysql/mariadb artifacts before setup
prepare_repository_setup "mariadb" "mysql"
```
### `cleanup_tool_keyrings`
Force-removes GPG keys for specific tools from `/usr/share/keyrings/`, `/etc/apt/keyrings/`, and `/etc/apt/trusted.gpg.d/`.
```bash
cleanup_tool_keyrings "docker" "kubernetes"
```
---
## GitHub Release Helpers
> **Note**: `fetch_and_deploy_gh_release` is the **preferred method** for downloading GitHub releases. It handles version tracking automatically. Only use `get_latest_github_release` if you need the version number separately.
### `fetch_and_deploy_gh_release`
**Primary method** for downloading and extracting GitHub releases. Handles version tracking automatically.
```bash
# Basic usage - downloads tarball to /opt/appname
fetch_and_deploy_gh_release "appname" "owner/repo"
# With explicit parameters
fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" "latest" "/opt/appname"
# Pre-built release with specific asset pattern
fetch_and_deploy_gh_release "koel" "koel/koel" "prebuild" "latest" "/opt/koel" "koel-*.tar.gz"
# Clean install (removes old directory first) - used in update_script
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo" "tarball" "latest" "/opt/appname"
```
**Parameters:**
| Parameter | Default | Description |
| --------------- | ------------- | ----------------------------------------------------------------- |
| `name` | required | App name (for version tracking) |
| `repo` | required | GitHub repo (`owner/repo`) |
| `type` | `tarball` | Release type: `tarball`, `zipball`, `prebuild`, `binary` |
| `version` | `latest` | Version tag or `latest` |
| `dest` | `/opt/[name]` | Destination directory |
| `asset_pattern` | `""` | For `prebuild`: glob pattern to match asset (e.g. `app-*.tar.gz`) |
**Environment Variables:**
| Variable | Description |
| ----------------- | ------------------------------------------------------------ |
| `CLEAN_INSTALL=1` | Remove destination directory before extracting (for updates) |
### `check_for_gh_release`
Check if a newer version is available. Returns 0 if update needed, 1 if already at latest. **Use in `update_script()` function.**
```bash
# In update_script() function in ct/appname.sh
if check_for_gh_release "appname" "owner/repo"; then
msg_info "Updating..."
# Stop services, backup, update, restore, start
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "appname" "owner/repo"
msg_ok "Updated successfully!"
fi
```
### `get_latest_github_release`
Get the latest release version from a GitHub repository. **Only use if you need the version number separately** (e.g., for manual download or display).
```bash
RELEASE=$(get_latest_github_release "owner/repo")
echo "Latest version: $RELEASE"
```
---
## Tools & Utilities
### `setup_meilisearch`
Install Meilisearch, a lightning-fast search engine.
```bash
setup_meilisearch
# Use in script
$STD php artisan scout:sync-index-settings
```
### `setup_yq`
Install yq YAML processor.
```bash
setup_yq
# Use in script
yq '.server.port = 8080' -i config.yaml
````
### `setup_ffmpeg`
Install FFmpeg with common codecs.
```bash
setup_ffmpeg
```
### `setup_hwaccel`
Setup GPU hardware acceleration (Intel/AMD/NVIDIA).
```bash
# Only runs if GPU passthrough is detected (/dev/dri, /dev/nvidia0, /dev/kfd)
setup_hwaccel
```
### `setup_imagemagick`
Install ImageMagick 7 from source.
```bash
setup_imagemagick
```
### `setup_docker`
Install Docker Engine.
```bash
setup_docker
```
### `setup_adminer`
Install Adminer for database management.
```bash
setup_mariadb
setup_adminer
# Access at http://IP/adminer
```
---
## SSL/TLS
### `create_self_signed_cert`
Create a self-signed SSL certificate.
```bash
create_self_signed_cert
# Creates files at:
# /etc/ssl/[appname]/[appname].key
# /etc/ssl/[appname]/[appname].crt
```
---
## Utility Functions
### `verify_tool_version`
Validate that the installed major version matches the expected version. Useful during upgrades or troubleshooting.
```bash
# Verify Node.js is version 22
verify_tool_version "nodejs" "22" "$(node -v | grep -oP '^v\K[0-9]+')"
```
### `get_lxc_ip`
Set the `$LOCAL_IP` variable with the container's IP address.
```bash
get_lxc_ip
echo "Container IP: $LOCAL_IP"
# Use in config files
sed -i "s/localhost/$LOCAL_IP/g" /opt/myapp/config.yaml
```
### `ensure_dependencies`
Ensure packages are installed (installs if missing).
```bash
ensure_dependencies "jq" "unzip" "curl"
```
### `msg_info` / `msg_ok` / `msg_error` / `msg_warn`
Display formatted messages.
```bash
msg_info "Installing application..."
# ... do work ...
msg_ok "Installation complete"
msg_warn "Optional feature not available"
msg_error "Installation failed"
```
---
## Package Management
### `cleanup_lxc`
Final cleanup function - call at end of install script.
```bash
# At the end of your install script
motd_ssh
customize
cleanup_lxc # Handles autoremove, autoclean, cache cleanup
```
### `install_packages_with_retry`
Install packages with automatic retry on failure.
```bash
install_packages_with_retry "package1" "package2" "package3"
```
### `prepare_repository_setup`
Prepare system for adding new repositories (cleanup old repos, keyrings).
```bash
prepare_repository_setup "mariadb" "mysql"
```
---
## Complete Examples
### Example 1: Node.js App with PostgreSQL (install script)
```bash
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: YourUsername
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/example/myapp
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y nginx
msg_ok "Installed Dependencies"
# Setup runtimes and databases FIRST
NODE_VERSION="22" setup_nodejs
PG_VERSION="16" setup_postgresql
PG_DB_NAME="myapp" PG_DB_USER="myapp" setup_postgresql_db
get_lxc_ip
# Download app using fetch_and_deploy (handles version tracking)
fetch_and_deploy_gh_release "myapp" "example/myapp" "tarball" "latest" "/opt/myapp"
msg_info "Setting up MyApp"
cd /opt/myapp
$STD npm ci --production
msg_ok "Setup MyApp"
msg_info "Configuring MyApp"
cat <<EOF >/opt/myapp/.env
DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost/${PG_DB_NAME}
HOST=${LOCAL_IP}
PORT=3000
EOF
msg_ok "Configured MyApp"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/myapp.service
[Unit]
Description=MyApp
After=network.target postgresql.service
[Service]
Type=simple
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/node /opt/myapp/server.js
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now myapp
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc
```
### Example 2: Matching Container Script (ct script)
```bash
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: YourUsername
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/example/myapp
APP="MyApp"
var_tags="${var_tags:-webapp}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-6}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/myapp ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
# check_for_gh_release returns true if update available
if check_for_gh_release "myapp" "example/myapp"; then
msg_info "Stopping Service"
systemctl stop myapp
msg_ok "Stopped Service"
msg_info "Creating Backup"
cp /opt/myapp/.env /tmp/myapp_env.bak
msg_ok "Created Backup"
# CLEAN_INSTALL=1 removes old dir before extracting
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "myapp" "example/myapp" "tarball" "latest" "/opt/myapp"
msg_info "Restoring Config & Rebuilding"
cp /tmp/myapp_env.bak /opt/myapp/.env
rm /tmp/myapp_env.bak
cd /opt/myapp
$STD npm ci --production
msg_ok "Restored Config & Rebuilt"
msg_info "Starting Service"
systemctl start myapp
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
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} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
```
### Example 3: PHP App with MariaDB (install script)
```bash
#!/usr/bin/env bash
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y nginx
msg_ok "Installed Dependencies"
# PHP with FPM and common modules
PHP_VERSION="8.4" PHP_FPM="YES" PHP_MODULE="bcmath,curl,gd,intl,mbstring,mysql,xml,zip" setup_php
setup_composer
setup_mariadb
MARIADB_DB_NAME="myapp" MARIADB_DB_USER="myapp" setup_mariadb_db
get_lxc_ip
# Download pre-built release (with asset pattern)
fetch_and_deploy_gh_release "myapp" "example/myapp" "prebuild" "latest" "/opt/myapp" "myapp-*.tar.gz"
msg_info "Configuring MyApp"
cd /opt/myapp
cp .env.example .env
sed -i "s|APP_URL=.*|APP_URL=http://${LOCAL_IP}|" .env
sed -i "s|DB_DATABASE=.*|DB_DATABASE=${MARIADB_DB_NAME}|" .env
sed -i "s|DB_USERNAME=.*|DB_USERNAME=${MARIADB_DB_USER}|" .env
sed -i "s|DB_PASSWORD=.*|DB_PASSWORD=${MARIADB_DB_PASS}|" .env
$STD composer install --no-dev --no-interaction
$STD php artisan key:generate --force
$STD php artisan migrate --force
chown -R www-data:www-data /opt/myapp
msg_ok "Configured MyApp"
# ... nginx config, service creation ...
motd_ssh
customize
cleanup_lxc
```

654
docs/contribution/README.md Normal file
View File

@@ -0,0 +1,654 @@
# 🤝 Contributing to ProxmoxVE
Complete guide to contributing to the ProxmoxVE project - from your first fork to submitting your pull request.
---
## 📋 Table of Contents
- [Quick Start](#quick-start)
- [Setting Up Your Fork](#setting-up-your-fork)
- [Coding Standards](#coding-standards)
- [Code Audit](#code-audit)
- [Guides & Resources](#guides--resources)
- [FAQ](#faq)
---
## 🚀 Quick Start
### 60 Seconds to Contributing (Development)
When developing and testing **in your fork**:
```bash
# 1. Fork on GitHub
# Visit: https://github.com/community-scripts/ProxmoxVE → Fork (top right)
# 2. Clone your fork
git clone https://github.com/YOUR_USERNAME/ProxmoxVE.git
cd ProxmoxVE
# 3. Auto-configure your fork (IMPORTANT - updates all links!)
bash docs/contribution/setup-fork.sh --full
# 4. Create a feature branch
git checkout -b feature/my-awesome-app
# 5. Read the guides
cat docs/README.md # Documentation overview
cat docs/ct/DETAILED_GUIDE.md # For container scripts
cat docs/install/DETAILED_GUIDE.md # For install scripts
# 6. Create your contribution
cp docs/contribution/templates_ct/AppName.sh ct/myapp.sh
cp docs/contribution/templates_install/AppName-install.sh install/myapp-install.sh
# ... edit files ...
# 7. Push to your fork and test via GitHub
git push origin feature/my-awesome-app
bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"
# ⏱️ GitHub may take 10-30 seconds to update files - be patient!
# 8. Request website metadata via the website
# Go to the script's page on the website, use the "Report issue" button — it will guide you.
# 9. No direct install-script test
# Install scripts are executed by the CT script inside the container
# 10. Commit ONLY your new files (see Cherry-Pick section below!)
git add ct/myapp.sh install/myapp-install.sh
git commit -m "feat: add MyApp container and install scripts"
git push origin feature/my-awesome-app
# 11. Create Pull Request on GitHub
```
⚠️ **IMPORTANT: After setup-fork.sh, many files are modified!**
See the **Cherry-Pick: Submitting Only Your Changes** section below to learn how to push ONLY your 2 files instead of 600+ modified files!
### How Users Run Scripts (After Merged)
Once your script is merged to the main repository, users download and run it from GitHub like this:
```bash
# ✅ Users run from GitHub (normal usage after PR merged)
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/myapp.sh)"
# Install scripts are called by the CT script and are not run directly by users
```
### Development vs. Production Execution
**During Development (you, in your fork):**
```bash
# You MUST test via curl from your GitHub fork (not local files!)
bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"
# The script's curl commands are updated by setup-fork.sh to point to YOUR fork
# This ensures you're testing your actual changes
# ⏱️ Wait 10-30 seconds after pushing - GitHub updates slowly
```
**After Merge (users, from GitHub):**
```bash
# Users download the script from upstream via curl
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/myapp.sh)"
# The script's curl commands now point back to upstream (community-scripts)
# This is the stable, tested version
```
**Summary:**
- **Development**: Push to fork, test via curl → setup-fork.sh changes curl URLs to your fork
- **Production**: curl | bash from upstream → curl URLs point to community-scripts repo
---
## 🍴 Setting Up Your Fork
### Automatic Setup (Recommended)
When you clone your fork, run the setup script to automatically configure everything:
```bash
bash docs/contribution/setup-fork.sh --full
```
**What it does:**
- Auto-detects your GitHub username from git config
- Auto-detects your fork repository name
- Updates **ALL** hardcoded links to point to your fork instead of the main repo (`--full`)
- Creates `.git-setup-info` with your configuration
- Allows you to develop and test independently in your fork
**Why this matters:**
Without running this script, all links in your fork will still point to the upstream repository (community-scripts). This is a problem when testing because:
- Installation links will pull from upstream, not your fork
- Updates will target the wrong repository
- Your contributions won't be properly tested
**After running setup-fork.sh:**
Your fork is fully configured and ready to develop. You can:
- Push changes to your fork
- Test via curl: `bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"`
- All links will reference your fork for development
- ⏱️ Wait 10-30 seconds after pushing - GitHub takes time to update
- Commit and push with confidence
- Create a PR to merge into upstream
**See**: [FORK_SETUP.md](FORK_SETUP.md) for detailed instructions
### Manual Setup
If the script doesn't work, manually configure:
```bash
# Set git user
git config user.name "Your Name"
git config user.email "your.email@example.com"
# Add upstream remote for syncing with main repo
git remote add upstream https://github.com/community-scripts/ProxmoxVE.git
# Verify remotes
git remote -v
# Should show: origin (your fork) and upstream (main repo)
```
---
## 📖 Coding Standards
All scripts and configurations must follow our coding standards to ensure consistency and quality.
### Available Guides
- **[CONTRIBUTING.md](CONTRIBUTING.md)** - Essential coding standards and best practices
- **[CODE-AUDIT.md](CODE-AUDIT.md)** - Code review checklist and audit procedures
- **[GUIDE.md](GUIDE.md)** - Comprehensive contribution guide
- **[HELPER_FUNCTIONS.md](HELPER_FUNCTIONS.md)** - Reference for all tools.func helper functions
- **Container Scripts** - `/ct/` templates and guidelines
- **Install Scripts** - `/install/` templates and guidelines
- **Website metadata** Request via the website (Report issue on the script page); see [templates_json/AppName.md](templates_json/AppName.md)
### Quick Checklist
- ✅ Use `/ct/example.sh` as template for container scripts
- ✅ Use `/install/example-install.sh` as template for install scripts
- ✅ Follow naming conventions: `appname.sh` and `appname-install.sh`
- ✅ Include proper shebang: `#!/usr/bin/env bash`
- ✅ Add copyright header with author
- ✅ Handle errors properly with `msg_error`, `msg_ok`, etc.
- ✅ Test before submitting PR (via curl from your fork, not local bash)
- ✅ Update documentation if needed
---
## 🔍 Code Audit
Before submitting a pull request, ensure your code passes our audit:
**See**: [CODE_AUDIT.md](CODE_AUDIT.md) for complete audit checklist
Key points:
- Code consistency with existing scripts
- Proper error handling
- Correct variable naming
- Adequate comments and documentation
- Security best practices
---
## 🍒 Cherry-Pick: Submitting Only Your Changes
**Problem**: `setup-fork.sh` modifies 600+ files to update links. You don't want to submit all of those changes - only your new 2 files!
**Solution**: Use git cherry-pick to select only YOUR files.
### Step-by-Step Cherry-Pick Guide
#### 1. Check what changed
```bash
# See all modified files
git status
# Verify your files are there
git status | grep -E "ct/myapp|install/myapp"
```
#### 2. Create a clean feature branch for submission
```bash
# Go back to upstream main (clean slate)
git fetch upstream
git checkout -b submit/myapp upstream/main
# Don't use your modified main branch!
```
#### 3. Cherry-pick ONLY your files
Cherry-picking extracts specific changes from commits:
```bash
# Option A: Cherry-pick commits that added your files
# (if you committed your files separately)
git cherry-pick <commit-hash-of-your-files>
# Option B: Manually copy and commit only your files
# From your work branch, get the file contents
git show feature/my-awesome-app:ct/myapp.sh > /tmp/myapp.sh
git show feature/my-awesome-app:install/myapp-install.sh > /tmp/myapp-install.sh
# Add them to the clean branch
cp /tmp/myapp.sh ct/myapp.sh
cp /tmp/myapp-install.sh install/myapp-install.sh
# Commit
git add ct/myapp.sh install/myapp-install.sh
git commit -m "feat: add MyApp"
```
#### 4. Verify only your files are in the PR
```bash
# Check git diff against upstream
git diff upstream/main --name-only
# Should show ONLY:
# ct/myapp.sh
# install/myapp-install.sh
```
#### 5. Push and create PR
```bash
# Push your clean submission branch
git push origin submit/myapp
# Create PR on GitHub from: submit/myapp → main
```
### Why This Matters
- ✅ Clean PR with only your changes
- ✅ Easier for maintainers to review
- ✅ Faster merge without conflicts
- ❌ Without cherry-pick: PR has 600+ file changes (won't merge!)
### If You Made a Mistake
```bash
# Delete the messy branch
git branch -D submit/myapp
# Go back to clean branch
git checkout -b submit/myapp upstream/main
# Try cherry-picking again
```
---
If you're using **Visual Studio Code** with an AI assistant, you can leverage our detailed guidelines to generate high-quality contributions automatically.
### How to Use AI Assistance
1. **Open the AI Guidelines**
```
docs/contribution/AI.md
```
This file contains all requirements, patterns, and examples for writing proper scripts.
2. **Prepare Your Information**
Before asking the AI to generate code, gather:
- **Repository URL**: e.g., `https://github.com/owner/myapp`
- **Dockerfile/Script**: Paste the app's installation instructions (if available)
- **Dependencies**: What packages does it need? (Node, Python, Java, PostgreSQL, etc.)
- **Ports**: What port does it listen on? (e.g., 3000, 8080, 5000)
- **Configuration**: Any environment variables or config files?
3. **Tell the AI Assistant**
Share with the AI:
- The repository URL
- The Dockerfile or install instructions
- Link to [docs/contribution/AI.md](AI.md) with instructions to follow
**Example prompt:**
```
I want to contribute a container script for MyApp to ProxmoxVE.
Repository: https://github.com/owner/myapp
Here's the Dockerfile:
[paste Dockerfile content]
Please follow the guidelines in docs/contribution/AI.md to create:
1. ct/myapp.sh (container script)
2. install/myapp-install.sh (installation script)
Website listing/metadata is requested separately via the website (Report issue on the script page).
```
4. **AI Will Generate**
The AI will produce scripts that:
- Follow all ProxmoxVE patterns and conventions
- Use helper functions from `tools.func` correctly
- Include proper error handling and messages
- Have correct update mechanisms
- Are ready to submit as a PR
Website listing/metadata is requested separately via the website (Report issue on the script page).
### Key Points for AI Assistants
- **Templates Location**: `docs/contribution/templates_ct/AppName.sh`, `templates_install/`, `templates_json/`
- **Guidelines**: Must follow `docs/contribution/AI.md` exactly
- **Helper Functions**: Use only functions from `misc/tools.func` - never write custom ones
- **Testing**: Always test before submission via curl from your fork
```bash
bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"
# Wait 10-30 seconds after pushing changes
```
- **No Docker**: Container scripts must be bare-metal, not Docker-based
### Benefits
- **Speed**: AI generates boilerplate in seconds
- **Consistency**: Follows same patterns as 200+ existing scripts
- **Quality**: Less bugs and more maintainable code
- **Learning**: See how your app should be structured
---
### Documentation
- **[docs/README.md](../README.md)** - Main documentation hub
- **[docs/ct/README.md](../ct/README.md)** - Container scripts overview
- **[docs/install/README.md](../install/README.md)** - Installation scripts overview
- **[docs/ct/DETAILED_GUIDE.md](../ct/DETAILED_GUIDE.md)** - Complete ct/ script reference
- **[docs/install/DETAILED_GUIDE.md](../install/DETAILED_GUIDE.md)** - Complete install/ script reference
- **[docs/TECHNICAL_REFERENCE.md](../TECHNICAL_REFERENCE.md)** - Architecture deep-dive
- **[docs/EXIT_CODES.md](../EXIT_CODES.md)** - Exit codes reference
- **[docs/DEV_MODE.md](../DEV_MODE.md)** - Debugging guide
### Community Guides
See [USER_SUBMITTED_GUIDES.md](USER_SUBMITTED_GUIDES.md) for excellent community-written guides:
- Home Assistant installation and configuration
- Frigate setup on Proxmox
- Docker and Portainer installation
- Database setup and optimization
- And many more!
### Templates
Use these templates when creating new scripts:
```bash
# Container script template
cp docs/contribution/templates_ct/AppName.sh ct/my-app.sh
# Installation script template
cp docs/contribution/templates_install/AppName-install.sh install/my-app-install.sh
```
For website metadata (description, logo, etc.), use the Report issue button on the script's page on the website.
**Template Features:**
- Updated to match current codebase patterns
- Includes all available helper functions from `tools.func`
- Examples for Node.js, Python, PHP, Go applications
- Database setup examples (MariaDB, PostgreSQL)
- Proper service creation and cleanup
---
## 🔄 Git Workflow
### Keep Your Fork Updated
```bash
# Fetch latest from upstream
git fetch upstream
# Rebase your work on latest main
git rebase upstream/main
# Push to your fork
git push -f origin main
```
### Create Feature Branch
```bash
# Create and switch to new branch
git checkout -b feature/my-feature
# Make changes...
git add .
git commit -m "feat: description of changes"
# Push to your fork
git push origin feature/my-feature
# Create Pull Request on GitHub
```
### Before Submitting PR
1. **Sync with upstream**
```bash
git fetch upstream
git rebase upstream/main
```
2. **Test your changes** (via curl from your fork)
```bash
bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/my-app.sh)"
# Follow prompts and test the container
# ⏱️ Wait 10-30 seconds after pushing - GitHub takes time to update
```
3. **Check code standards**
- [ ] Follows template structure
- [ ] Proper error handling
- [ ] Documentation updated (if needed)
- [ ] No hardcoded values
- [ ] Version tracking implemented
4. **Push final changes**
```bash
git push origin feature/my-feature
```
---
## 📋 Pull Request Checklist
Before opening a PR:
- [ ] Code follows coding standards (see CONTRIBUTING.md)
- [ ] All templates used correctly
- [ ] Tested on Proxmox VE
- [ ] Error handling implemented
- [ ] Documentation updated (if applicable)
- [ ] No merge conflicts
- [ ] Synced with upstream/main
- [ ] Clear PR title and description
---
## ❓ FAQ
### ❌ Why can't I test with `bash ct/myapp.sh` locally?
You might try:
```bash
# ❌ WRONG - This won't test your actual changes!
bash ct/myapp.sh
./ct/myapp.sh
sh ct/myapp.sh
```
**Why this fails:**
- `bash ct/myapp.sh` uses the LOCAL clone file
- The LOCAL file doesn't execute the curl commands - it's already on disk
- The curl URLs INSIDE the script are modified by setup-fork.sh, but they're not executed
- So you can't verify if your curl URLs actually work
- Users will get the curl URL version (which may be broken)
**Solution:** Always test via curl from GitHub:
```bash
# ✅ CORRECT - Tests the actual GitHub URLs
bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"
```
### ❓ How do I test my changes?
You **cannot** test locally with `bash ct/myapp.sh` from your cloned directory!
You **must** push to GitHub and test via curl from your fork:
```bash
# 1. Push your changes to your fork
git push origin feature/my-awesome-app
# 2. Test via curl (this loads the script from GitHub, not local files)
bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/my-app.sh)"
# 3. For verbose/debug output, pass environment variables
VERBOSE=yes bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/my-app.sh)"
DEV_MODE_LOGS=true bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/my-app.sh)"
```
**Why?**
- Local `bash ct/myapp.sh` uses local files from your clone
- But the script's INTERNAL curl commands have been modified by setup-fork.sh to point to your fork
- This discrepancy means you're not actually testing the curl URLs
- Testing via curl ensures the script downloads from YOUR fork GitHub URLs
- ⏱️ **Important:** GitHub takes 10-30 seconds to recognize newly pushed files. Wait before testing!
**What if local bash worked?**
You'd be testing local files only, not the actual GitHub URLs that users will download. This means broken curl links wouldn't be caught during testing.
### What if my PR has conflicts?
```bash
# Sync with upstream main repository
git fetch upstream
git rebase upstream/main
# Resolve conflicts in your editor
git add .
git rebase --continue
git push -f origin your-branch
```
### How do I keep my fork updated?
Two ways:
**Option 1: Run setup script again**
```bash
bash docs/contribution/setup-fork.sh --full
```
**Option 2: Manual sync**
```bash
git fetch upstream
git rebase upstream/main
git push -f origin main
```
### Where do I ask questions?
- **GitHub Issues**: For bugs and feature requests
- **GitHub Discussions**: For general questions and ideas
- **Discord**: Community-scripts server for real-time chat
---
## 🎓 Learning Resources
### For First-Time Contributors
1. Read: [docs/README.md](../README.md) - Documentation overview
2. Read: [CONTRIBUTING.md](CONTRIBUTING.md) - Essential coding standards
3. Choose your path:
- Containers → [docs/ct/DETAILED_GUIDE.md](../ct/DETAILED_GUIDE.md)
- Installation → [docs/install/DETAILED_GUIDE.md](../install/DETAILED_GUIDE.md)
4. Study existing scripts in same category
5. Create your contribution
### For Experienced Developers
1. Review [CONTRIBUTING.md](CONTRIBUTING.md) - Coding standards
2. Review [CODE_AUDIT.md](CODE_AUDIT.md) - Audit checklist
3. Check templates in `/docs/contribution/templates_*/`
4. Use AI assistants with [AI.md](AI.md) for code generation
5. Submit PR with confidence
### For Using AI Assistants
See "Using AI Assistants" section above for:
- How to structure prompts
- What information to provide
- How to validate AI output
---
## 🚀 Ready to Contribute?
1. **Fork** the repository
2. **Clone** your fork and **setup** with `bash docs/contribution/setup-fork.sh --full`
3. **Choose** your contribution type (container, installation, tools, etc.)
4. **Read** the appropriate detailed guide
5. **Create** your feature branch
6. **Develop** and **test** your changes
7. **Commit** with clear messages
8. **Push** to your fork
9. **Create** Pull Request
---
## 📞 Contact & Support
- **GitHub**: [community-scripts/ProxmoxVE](https://github.com/community-scripts/ProxmoxVE)
- **Issues**: [GitHub Issues](https://github.com/community-scripts/ProxmoxVE/issues)
- **Discussions**: [GitHub Discussions](https://github.com/community-scripts/ProxmoxVE/discussions)
- **Discord**: [Join Server](https://discord.gg/UHrpNWGwkH)
---
**Thank you for contributing to ProxmoxVE!** 🙏
Your efforts help make Proxmox VE automation accessible to everyone. Happy coding! 🚀

View File

@@ -0,0 +1,336 @@
#!/bin/bash
################################################################################
# ProxmoxVE Fork Setup Script
#
# Automatically configures documentation and scripts for your fork
# Detects your GitHub username and repository from git config
# Updates all hardcoded links to point to your fork
#
# Usage:
# ./setup-fork.sh # Auto-detect from git config (updates misc/ only)
# ./setup-fork.sh YOUR_USERNAME # Specify username (updates misc/ only)
# ./setup-fork.sh YOUR_USERNAME REPO_NAME # Specify both (updates misc/ only)
# ./setup-fork.sh --full # Update all files including ct/, install/, vm/, etc.
#
# Examples:
# ./setup-fork.sh john # Uses john/ProxmoxVE, updates misc/ only
# ./setup-fork.sh john my-fork # Uses john/my-fork, updates misc/ only
# ./setup-fork.sh --full # Auto-detect + update all files
################################################################################
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Default values
REPO_NAME="ProxmoxVE"
USERNAME=""
AUTO_DETECT=true
UPDATE_ALL=false
################################################################################
# FUNCTIONS
################################################################################
print_header() {
echo -e "\n${BLUE}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}${NC} ProxmoxVE Fork Setup Script"
echo -e "${BLUE}${NC} Configuring for your fork..."
echo -e "${BLUE}╚════════════════════════════════════════════════════════════╝${NC}\n"
}
print_info() {
echo -e "${BLUE}${NC} $1"
}
print_success() {
echo -e "${GREEN}${NC} $1"
}
print_warning() {
echo -e "${YELLOW}${NC} $1"
}
print_error() {
echo -e "${RED}${NC} $1"
}
# Detect username from git remote
detect_username() {
local remote_url
# Try to get from origin
if ! remote_url=$(git config --get remote.origin.url 2>/dev/null); then
return 1
fi
# Extract username from SSH or HTTPS URL
if [[ $remote_url =~ git@github.com:([^/]+) ]]; then
echo "${BASH_REMATCH[1]}"
elif [[ $remote_url =~ github.com/([^/]+) ]]; then
echo "${BASH_REMATCH[1]}"
else
return 1
fi
}
# Detect repo name from git remote
detect_repo_name() {
local remote_url
if ! remote_url=$(git config --get remote.origin.url 2>/dev/null); then
return 1
fi
# Extract repo name (remove .git if present)
if [[ $remote_url =~ /([^/]+?)(.git)?$ ]]; then
local repo="${BASH_REMATCH[1]}"
echo "${repo%.git}"
else
return 1
fi
}
# Ask user for confirmation
confirm() {
local prompt="$1"
local response
echo -ne "${YELLOW}${prompt} (y/n)${NC} "
read -r response
[[ $response =~ ^[Yy]$ ]]
}
# Update links in files
update_links() {
local old_repo="community-scripts"
local old_name="ProxmoxVE"
local new_owner="$1"
local new_repo="$2"
local files_updated=0
print_info "Scanning for hardcoded links..."
# Change to repo root
local repo_root=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
# Determine search path
local search_path="$repo_root/misc"
if [[ "$UPDATE_ALL" == "true" ]]; then
search_path="$repo_root"
print_info "Searching all files (--full mode)"
else
print_info "Searching misc/ directory only (core functions)"
fi
echo ""
# Find all files containing the old repo reference
while IFS= read -r file; do
# Count occurrences
local count=$(grep -E -c "(github.com|githubusercontent.com)/$old_repo/$old_name" "$file" 2>/dev/null || echo 0)
if [[ $count -gt 0 ]]; then
# Backup original
cp "$file" "$file.backup"
# Replace links - use different sed syntax for BSD/macOS vs GNU sed
if sed --version &>/dev/null 2>&1; then
# GNU sed
sed -E -i "s@(github.com|githubusercontent.com)/$old_repo/$old_name@\\1/$new_owner/$new_repo@g" "$file"
else
# BSD sed (macOS)
sed -E -i '' "s@(github.com|githubusercontent.com)/$old_repo/$old_name@\\1/$new_owner/$new_repo@g" "$file"
fi
((files_updated++))
print_success "Updated $file ($count links)"
fi
done < <(find "$search_path" -type f \( -name "*.md" -o -name "*.sh" -o -name "*.func" -o -name "*.json" \) -not -path "*/.git/*" 2>/dev/null | xargs grep -E -l "(github.com|githubusercontent.com)/$old_repo/$old_name" 2>/dev/null)
return $files_updated
}
# Create user git config setup info
create_git_setup_info() {
local username="$1"
cat >.git-setup-info <<'EOF'
# Git Configuration for ProxmoxVE Development
## Recommended Git Configuration
### Set up remotes for easy syncing with upstream:
```bash
# View your current remotes
git remote -v
# If you don't have 'upstream' configured, add it:
git remote add upstream https://github.com/community-scripts/ProxmoxVE.git
# Verify both remotes exist:
git remote -v
# Should show:
# origin https://github.com/YOUR_USERNAME/ProxmoxVE.git (fetch)
# origin https://github.com/YOUR_USERNAME/ProxmoxVE.git (push)
# upstream https://github.com/community-scripts/ProxmoxVE.git (fetch)
# upstream https://github.com/community-scripts/ProxmoxVE.git (push)
```
### Configure Git User (if not done globally)
```bash
git config user.name "Your Name"
git config user.email "your.email@example.com"
# Or configure globally:
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
```
### Useful Git Workflows
**Keep your fork up-to-date:**
```bash
git fetch upstream
git rebase upstream/main
git push origin main
```
**Create feature branch:**
```bash
git checkout -b feature/my-awesome-app
# Make changes...
git commit -m "feat: add my awesome app"
git push origin feature/my-awesome-app
```
**Pull latest from upstream:**
```bash
git fetch upstream
git merge upstream/main
```
---
For more help, see: docs/contribution/README.md
EOF
print_success "Created .git-setup-info file"
}
################################################################################
# MAIN LOGIC
################################################################################
print_header
# Parse command line arguments
if [[ $# -gt 0 ]]; then
# Check for --full flag
if [[ "$1" == "--full" ]]; then
UPDATE_ALL=true
shift # Remove --full from arguments
fi
# Process remaining arguments
if [[ $# -gt 0 ]]; then
USERNAME="$1"
AUTO_DETECT=false
if [[ $# -gt 1 ]]; then
REPO_NAME="$2"
fi
fi
fi
# Try auto-detection
if [[ -z "$USERNAME" ]]; then
if username=$(detect_username); then
USERNAME="$username"
print_success "Detected GitHub username: $USERNAME"
else
print_error "Could not auto-detect GitHub username from git config"
echo -e "${YELLOW}Please run:${NC}"
echo " ./setup-fork.sh YOUR_USERNAME"
exit 1
fi
fi
# Auto-detect repo name if needed
if repo_name=$(detect_repo_name); then
REPO_NAME="$repo_name"
if [[ "$REPO_NAME" != "ProxmoxVE" ]]; then
print_info "Detected custom repo name: $REPO_NAME"
else
print_success "Using default repo name: ProxmoxVE"
fi
fi
# Validate inputs
if [[ -z "$USERNAME" ]]; then
print_error "Username cannot be empty"
exit 1
fi
if [[ -z "$REPO_NAME" ]]; then
print_error "Repository name cannot be empty"
exit 1
fi
# Show what we'll do
echo -e "${BLUE}Configuration Summary:${NC}"
echo " Repository URL: https://github.com/$USERNAME/$REPO_NAME"
if [[ "$UPDATE_ALL" == "true" ]]; then
echo " Files to update: ALL files (ct/, install/, vm/, misc/, docs/, etc.)"
else
echo " Files to update: misc/ directory only (core functions)"
fi
echo ""
# Ask for confirmation
if ! confirm "Apply these changes?"; then
print_warning "Setup cancelled"
exit 0
fi
echo ""
# Update all links
if update_links "$USERNAME" "$REPO_NAME"; then
links_changed=$?
print_success "Updated $links_changed files"
else
print_warning "No links needed updating or some files not found"
fi
# Create git setup info file
create_git_setup_info "$USERNAME"
# Final summary
echo ""
echo -e "${GREEN}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}${NC} Fork Setup Complete! ${GREEN}${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════════╝${NC}"
echo ""
print_success "All documentation links updated to point to your fork"
print_info "Your fork: https://github.com/$USERNAME/$REPO_NAME"
print_info "Upstream: https://github.com/community-scripts/ProxmoxVE"
echo ""
echo -e "${BLUE}Next Steps:${NC}"
echo " 1. Review the changes: git diff"
echo " 2. Check .git-setup-info for recommended git workflow"
echo " 3. Start developing: git checkout -b feature/my-app"
echo " 4. Read: docs/contribution/README.md"
echo ""
print_success "Happy contributing! 🚀"

View File

@@ -0,0 +1,278 @@
# CT Container Scripts - Quick Reference
> [!WARNING]
> **This is legacy documentation.** Refer to the **modern template** at [templates_ct/AppName.sh](AppName.sh) for best practices.
>
> Current templates use:
>
> - `tools.func` helpers instead of manual patterns
> - `check_for_gh_release` and `fetch_and_deploy_gh_release` from build.func
> - Automatic setup-fork.sh configuration
---
## Before Creating a Script
1. **Fork & Clone:**
```bash
git clone https://github.com/YOUR_USERNAME/ProxmoxVE.git
cd ProxmoxVE
```
2. **Run setup-fork.sh** (updates all curl URLs to your fork):
```bash
bash docs/contribution/setup-fork.sh
```
3. **Copy the Modern Template:**
```bash
cp templates_ct/AppName.sh ct/MyApp.sh
# Edit ct/MyApp.sh with your app details
```
4. **Test Your Script (via GitHub):**
⚠️ **Important:** You must push to GitHub and test via curl, not `bash ct/MyApp.sh`!
```bash
# Push your changes to your fork first
git push origin feature/my-awesome-app
# Then test via curl (this loads from YOUR fork, not local files)
bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/MyApp.sh)"
```
> 💡 **Why?** The script's curl commands are modified by setup-fork.sh, but local execution uses local files, not the updated GitHub URLs. Testing via curl ensures your script actually works.
>
> ⏱️ **Note:** GitHub sometimes takes 10-30 seconds to update files. If you don't see your changes, wait and try again.
5. **Cherry-Pick for PR** (submit ONLY your 3-4 files):
- See [Cherry-Pick Guide](../README.md) for step-by-step git commands
---
## Template Structure
The modern template includes:
### Header
```bash
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# (Note: setup-fork.sh changes this URL to point to YOUR fork during development)
```
### Metadata
```bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: YourUsername
# License: MIT
APP="MyApp"
var_tags="app-category;foss"
var_cpu="2"
var_ram="2048"
var_disk="4"
var_os="alpine"
var_version="3.20"
var_unprivileged="1"
```
### Core Setup
```bash
header_info "$APP"
variables
color
catch_errors
```
### Update Function
The modern template provides a standard update pattern:
```bash
function update_script() {
header_info
check_container_storage
check_container_resources
# Use tools.func helpers:
check_for_gh_release "myapp" "owner/repo"
fetch_and_deploy_gh_release "myapp" "owner/repo" "tarball" "latest" "/opt/myapp"
}
```
---
## Key Patterns
### Check for Updates (App Repository)
Use `check_for_gh_release` with the **app repo**:
```bash
check_for_gh_release "myapp" "owner/repo"
```
### Deploy External App
Use `fetch_and_deploy_gh_release` with the **app repo**:
```bash
fetch_and_deploy_gh_release "myapp" "owner/repo"
```
### Avoid Manual Version Checking
❌ OLD (manual):
```bash
RELEASE=$(curl -fsSL https://api.github.com/repos/myapp/myapp/releases/latest | grep tag_name)
```
✅ NEW (use tools.func):
```bash
fetch_and_deploy_gh_release "myapp" "owner/repo"
```
---
## Best Practices
1. **Use tools.func helpers** - Don't manually curl for versions
2. **Only add app-specific dependencies** - Don't add ca-certificates, curl, gnupg (handled by build.func)
3. **Test via curl from your fork** - Push first, then: `bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/MyApp.sh)"`
4. **Wait for GitHub to update** - Takes 10-30 seconds after git push
5. **Cherry-pick only YOUR files** - Submit only ct/MyApp.sh, install/MyApp-install.sh (2 files). Website metadata: use Report issue on the script's page on the website.
6. **Verify before PR** - Run `git diff upstream/main --name-only` to confirm only your files changed
---
## Common Update Patterns
See the [modern template](AppName.sh) and [AI.md](../AI.md) for complete working examples.
Recent reference scripts with good update functions:
- [Trip](https://github.com/community-scripts/ProxmoxVE/blob/main/ct/trip.sh)
- [Thingsboard](https://github.com/community-scripts/ProxmoxVE/blob/main/ct/thingsboard.sh)
- [UniFi](https://github.com/community-scripts/ProxmoxVE/blob/main/ct/unifi.sh)
---
## Need Help?
- **[README.md](../README.md)** - Full contribution workflow
- **[AI.md](../AI.md)** - AI-generated script guidelines
- **[FORK_SETUP.md](../FORK_SETUP.md)** - Why setup-fork.sh is important
- **[Slack Community](https://discord.gg/your-link)** - Ask questions
````
### 3.4 **Verbosity**
- Use the appropriate flag (**-q** in the examples) for a command to suppress its output.
Example:
```bash
curl -fsSL
unzip -q
````
- If a command does not come with this functionality use `$STD` to suppress it's output.
Example:
```bash
$STD php artisan migrate --force
$STD php artisan config:clear
```
### 3.5 **Backups**
- Backup user data if necessary.
- Move all user data back in the directory when the update is finished.
> [!NOTE]
> This is not meant to be a permanent backup
Example backup:
```bash
mv /opt/snipe-it /opt/snipe-it-backup
```
Example config restore:
```bash
cp /opt/snipe-it-backup/.env /opt/snipe-it/.env
cp -r /opt/snipe-it-backup/public/uploads/ /opt/snipe-it/public/uploads/
cp -r /opt/snipe-it-backup/storage/private_uploads /opt/snipe-it/storage/private_uploads
```
### 3.6 **Cleanup**
- Do not forget to remove any temporary files/folders such as zip-files or temporary backups.
Example:
```bash
rm -rf /opt/v${RELEASE}.zip
rm -rf /opt/snipe-it-backup
```
### 3.7 **No update function**
- In case you can not provide an update function use the following code to provide user feedback.
```bash
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/snipeit ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "Currently we don't provide an update function for this ${APP}."
exit
}
```
---
## 4 **End of the script**
- `start`: Launches Whiptail dialogue
- `build_container`: Collects and integrates user settings
- `description`: Sets LXC container description
- With `echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"` you can point the user to the IP:PORT/folder needed to access the app.
```bash
start
build_container
description
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}${CL}"
```
---
## 5. **Contribution checklist**
- [ ] Shebang is correctly set (`#!/usr/bin/env bash`).
- [ ] Correct link to _build.func_
- [ ] Metadata (author, license) is included at the top.
- [ ] Variables follow naming conventions.
- [ ] Update function exists.
- [ ] Update functions checks if app is installed and for new version.
- [ ] Update function cleans up temporary files.
- [ ] Script ends with a helpful message for the user to reach the application.

View File

@@ -0,0 +1,138 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: [YourGitHubUsername]
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: [SOURCE_URL e.g. https://github.com/example/app]
# ============================================================================
# APP CONFIGURATION
# ============================================================================
# These values are sent to build.func and define default container resources.
# Users can customize these during installation via the interactive prompts.
# ============================================================================
APP="[AppName]"
var_tags="${var_tags:-[category1];[category2]}" # Max 2 tags, semicolon-separated
var_cpu="${var_cpu:-2}" # CPU cores: 1-4 typical
var_ram="${var_ram:-2048}" # RAM in MB: 512, 1024, 2048, etc.
var_disk="${var_disk:-8}" # Disk in GB: 6, 8, 10, 20 typical
var_os="${var_os:-debian}" # OS: debian, ubuntu, alpine
var_version="${var_version:-13}" # OS Version: 13 (Debian), 24.04 (Ubuntu), 3.21 (Alpine)
var_unprivileged="${var_unprivileged:-1}" # 1=unprivileged (secure), 0=privileged (for Docker/Podman)
# ============================================================================
# INITIALIZATION - These are required in all CT scripts
# ============================================================================
header_info "$APP" # Display app name and setup header
variables # Initialize build.func variables
color # Load color variables for output
catch_errors # Enable error handling with automatic exit on failure
# ============================================================================
# UPDATE SCRIPT - Called when user selects "Update" from web interface
# ============================================================================
# This function is triggered by the web interface to update the application.
# It should:
# 1. Check if installation exists
# 2. Check for new GitHub releases
# 3. Stop running services
# 4. Backup critical data
# 5. Deploy new version
# 6. Run post-update commands (migrations, config updates, etc.)
# 7. Restore data if needed
# 8. Start services
#
# Exit with `exit` at the end to prevent container restart.
# ============================================================================
function update_script() {
header_info
check_container_storage
check_container_resources
# Step 1: Verify installation exists
if [[ ! -d /opt/[appname] ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
# Step 2: Check if update is available
if check_for_gh_release "[appname]" "YourUsername/YourRepo"; then
# Step 3: Stop services before update
msg_info "Stopping Service"
systemctl stop [appname]
msg_ok "Stopped Service"
# Step 4: Backup critical data before overwriting
msg_info "Backing up Data"
cp -r /opt/[appname]/data /opt/[appname]_data_backup 2>/dev/null || true
msg_ok "Backed up Data"
# Step 5: Download and deploy new version
# CLEAN_INSTALL=1 removes old directory before extracting
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "[appname]" "owner/repo" "tarball" "latest" "/opt/[appname]"
# Step 6: Run post-update commands (uncomment as needed)
# These examples show common patterns - use what applies to your app:
#
# For Node.js apps:
# msg_info "Installing Dependencies"
# cd /opt/[appname]
# $STD npm ci --production
# msg_ok "Installed Dependencies"
#
# For Python apps:
# msg_info "Installing Dependencies"
# cd /opt/[appname]
# $STD uv sync --frozen
# msg_ok "Installed Dependencies"
#
# For database migrations:
# msg_info "Running Database Migrations"
# cd /opt/[appname]
# $STD npm run migrate
# msg_ok "Ran Database Migrations"
#
# For PHP apps:
# msg_info "Installing Dependencies"
# cd /opt/[appname]
# $STD composer install --no-dev
# msg_ok "Installed Dependencies"
# Step 7: Restore data from backup
msg_info "Restoring Data"
cp -r /opt/[appname]_data_backup/. /opt/[appname]/data/ 2>/dev/null || true
rm -rf /opt/[appname]_data_backup
msg_ok "Restored Data"
# Step 8: Restart service with new version
msg_info "Starting Service"
systemctl start [appname]
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
exit
}
# ============================================================================
# MAIN EXECUTION - Container creation flow
# ============================================================================
# These are called by build.func and handle the full installation process:
# 1. start - Initialize container creation
# 2. build_container - Execute the install script inside container
# 3. description - Display completion info and access details
# ============================================================================
start
build_container
description
# ============================================================================
# COMPLETION MESSAGE
# ============================================================================
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}:[PORT]${CL}"

View File

@@ -0,0 +1,494 @@
# Install Scripts - Quick Reference
> [!WARNING]
> **This is legacy documentation.** Refer to the **modern template** at [templates_install/AppName-install.sh](AppName-install.sh) for best practices.
>
> Current templates use:
>
> - `tools.func` helpers (setup_nodejs, setup_uv, setup_postgresql_db, etc.)
> - Automatic dependency installation via build.func
> - Standardized environment variable patterns
---
## Before Creating a Script
1. **Copy the Modern Template:**
```bash
cp templates_install/AppName-install.sh install/MyApp-install.sh
# Edit install/MyApp-install.sh
```
2. **Key Pattern:**
- CT scripts source build.func and call the install script
- Install scripts use sourced FUNCTIONS_FILE_PATH (via build.func)
- Both scripts work together in the container
3. **Test via GitHub:**
```bash
# Push your changes to your fork first
git push origin feature/my-awesome-app
# Test the CT script via curl (it will call the install script)
bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/MyApp.sh)"
# ⏱️ Wait 10-30 seconds after pushing - GitHub takes time to update
```
---
## Template Structure
### Header
```bash
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/install.func)
# (setup-fork.sh modifies this URL to point to YOUR fork during development)
```
### Dependencies (App-Specific Only)
```bash
# Don't add: ca-certificates, curl, gnupg, wget, git, jq
# These are handled by build.func
msg_info "Installing dependencies"
$STD apt-get install -y app-specific-deps
msg_ok "Installed dependencies"
```
### Runtime Setup
Use tools.func helpers instead of manual installation:
```bash
# ✅ NEW (use tools.func):
NODE_VERSION="20"
setup_nodejs
# OR
PYTHON_VERSION="3.12"
setup_uv
# OR
PG_DB_NAME="myapp_db"
PG_DB_USER="myapp"
setup_postgresql_db
```
### Service Configuration
```bash
# Create .env file
msg_info "Configuring MyApp"
cat << EOF > /opt/myapp/.env
DEBUG=false
PORT=8080
DATABASE_URL=postgresql://...
EOF
msg_ok "Configuration complete"
# Create systemd service
msg_info "Creating systemd service"
cat << EOF > /etc/systemd/system/myapp.service
[Unit]
Description=MyApp
[Service]
ExecStart=/usr/bin/node /opt/myapp/app.js
[Install]
WantedBy=multi-user.target
EOF
msg_ok "Service created"
```
### Finalization
```bash
msg_info "Finalizing MyApp installation"
systemctl enable --now myapp
motd_ssh
customize
msg_ok "MyApp installation complete"
cleanup_lxc
```
---
## Key Patterns
### Avoid Manual Version Checking
❌ OLD (manual):
```bash
RELEASE=$(curl -fsSL https://api.github.com/repos/app/repo/releases/latest | grep tag_name)
wget https://github.com/app/repo/releases/download/$RELEASE/app.tar.gz
```
✅ NEW (use tools.func via CT script's fetch_and_deploy_gh_release):
```bash
# In CT script, not install script:
fetch_and_deploy_gh_release "myapp" "app/repo" "app.tar.gz" "latest" "/opt/myapp"
```
### Database Setup
```bash
# Use setup_postgresql_db, setup_mysql_db, etc.
PG_DB_NAME="myapp"
PG_DB_USER="myapp"
setup_postgresql_db
```
### Node.js Setup
```bash
NODE_VERSION="20"
setup_nodejs
npm install --no-save
```
---
## Best Practices
1. **Only add app-specific dependencies**
- Don't add: ca-certificates, curl, gnupg, wget, git, jq
- These are handled by build.func
2. **Use tools.func helpers**
- setup_nodejs, setup_python, setup_uv, setup_postgresql_db, setup_mysql_db, etc.
3. **Don't do version checks in install script**
- Version checking happens in CT script's update_script()
- Install script just installs the latest
4. **Structure:**
- Dependencies
- Runtime setup (tools.func)
- Deployment (fetch from CT script)
- Configuration files
- Systemd service
- Finalization
---
## Reference Scripts
See working examples:
- [Trip](https://github.com/community-scripts/ProxmoxVE/blob/main/install/trip-install.sh)
- [Thingsboard](https://github.com/community-scripts/ProxmoxVE/blob/main/install/thingsboard-install.sh)
- [UniFi](https://github.com/community-scripts/ProxmoxVE/blob/main/install/unifi-install.sh)
---
## Need Help?
- **[Modern Template](AppName-install.sh)** - Start here
- **[CT Template](../templates_ct/AppName.sh)** - How CT scripts work
- **[README.md](../README.md)** - Full contribution workflow
- **[AI.md](../AI.md)** - AI-generated script guidelines
### 1.2 **Comments**
- Add clear comments for script metadata, including author, copyright, and license information.
- Use meaningful inline comments to explain complex commands or logic.
Example:
```bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: [YourUserName]
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: [SOURCE_URL]
```
> [!NOTE]:
>
> - Add your username
> - When updating/reworking scripts, add "| Co-Author [YourUserName]"
### 1.3 **Variables and function import**
- This sections adds the support for all needed functions and variables.
```bash
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
```
---
## 2. **Variable naming and management**
### 2.1 **Naming conventions**
- Use uppercase names for constants and environment variables.
- Use lowercase names for local script variables.
Example:
```bash
DB_NAME=snipeit_db # Environment-like variable (constant)
db_user="snipeit" # Local variable
```
---
## 3. **Dependencies**
### 3.1 **Install all at once**
- Install all dependencies with a single command if possible
Example:
```bash
$STD apt-get install -y \
curl \
composer \
git \
sudo \
mc \
nginx
```
### 3.2 **Collapse dependencies**
Collapse dependencies to keep the code readable.
Example:
Use
```bash
php8.2-{bcmath,common,ctype}
```
instead of
```bash
php8.2-bcmath php8.2-common php8.2-ctype
```
---
## 4. **Paths to application files**
If possible install the app and all necessary files in `/opt/`
---
## 5. **Version management**
### 5.1 **Install the latest release**
- Always try and install the latest release
- Do not hardcode any version if not absolutely necessary
Example for a git release:
```bash
RELEASE=$(curl -fsSL https://api.github.com/repos/snipe/snipe-it/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
curl -fsSL "https://github.com/snipe/snipe-it/archive/refs/tags/v${RELEASE}.zip"
```
### 5.2 **Save the version for update checks**
- Write the installed version into a file.
- This is used for the update function in **AppName.sh** to check for if a Update is needed.
Example:
```bash
echo "${RELEASE}" >"/opt/AppName_version.txt"
```
---
## 6. **Input and output management**
### 6.1 **User feedback**
- Use standard functions like `msg_info`, `msg_ok` or `msg_error` to print status messages.
- Each `msg_info` must be followed with a `msg_ok` before any other output is made.
- Display meaningful progress messages at key stages.
Example:
```bash
msg_info "Installing Dependencies"
$STD apt-get install -y ...
msg_ok "Installed Dependencies"
```
### 6.2 **Verbosity**
- Use the appropiate flag (**-q** in the examples) for a command to suppres its output
Example:
```bash
curl -fsSL
unzip -q
```
- If a command dose not come with such a functionality use `$STD` (a custom standard redirection variable) for managing output verbosity.
Example:
```bash
$STD apt-get install -y nginx
```
---
## 7. **String/File Manipulation**
### 7.1 **File Manipulation**
- Use `sed` to replace placeholder values in configuration files.
Example:
```bash
sed -i -e "s|^DB_DATABASE=.*|DB_DATABASE=$DB_NAME|" \
-e "s|^DB_USERNAME=.*|DB_USERNAME=$DB_USER|" \
-e "s|^DB_PASSWORD=.*|DB_PASSWORD=$DB_PASS|" .env
```
---
## 8. **Security practices**
### 8.1 **Password generation**
- Use `openssl` to generate random passwords.
- Use only alphanumeric values to not introduce unknown behaviour.
Example:
```bash
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
```
### 8.2 **File permissions**
Explicitly set secure ownership and permissions for sensitive files.
Example:
```bash
chown -R www-data: /opt/snipe-it
chmod -R 755 /opt/snipe-it
```
---
## 9. **Service Configuration**
### 9.1 **Configuration files**
Use `cat <<EOF` to write configuration files in a clean and readable way.
Example:
```bash
cat <<EOF >/etc/nginx/conf.d/snipeit.conf
server {
listen 80;
root /opt/snipe-it/public;
index index.php;
}
EOF
```
### 9.2 **Credential management**
Store the generated credentials in a file.
Example:
```bash
USERNAME=username
PASSWORD=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
{
echo "Application-Credentials"
echo "Username: $USERNAME"
echo "Password: $PASSWORD"
} >> ~/application.creds
```
### 9.3 **Enviroment files**
Use `cat <<EOF` to write enviromental files in a clean and readable way.
Example:
```bash
cat <<EOF >/path/to/.env
VARIABLE="value"
PORT=3000
DB_NAME="${DB_NAME}"
EOF
```
### 9.4 **Services**
Enable affected services after configuration changes and start them right away.
Example:
```bash
systemctl enable -q --now nginx
```
---
## 10. **Cleanup**
### 10.1 **Remove temporary files**
Remove temporary files and downloads after use.
Example:
```bash
rm -rf /opt/v${RELEASE}.zip
```
### 10.2 **Autoremove and autoclean**
Remove unused dependencies to reduce disk space usage.
Example:
```bash
apt-get -y autoremove
apt-get -y autoclean
```
---
## 11. **Best Practices Checklist**
- [ ] Shebang is correctly set (`#!/usr/bin/env bash`).
- [ ] Metadata (author, license) is included at the top.
- [ ] Variables follow naming conventions.
- [ ] Sensitive values are dynamically generated.
- [ ] Files and services have proper permissions.
- [ ] Script cleans up temporary files.
---
### Example: High-Level Script Flow
1. Dependencies installation
2. Database setup
3. Download and configure application
4. Service configuration
5. Final cleanup

View File

@@ -0,0 +1,207 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: [YourGitHubUsername]
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: [SOURCE_URL e.g. https://github.com/example/app]
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
# =============================================================================
# DEPENDENCIES - Only add app-specific dependencies here!
# Don't add: ca-certificates, curl, gnupg, git, build-essential (handled by build.func)
# =============================================================================
msg_info "Installing Dependencies"
$STD apt install -y \
libharfbuzz0b \
fontconfig
msg_ok "Installed Dependencies"
# =============================================================================
# SETUP RUNTIMES & DATABASES (if needed)
# =============================================================================
# Examples (uncomment as needed):
#
# NODE_VERSION="22" setup_nodejs
# NODE_VERSION="22" NODE_MODULE="pnpm" setup_nodejs # Installs pnpm
# PYTHON_VERSION="3.13" setup_uv
# JAVA_VERSION="21" setup_java
# GO_VERSION="1.22" setup_go
# PHP_VERSION="8.4" PHP_FPM="YES" setup_php
# setup_postgresql # Server only
# setup_mariadb # Server only
# setup_meilisearch # Search engine
#
# Then set up DB and user (sets $[DB]_DB_PASS):
# PG_DB_NAME="myapp" PG_DB_USER="myapp" setup_postgresql_db
# MARIADB_DB_NAME="myapp" MARIADB_DB_USER="myapp" setup_mariadb_db
# =============================================================================
# DOWNLOAD & DEPLOY APPLICATION
# =============================================================================
# fetch_and_deploy_gh_release modes:
# "tarball" - Source tarball (default if omitted)
# "binary" - .deb package (auto-detects amd64/arm64)
# "prebuild" - Pre-built archive (.tar.gz)
# "singlefile" - Single binary file
#
# Examples:
# fetch_and_deploy_gh_release "myapp" "YourUsername/myapp" "tarball" "latest" "/opt/myapp"
# fetch_and_deploy_gh_release "myapp" "YourUsername/myapp" "binary" "latest" "/tmp"
# fetch_and_deploy_gh_release "myapp" "YourUsername/myapp" "prebuild" "latest" "/opt/myapp" "myapp-*.tar.gz"
fetch_and_deploy_gh_release "[appname]" "owner/repo" "tarball" "latest" "/opt/[appname]"
# --- Tools & Utilities ---
# get_lxc_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]/
# =============================================================================
# EXAMPLES
# =============================================================================
#
# EXAMPLE 1: Node.js Application with PostgreSQL
# ---------------------------------------------
# NODE_VERSION="22" setup_nodejs
# PG_VERSION="17" setup_postgresql
# PG_DB_NAME="myapp" PG_DB_USER="myapp" setup_postgresql_db
# get_lxc_ip
# fetch_and_deploy_gh_release "myapp" "owner/myapp" "tarball" "latest" "/opt/myapp"
#
# msg_info "Configuring MyApp"
# cd /opt/myapp
# $STD npm ci
# cat <<EOF >/opt/myapp/.env
# DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost/${PG_DB_NAME}
# HOST=${LOCAL_IP}
# PORT=3000
# EOF
# msg_ok "Configured MyApp"
#
# EXAMPLE 2: Python Application with uv
# ------------------------------------
# PYTHON_VERSION="3.13" setup_uv
# get_lxc_ip
# fetch_and_deploy_gh_release "myapp" "owner/myapp" "tarball" "latest" "/opt/myapp"
#
# msg_info "Setting up MyApp"
# cd /opt/myapp
# $STD uv sync
# cat <<EOF >/opt/myapp/.env
# HOST=${LOCAL_IP}
# PORT=8000
# EOF
# msg_ok "Setup MyApp"
# =============================================================================
# EXAMPLE 3: PHP Application with MariaDB + Nginx
# =============================================================================
# PHP_VERSION="8.4" PHP_FPM="YES" PHP_MODULE="bcmath,curl,gd,intl,mbstring,mysql,xml,zip" setup_php
# setup_composer
# setup_mariadb
# MARIADB_DB_NAME="myapp" MARIADB_DB_USER="myapp" setup_mariadb_db
# get_lxc_ip
# fetch_and_deploy_gh_release "myapp" "owner/myapp" "prebuild" "latest" "/opt/myapp" "myapp-*.tar.gz"
#
# msg_info "Configuring MyApp"
# cd /opt/myapp
# cp .env.example .env
# sed -i "s|APP_URL=.*|APP_URL=http://${LOCAL_IP}|" .env
# sed -i "s|DB_DATABASE=.*|DB_DATABASE=${MARIADB_DB_NAME}|" .env
# sed -i "s|DB_USERNAME=.*|DB_USERNAME=${MARIADB_DB_USER}|" .env
# sed -i "s|DB_PASSWORD=.*|DB_PASSWORD=${MARIADB_DB_PASS}|" .env
# $STD composer install --no-dev --no-interaction
# chown -R www-data:www-data /opt/myapp
# msg_ok "Configured MyApp"
# =============================================================================
# YOUR APPLICATION INSTALLATION
# =============================================================================
# 1. Setup runtimes and databases FIRST
# 2. Call get_lxc_ip if you need the container IP
# 3. Use fetch_and_deploy_gh_release to download the app (handles version tracking)
# 4. Configure the application
# 5. Create systemd service
# 6. Finalize with motd_ssh, customize, cleanup_lxc
# --- Setup runtimes/databases ---
NODE_VERSION="22" setup_nodejs
get_lxc_ip
# --- Download and install app ---
fetch_and_deploy_gh_release "[appname]" "[owner/repo]" "tarball" "latest" "/opt/[appname]"
msg_info "Setting up [AppName]"
cd /opt/[appname]
# $STD npm ci
msg_ok "Setup [AppName]"
# =============================================================================
# CONFIGURATION
# =============================================================================
msg_info "Configuring [AppName]"
cd /opt/[appname]
# Install application dependencies (uncomment as needed):
# $STD npm ci --production # Node.js apps
# $STD uv sync --frozen # Python apps
# $STD composer install --no-dev # PHP apps
# $STD cargo build --release # Rust apps
# Create .env file if needed:
cat <<EOF >/opt/[appname]/.env
# Use import_local_ip to get container IP, or hardcode if building on Proxmox
APP_URL=http://localhost
PORT=8080
EOF
msg_ok "Configured [AppName]"
# =============================================================================
# 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]
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"
# =============================================================================
# CLEANUP & FINALIZATION
# =============================================================================
# These are called automatically, but shown here for clarity:
# motd_ssh - Displays service info on SSH login
# customize - Enables optional customizations
# cleanup_lxc - Removes temp files, bash history, logs
motd_ssh
customize
cleanup_lxc

View File

@@ -0,0 +1,40 @@
{
"name": "AppName",
"slug": "appname",
"categories": [
0
],
"date_created": "2026-01-18",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://docs.example.com/",
"website": "https://example.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/appname.webp",
"config_path": "/opt/appname/.env",
"description": "Short description of what AppName does and its main features.",
"install_methods": [
{
"type": "default",
"script": "ct/appname.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Change the default password after first login!",
"type": "warning"
}
]
}

View File

@@ -0,0 +1,160 @@
# Website Metadata - Quick Reference
Metadata (name, slug, description, logo, categories, etc.) controls how your application appears on the website. You do **not** add JSON files to the repo — you request changes via the website.
---
## How to Request or Update Metadata
1. **Go to the script on the website** — Open the [ProxmoxVE website](https://community-scripts.github.io/ProxmoxVE/), find your script (or the script you want to update).
2. **Press the "Report issue" button** on that scripts page.
3. **Follow the guide** — The flow will walk you through submitting or updating metadata.
---
## Metadata Structure (Reference)
The following describes the structure of script metadata used by the website. Use it as reference when filling out the form or describing what you need.
```json
{
"name": "MyApp",
"slug": "myapp",
"categories": [1],
"date_created": "2026-01-18",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://docs.example.com/",
"website": "https://example.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/myapp.webp",
"config_path": "/opt/myapp/.env",
"description": "Brief description of what MyApp does",
"install_methods": [
{
"type": "default",
"script": "ct/myapp.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Change the default password after first login!",
"type": "warning"
}
]
}
```
---
## Field Reference
| Field | Required | Example | Notes |
| --------------------- | -------- | ----------------- | ---------------------------------------------- |
| `name` | Yes | "MyApp" | Display name |
| `slug` | Yes | "myapp" | URL-friendly identifier (lowercase, no spaces) |
| `categories` | Yes | [1] | One or more category IDs |
| `date_created` | Yes | "2026-01-18" | Format: YYYY-MM-DD |
| `type` | Yes | "ct" | Container type: "ct" or "vm" |
| `interface_port` | Yes | 3000 | Default web interface port |
| `logo` | No | "https://..." | Logo URL (64px x 64px PNG) |
| `config_path` | Yes | "/opt/myapp/.env" | Main config file location |
| `description` | Yes | "App description" | Brief description (100 chars) |
| `install_methods` | Yes | See below | Installation resources (array) |
| `default_credentials` | No | See below | Optional default login |
| `notes` | No | See below | Additional notes (array) |
---
## Install Methods
Each installation method specifies resource requirements:
```json
"install_methods": [
{
"type": "default",
"script": "ct/myapp.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "Debian",
"version": "13"
}
}
]
```
**Resource Defaults:**
- CPU: Cores (1-8)
- RAM: Megabytes (256-4096)
- Disk: Gigabytes (4-50)
---
## Common Categories
- `0` Miscellaneous
- `1` Proxmox & Virtualization
- `2` Operating Systems
- `3` Containers & Docker
- `4` Network & Firewall
- `5` Adblock & DNS
- `6` Authentication & Security
- `7` Backup & Recovery
- `8` Databases
- `9` Monitoring & Analytics
- `10` Dashboards & Frontends
- `11` Files & Downloads
- `12` Documents & Notes
- `13` Media & Streaming
- `14` \*Arr Suite
- `15` NVR & Cameras
- `16` IoT & Smart Home
- `17` ZigBee, Z-Wave & Matter
- `18` MQTT & Messaging
- `19` Automation & Scheduling
- `20` AI / Coding & Dev-Tools
- `21` Webservers & Proxies
- `22` Bots & ChatOps
- `23` Finance & Budgeting
- `24` Gaming & Leisure
- `25` Business & ERP
---
## Best Practices
1. **Use the JSON Generator** - It validates structure
2. **Keep descriptions short** - 100 characters max
3. **Use real resource requirements** - Based on your testing
4. **Include sensible defaults** - Pre-filled in install_methods
5. **Slug must be lowercase** - No spaces, use hyphens
---
## See Examples on the Website
View script pages on the [ProxmoxVE website](https://community-scripts.github.io/ProxmoxVE/) to see how metadata is displayed for existing scripts.
---
## Need Help?
- **Request metadata** — Use the Report issue button on the scripts page on the website (see [How to Request or Update Metadata](#how-to-request-or-update-metadata) above).
- **[JSON Generator](https://community-scripts.github.io/ProxmoxVE/json-editor)** - Reference only; structure validation
- **[README.md](../README.md)** - Full contribution workflow

472
docs/ct/DETAILED_GUIDE.md Normal file
View File

@@ -0,0 +1,472 @@
# 🚀 **Application Container Scripts (ct/AppName.sh)**
**Modern Guide to Creating LXC Container Installation Scripts**
> **Updated**: December 2025
> **Context**: Fully integrated with build.func, advanced_settings wizard, and defaults system
> **Example Used**: `/ct/pihole.sh`, `/ct/docker.sh`
---
## 📋 Table of Contents
- [Overview](#overview)
- [Architecture & Flow](#architecture--flow)
- [File Structure](#file-structure)
- [Complete Script Template](#complete-script-template)
- [Function Reference](#function-reference)
- [Advanced Features](#advanced-features)
- [Real Examples](#real-examples)
- [Troubleshooting](#troubleshooting)
- [Contribution Checklist](#contribution-checklist)
---
## Overview
### Purpose
Container scripts (`ct/AppName.sh`) are **entry points for creating LXC containers** with specific applications pre-installed. They:
1. Define container defaults (CPU, RAM, disk, OS)
2. Call the main build orchestrator (`build.func`)
3. Implement application-specific update mechanisms
4. Provide user-facing success messages
### Execution Context
```
Proxmox Host
ct/AppName.sh sourced (runs as root on host)
build.func: Creates LXC container + runs install script inside
install/AppName-install.sh (runs inside container)
Container ready with app installed
```
### Key Integration Points
- **build.func** - Main orchestrator (container creation, storage, variable management)
- **install.func** - Container-specific setup (OS update, package management)
- **tools.func** - Tool installation helpers (repositories, GitHub releases)
- **core.func** - UI/messaging functions (colors, spinners, validation)
- **error_handler.func** - Error handling and signal management
---
## Architecture & Flow
### Container Creation Flow
```
START: bash ct/pihole.sh
[1] Set APP, var_*, defaults
[2] header_info() → Display ASCII art
[3] variables() → Parse arguments & load build.func
[4] color() → Setup ANSI codes
[5] catch_errors() → Setup trap handlers
[6] install_script() → Show mode menu (5 options)
├─ INSTALL_MODE="0" (Default)
├─ INSTALL_MODE="1" (Advanced - 19-step wizard)
├─ INSTALL_MODE="2" (User Defaults)
├─ INSTALL_MODE="3" (App Defaults)
└─ INSTALL_MODE="4" (Settings Menu)
[7] advanced_settings() → Collect user configuration (if mode=1)
[8] start() → Confirm or re-edit settings
[9] build_container() → Create LXC + execute install script
[10] description() → Set container description
[11] SUCCESS → Display access URL
END
```
### Default Values Precedence
```
Priority 1 (Highest): Environment Variables (var_cpu, var_ram, etc.)
Priority 2: App-Specific Defaults (/defaults/AppName.vars)
Priority 3: User Global Defaults (/default.vars)
Priority 4 (Lowest): Built-in Defaults (in build.func)
```
---
## File Structure
### Minimal ct/AppName.sh Template
```
#!/usr/bin/env bash # [1] Shebang
# [2] Copyright/License
source <(curl -s .../misc/build.func) # [3] Import functions
# [4] APP metadata
APP="AppName" # [5] Default values
var_tags="tag1;tag2"
var_cpu="2"
var_ram="2048"
...
header_info "$APP" # [6] Display header
variables # [7] Process arguments
color # [8] Setup colors
catch_errors # [9] Setup error handling
function update_script() { ... } # [10] Update function (optional)
start # [11] Launch container creation
build_container
description
msg_ok "Completed successfully!\n"
```
---
## Complete Script Template
### 1. File Header & Imports
```bash
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: YourUsername
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/example/project
# Import main orchestrator
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVE/raw/branch/main/misc/build.func)
```
> **⚠️ IMPORTANT**: Before opening a PR, change URL to `community-scripts` repo!
### 2. Application Metadata
```bash
# Application Configuration
APP="ApplicationName"
var_tags="tag1;tag2;tag3" # Max 3-4 tags, no spaces, semicolon-separated
# Container Resources
var_cpu="2" # CPU cores
var_ram="2048" # RAM in MB
var_disk="10" # Disk in GB
# Container Type & OS
var_os="debian" # Options: alpine, debian, ubuntu
var_version="12" # Alpine: 3.20+, Debian: 11-13, Ubuntu: 20.04+
var_unprivileged="1" # 1=unprivileged (secure), 0=privileged (rarely needed)
```
**Variable Naming Convention**:
- Variables exposed to user: `var_*` (e.g., `var_cpu`, `var_hostname`, `var_ssh`)
- Internal variables: lowercase (e.g., `container_id`, `app_version`)
### 3. Display & Initialization
```bash
# Display header ASCII art
header_info "$APP"
# Process command-line arguments and load configuration
variables
# Setup ANSI color codes and formatting
color
# Initialize error handling (trap ERR, EXIT, INT, TERM)
catch_errors
```
### 4. Update Function (Highly Recommended)
```bash
function update_script() {
header_info
# Always start with these checks
check_container_storage
check_container_resources
# Verify app is installed
if [[ ! -d /opt/appname ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
# Get latest version 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)}')
# Compare with saved version
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
msg_info "Updating ${APP} to v${RELEASE}"
# Backup user data
cp -r /opt/appname /opt/appname-backup
# Perform update
cd /opt
wget -q "https://github.com/user/repo/releases/download/v${RELEASE}/app-${RELEASE}.tar.gz"
tar -xzf app-${RELEASE}.tar.gz
# Restore user data
cp /opt/appname-backup/config/* /opt/appname/config/
# Cleanup
rm -rf app-${RELEASE}.tar.gz /opt/appname-backup
# Save new version
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
}
```
### 5. Script Launch
```bash
# Start the container creation workflow
start
# Build the container with selected configuration
build_container
# Set container description/notes in Proxmox UI
description
# Display success message
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}:8080${CL}"
```
---
## Function Reference
### Core Functions (From build.func)
#### `variables()`
**Purpose**: Initialize container variables, load user arguments, setup orchestration
**Triggered by**: Called automatically at script start
**Behavior**:
1. Parse command-line arguments (if any)
2. Generate random UUID for session tracking
3. Load container storage from Proxmox
4. Initialize application-specific defaults
5. Setup SSH/environment configuration
#### `start()`
**Purpose**: Launch the container creation menu with 5 installation modes
**Menu Options**:
```
1. Default Installation (Quick setup, predefined settings)
2. Advanced Installation (19-step wizard with full control)
3. User Defaults (Load ~/.community-scripts/default.vars)
4. App Defaults (Load /defaults/AppName.vars)
5. Settings Menu (Interactive mode selection)
```
#### `build_container()`
**Purpose**: Main orchestrator for LXC container creation
**Operations**:
1. Validates all variables
2. Creates LXC container via `pct create`
3. Executes `install/AppName-install.sh` inside container
4. Monitors installation progress
5. Handles errors and rollback on failure
#### `description()`
**Purpose**: Set container description/notes visible in Proxmox UI
---
## Advanced Features
### 1. Custom Configuration Menus
If your app has additional setup beyond standard vars:
```bash
custom_app_settings() {
CONFIGURE_DB=$(whiptail --title "Database Setup" \
--yesno "Would you like to configure a custom database?" 8 60)
if [[ $? -eq 0 ]]; then
DB_HOST=$(whiptail --inputbox "Database Host:" 8 60 3>&1 1>&2 2>&3)
DB_PORT=$(whiptail --inputbox "Database Port:" 8 60 "3306" 3>&1 1>&2 2>&3)
fi
}
custom_app_settings
```
### 2. Update Function Patterns
Save installed version for update checks
### 3. Health Check Functions
Add custom validation:
```bash
function health_check() {
header_info
if [[ ! -d /opt/appname ]]; then
msg_error "Application not found!"
exit 1
fi
if ! systemctl is-active --quiet appname; then
msg_error "Application service not running"
exit 1
fi
msg_ok "Health check passed"
}
```
---
## Real Examples
### Example 1: Simple Web App (Debian-based)
```bash
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVE/raw/branch/main/misc/build.func)
APP="Homarr"
var_tags="dashboard;homepage"
var_cpu="2"
var_ram="1024"
var_disk="5"
var_os="debian"
var_version="12"
var_unprivileged="1"
header_info "$APP"
variables
color
catch_errors
function update_script() {
# Update logic here
}
start
build_container
description
msg_ok "Completed successfully!\n"
```
---
## Troubleshooting
### Container Creation Fails
**Symptom**: `pct create` exits with error code 209
**Solution**:
```bash
# Check existing containers
pct list | grep CTID
# Remove conflicting container
pct destroy CTID
# Retry ct/AppName.sh
```
### Update Function Doesn't Detect New Version
**Debug**:
```bash
# Check version file
cat /opt/AppName_version.txt
# Test GitHub API
curl -fsSL https://api.github.com/repos/user/repo/releases/latest | grep tag_name
```
---
## Contribution Checklist
Before submitting a PR:
### Script Structure
- [ ] Shebang is `#!/usr/bin/env bash`
- [ ] Imports `build.func` from community-scripts repo
- [ ] Copyright header with author and source URL
- [ ] APP variable matches filename
- [ ] `var_tags` are semicolon-separated (no spaces)
### Default Values
- [ ] `var_cpu` set appropriately (2-4 for most apps)
- [ ] `var_ram` set appropriately (1024-4096 MB minimum)
- [ ] `var_disk` sufficient for app + data (5-20 GB)
- [ ] `var_os` is realistic
### Functions
- [ ] `update_script()` implemented
- [ ] Update function checks if app installed
- [ ] Proper error handling with `msg_error`
### Testing
- [ ] Script tested with default installation
- [ ] Script tested with advanced (19-step) installation
- [ ] Update function tested on existing installation
---
## Best Practices
### ✅ DO:
1. **Use meaningful defaults**
2. **Implement version tracking**
3. **Handle edge cases**
4. **Use proper messaging with msg_info/msg_ok/msg_error**
### ❌ DON'T:
1. **Hardcode versions**
2. **Use custom color codes** (use built-in variables)
3. **Forget error handling**
4. **Leave temporary files**
---
**Last Updated**: December 2025
**Compatibility**: ProxmoxVE with build.func v3+

72
docs/ct/README.md Normal file
View File

@@ -0,0 +1,72 @@
# Container Scripts Documentation (/ct)
This directory contains comprehensive documentation for container creation scripts in the `/ct` directory.
## Overview
Container scripts (`ct/*.sh`) are the entry points for creating LXC containers in Proxmox VE. They run on the host and orchestrate the entire container creation process.
## Documentation Structure
Each script has standardized documentation following the project pattern.
## Key Resources
- **[DETAILED_GUIDE.md](DETAILED_GUIDE.md)** - Complete reference for creating ct scripts
- **[../contribution/README.md](../contribution/README.md)** - How to contribute
- **[../misc/build.func/](../misc/build.func/)** - Core orchestrator documentation
## Container Creation Flow
```
ct/AppName.sh (host-side)
├─ Calls: build.func (orchestrator)
├─ Variables: var_cpu, var_ram, var_disk, var_os
└─ Creates: LXC Container
└─ Runs: install/appname-install.sh (inside)
```
## Available Scripts
See `/ct` directory for all container creation scripts. Common examples:
- `pihole.sh` - Pi-hole DNS/DHCP server
- `docker.sh` - Docker container runtime
- `wallabag.sh` - Article reading & archiving
- `nextcloud.sh` - Private cloud storage
- `debian.sh` - Basic Debian container
- And 30+ more...
## Quick Start
To understand how to create a container script:
1. Read: [UPDATED_APP-ct.md](../UPDATED_APP-ct.md)
2. Study: A similar existing script in `/ct`
3. Copy template and customize
4. Test locally
5. Submit PR
## Contributing a New Container
1. Create `ct/myapp.sh`
2. Create `install/myapp-install.sh`
3. Follow template in [UPDATED_APP-ct.md](../UPDATED_APP-ct.md)
4. Test thoroughly
5. Submit PR with both files
## Common Tasks
- **Add new container application** → [contribution/README.md](../contribution/README.md)
- **Debug container creation** → [EXIT_CODES.md](../EXIT_CODES.md)
- **Understand build.func** → [misc/build.func/](../misc/build.func/)
- **Development mode debugging** → [DEV_MODE.md](../DEV_MODE.md)
---
**Last Updated**: December 2025
**Maintainers**: community-scripts team

View File

@@ -0,0 +1,904 @@
# Configuration Reference
**Complete reference for all configuration variables and options in community-scripts for Proxmox VE.**
---
## Table of Contents
1. [Variable Naming Convention](#variable-naming-convention)
2. [Complete Variable Reference](#complete-variable-reference)
3. [Resource Configuration](#resource-configuration)
4. [Network Configuration](#network-configuration)
5. [IPv6 Configuration](#ipv6-configuration)
6. [SSH Configuration](#ssh-configuration)
7. [Container Features](#container-features)
8. [Storage Configuration](#storage-configuration)
9. [Security Settings](#security-settings)
10. [Advanced Options](#advanced-options)
11. [Quick Reference Table](#quick-reference-table)
---
## Variable Naming Convention
All configuration variables follow a consistent pattern:
```
var_<setting>=<value>
```
**Rules:**
- ✅ Always starts with `var_`
- ✅ Lowercase letters only
- ✅ Underscores for word separation
- ✅ No spaces around `=`
- ✅ Values can be quoted if needed
**Examples:**
```bash
# ✓ Correct
var_cpu=4
var_hostname=myserver
var_ssh_authorized_key=ssh-rsa AAAA...
# ✗ Wrong
CPU=4 # Missing var_ prefix
var_CPU=4 # Uppercase not allowed
var_cpu = 4 # Spaces around =
var-cpu=4 # Hyphens not allowed
```
---
## Complete Variable Reference
### var_unprivileged
**Type:** Boolean (0 or 1)
**Default:** `1` (unprivileged)
**Description:** Determines if container runs unprivileged (recommended) or privileged.
```bash
var_unprivileged=1 # Unprivileged (safer, recommended)
var_unprivileged=0 # Privileged (less secure, more features)
```
**When to use privileged (0):**
- Hardware access required
- Certain kernel modules needed
- Legacy applications
- Nested virtualization with full features
**Security Impact:**
- Unprivileged: Container root is mapped to unprivileged user on host
- Privileged: Container root = host root (security risk)
---
### var_cpu
**Type:** Integer
**Default:** Varies by app (usually 1-4)
**Range:** 1 to host CPU count
**Description:** Number of CPU cores allocated to container.
```bash
var_cpu=1 # Single core (minimal)
var_cpu=2 # Dual core (typical)
var_cpu=4 # Quad core (recommended for apps)
var_cpu=8 # High performance
```
**Best Practices:**
- Start with 2 cores for most applications
- Monitor usage with `pct exec <id> -- htop`
- Can be changed after creation
- Consider host CPU count (don't over-allocate)
---
### var_ram
**Type:** Integer (MB)
**Default:** Varies by app (usually 512-2048)
**Range:** 512 MB to host RAM
**Description:** Amount of RAM in megabytes.
```bash
var_ram=512 # 512 MB (minimal)
var_ram=1024 # 1 GB (typical)
var_ram=2048 # 2 GB (comfortable)
var_ram=4096 # 4 GB (recommended for databases)
var_ram=8192 # 8 GB (high memory apps)
```
**Conversion Guide:**
```
512 MB = 0.5 GB
1024 MB = 1 GB
2048 MB = 2 GB
4096 MB = 4 GB
8192 MB = 8 GB
16384 MB = 16 GB
```
**Best Practices:**
- Minimum 512 MB for basic Linux
- 1 GB for typical applications
- 2-4 GB for web servers, databases
- Monitor with `free -h` inside container
---
### var_disk
**Type:** Integer (GB)
**Default:** Varies by app (usually 2-8)
**Range:** 0.001 GB to storage capacity
**Description:** Root disk size in gigabytes.
```bash
var_disk=2 # 2 GB (minimal OS only)
var_disk=4 # 4 GB (typical)
var_disk=8 # 8 GB (comfortable)
var_disk=20 # 20 GB (recommended for apps)
var_disk=50 # 50 GB (large applications)
var_disk=100 # 100 GB (databases, media)
```
**Important Notes:**
- Can be expanded after creation (not reduced)
- Actual space depends on storage type
- Thin provisioning supported on most storage
- Plan for logs, data, updates
**Recommended Sizes by Use Case:**
```
Basic Linux container: 4 GB
Web server (Nginx/Apache): 8 GB
Application server: 10-20 GB
Database server: 20-50 GB
Docker host: 30-100 GB
Media server: 100+ GB
```
---
### var_hostname
**Type:** String
**Default:** Application name
**Max Length:** 63 characters
**Description:** Container hostname (FQDN format allowed).
```bash
var_hostname=myserver
var_hostname=pihole
var_hostname=docker-01
var_hostname=web.example.com
```
**Rules:**
- Lowercase letters, numbers, hyphens
- Cannot start or end with hyphen
- No underscores allowed
- No spaces
**Best Practices:**
```bash
# ✓ Good
var_hostname=web-server
var_hostname=db-primary
var_hostname=app.domain.com
# ✗ Avoid
var_hostname=Web_Server # Uppercase, underscore
var_hostname=-server # Starts with hyphen
var_hostname=my server # Contains space
```
---
### var_brg
**Type:** String
**Default:** `vmbr0`
**Description:** Network bridge interface.
```bash
var_brg=vmbr0 # Default Proxmox bridge
var_brg=vmbr1 # Custom bridge
var_brg=vmbr2 # Isolated network
```
**Common Setups:**
```
vmbr0 → Main network (LAN)
vmbr1 → Guest network
vmbr2 → DMZ
vmbr3 → Management
vmbr4 → Storage network
```
**Check available bridges:**
```bash
ip link show | grep vmbr
# or
brctl show
```
---
### var_net
**Type:** String
**Options:** `dhcp` or `static`
**Default:** `dhcp`
**Description:** IPv4 network configuration method.
```bash
var_net=dhcp # Automatic IP via DHCP
var_net=static # Manual IP configuration
```
**DHCP Mode:**
- Automatic IP assignment
- Easy setup
- Good for development
- Requires DHCP server on network
**Static Mode:**
- Fixed IP address
- Requires gateway configuration
- Better for servers
- Configure via advanced settings or after creation
---
### var_gateway
**Type:** IPv4 Address
**Default:** Auto-detected from host
**Description:** Network gateway IP address.
```bash
var_gateway=192.168.1.1
var_gateway=10.0.0.1
var_gateway=172.16.0.1
```
**Auto-detection:**
If not specified, system detects gateway from host:
```bash
ip route | grep default
```
**When to specify:**
- Multiple gateways available
- Custom routing setup
- Different network segment
---
### var_vlan
**Type:** Integer
**Range:** 1-4094
**Default:** None
**Description:** VLAN tag for network isolation.
```bash
var_vlan=10 # VLAN 10
var_vlan=100 # VLAN 100
var_vlan=200 # VLAN 200
```
**Common VLAN Schemes:**
```
VLAN 10 → Management
VLAN 20 → Servers
VLAN 30 → Desktops
VLAN 40 → Guest WiFi
VLAN 50 → IoT devices
VLAN 99 → DMZ
```
**Requirements:**
- Switch must support VLANs
- Proxmox bridge configured for VLAN aware
- Gateway on same VLAN
---
### var_mtu
**Type:** Integer
**Default:** `1500`
**Range:** 68-9000
**Description:** Maximum Transmission Unit size.
```bash
var_mtu=1500 # Standard Ethernet
var_mtu=1492 # PPPoE
var_mtu=9000 # Jumbo frames
```
**Common Values:**
```
1500 → Standard Ethernet (default)
1492 → PPPoE connections
1400 → Some VPN setups
9000 → Jumbo frames (10GbE networks)
```
**When to change:**
- Jumbo frames for performance on 10GbE
- PPPoE internet connections
- VPN tunnels with overhead
- Specific network requirements
---
### var_mac
**Type:** MAC Address
**Format:** `XX:XX:XX:XX:XX:XX`
**Default:** Auto-generated
**Description:** Container MAC address.
```bash
var_mac=02:00:00:00:00:01
var_mac=DE:AD:BE:EF:00:01
```
**When to specify:**
- MAC-based licensing
- Static DHCP reservations
- Network access control
- Cloning configurations
**Best Practices:**
- Use locally administered addresses (2nd bit set)
- Start with `02:`, `06:`, `0A:`, `0E:`
- Avoid vendor OUIs
- Document custom MACs
---
### var_ipv6_method
**Type:** String
**Options:** `auto`, `dhcp`, `static`, `none`, `disable`
**Default:** `none`
**Description:** IPv6 configuration method.
```bash
var_ipv6_method=auto # SLAAC (auto-configuration)
var_ipv6_method=dhcp # DHCPv6
var_ipv6_method=static # Manual configuration
var_ipv6_method=none # IPv6 enabled but not configured
var_ipv6_method=disable # IPv6 completely disabled
```
**Detailed Options:**
**auto (SLAAC)**
- Stateless Address Auto-Configuration
- Router advertisements
- No DHCPv6 server needed
- Recommended for most cases
**dhcp (DHCPv6)**
- Stateful configuration
- Requires DHCPv6 server
- More control over addressing
**static**
- Manual IPv6 address
- Manual gateway
- Full control
**none**
- IPv6 stack active
- No address configured
- Can configure later
**disable**
- IPv6 completely disabled at kernel level
- Use when IPv6 causes issues
- Sets `net.ipv6.conf.all.disable_ipv6=1`
---
### var_ns
**Type:** IP Address
**Default:** Auto (from host)
**Description:** DNS nameserver IP.
```bash
var_ns=8.8.8.8 # Google DNS
var_ns=1.1.1.1 # Cloudflare DNS
var_ns=9.9.9.9 # Quad9 DNS
var_ns=192.168.1.1 # Local DNS
```
**Common DNS Servers:**
```
8.8.8.8, 8.8.4.4 → Google Public DNS
1.1.1.1, 1.0.0.1 → Cloudflare DNS
9.9.9.9, 149.112.112.112 → Quad9 DNS
208.67.222.222 → OpenDNS
192.168.1.1 → Local router/Pi-hole
```
---
### var_ssh
**Type:** Boolean
**Options:** `yes` or `no`
**Default:** `no`
**Description:** Enable SSH server in container.
```bash
var_ssh=yes # SSH server enabled
var_ssh=no # SSH server disabled (console only)
```
**When enabled:**
- OpenSSH server installed
- Started on boot
- Port 22 open
- Root login allowed
**Security Considerations:**
- Disable if not needed
- Use SSH keys instead of passwords
- Consider non-standard port
- Firewall rules recommended
---
### var_ssh_authorized_key
**Type:** String (SSH public key)
**Default:** None
**Description:** SSH public key for root user.
```bash
var_ssh_authorized_key=ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC... user@host
var_ssh_authorized_key=ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... user@host
```
**Supported Key Types:**
- RSA (2048-4096 bits)
- Ed25519 (recommended)
- ECDSA
- DSA (deprecated)
**How to get your public key:**
```bash
cat ~/.ssh/id_rsa.pub
# or
cat ~/.ssh/id_ed25519.pub
```
**Multiple keys:**
Separate with newlines (in file) or use multiple deployments.
---
### var_pw
**Type:** String
**Default:** Empty (auto-login)
**Description:** Root password.
```bash
var_pw=SecurePassword123! # Set password
var_pw= # Auto-login (empty)
```
**Auto-login behavior:**
- No password required for console
- Automatic login on console access
- SSH still requires key if enabled
- Suitable for development
**Password best practices:**
- Minimum 12 characters
- Mix upper/lower/numbers/symbols
- Use password manager
- Rotate regularly
---
### var_nesting
**Type:** Boolean (0 or 1)
**Default:** `1`
**Description:** Allow nested containers (required for Docker).
```bash
var_nesting=1 # Nested containers allowed
var_nesting=0 # Nested containers disabled
```
**Required for:**
- Docker
- LXC inside LXC
- Systemd features
- Container orchestration
**Security Impact:**
- Slightly reduced isolation
- Required for container platforms
- Generally safe when unprivileged
---
### var_diagnostics
**Type:** Boolean (yes or no)
**Default:** `yes`
**Description:** Determines if anonymous telemetry and diagnostic data is sent to Community-Scripts API.
```bash
var_diagnostics=yes # Allow telemetry (helps us improve scripts)
var_diagnostics=no # Disable all telemetry
```
**Privacy & Usage:**
- Data is strictly anonymous (random session ID)
- Reports success/failure of installations
- Maps error codes (e.g., APT lock, out of RAM)
- No user-specific data, hostnames, or secret keys are ever sent
---
### var_gpu
**Type:** Boolean/Toggle
**Options:** `yes` or `no`
**Default:** `no`
**Description:** Enable GPU passthrough for the container.
```bash
var_gpu=yes # Enable GPU passthrough (auto-detect)
var_gpu=no # Disable GPU passthrough (default)
```
**Features enabled:**
- Auto-detects Intel (QuickSync), NVIDIA, and AMD GPUs
- Passes through `/dev/dri` and render nodes
- Configures appropriate container permissions
- Crucial for media servers (Plex, Jellyfin, Immich)
**Prerequisites:**
- Host drivers installed correctly
- Hardware present and visible to Proxmox
- IOMMU enabled (for some configurations)
---
### var_tun
**Type:** Boolean/Toggle
**Options:** `yes` or `no`
**Default:** `no`
**Description:** Enable TUN/TAP device support.
```bash
var_tun=yes # Enable TUN/TAP support
var_tun=no # Disable TUN/TAP support (default)
```
**Required for:**
- VPN software (WireGuard, OpenVPN)
- Network tunneling (Tailscale, ZeroTier)
- Custom network bridges
---
### var_keyctl
**Type:** Boolean (0 or 1)
**Default:** `0`
**Description:** Enable keyctl system call.
```bash
var_keyctl=1 # Keyctl enabled
var_keyctl=0 # Keyctl disabled
```
**Required for:**
- Docker in some configurations
- Systemd keyring features
- Encryption key management
- Some authentication systems
---
### var_fuse
**Type:** Boolean/Toggle
**Options:** `yes` or `no`
**Default:** `no`
**Description:** Enable FUSE filesystem support.
```bash
var_fuse=yes # FUSE enabled
var_fuse=no # FUSE disabled
```
**Required for:**
- sshfs
- AppImage
- Some backup tools
- User-space filesystems
---
### var_mknod
**Type:** Boolean (0 or 1)
**Default:** `0`
**Description:** Allow device node creation.
```bash
var_mknod=1 # Device nodes allowed
var_mknod=0 # Device nodes disabled
```
**Requires:**
- Kernel 5.3+
- Experimental feature
- Use with caution
---
### var_mount_fs
**Type:** String (comma-separated)
**Default:** Empty
**Description:** Allowed mountable filesystems.
```bash
var_mount_fs=nfs
var_mount_fs=nfs,cifs
var_mount_fs=ext4,xfs,nfs
```
**Common Options:**
```
nfs → NFS network shares
cifs → SMB/CIFS shares
ext4 → Ext4 filesystems
xfs → XFS filesystems
btrfs → Btrfs filesystems
```
---
### var_protection
**Type:** Boolean
**Options:** `yes` or `no`
**Default:** `no`
**Description:** Prevent accidental deletion.
```bash
var_protection=yes # Protected from deletion
var_protection=no # Can be deleted normally
```
**When protected:**
- Cannot delete via GUI
- Cannot delete via `pct destroy`
- Must disable protection first
- Good for production containers
---
### var_tags
**Type:** String (comma-separated)
**Default:** `community-script`
**Description:** Container tags for organization.
```bash
var_tags=production
var_tags=production,webserver
var_tags=dev,testing,temporary
```
**Best Practices:**
```bash
# Environment tags
var_tags=production
var_tags=development
var_tags=staging
# Function tags
var_tags=webserver,nginx
var_tags=database,postgresql
var_tags=cache,redis
# Project tags
var_tags=project-alpha,frontend
var_tags=customer-xyz,billing
# Combined
var_tags=production,webserver,project-alpha
```
---
### var_timezone
**Type:** String (TZ database format)
**Default:** Host timezone
**Description:** Container timezone.
```bash
var_timezone=Europe/Berlin
var_timezone=America/New_York
var_timezone=Asia/Tokyo
```
**Common Timezones:**
```
Europe/London
Europe/Berlin
Europe/Paris
America/New_York
America/Chicago
America/Los_Angeles
Asia/Tokyo
Asia/Singapore
Australia/Sydney
UTC
```
**List all timezones:**
```bash
timedatectl list-timezones
```
---
### var_verbose
**Type:** Boolean
**Options:** `yes` or `no`
**Default:** `no`
**Description:** Enable verbose output.
```bash
var_verbose=yes # Show all commands
var_verbose=no # Silent mode
```
**When enabled:**
- Shows all executed commands
- Displays detailed progress
- Useful for debugging
- More log output
---
### var_apt_cacher
**Type:** Boolean
**Options:** `yes` or `no`
**Default:** `no`
**Description:** Use APT caching proxy.
```bash
var_apt_cacher=yes
var_apt_cacher=no
```
**Benefits:**
- Faster package installs
- Reduced bandwidth
- Offline package cache
- Speeds up multiple containers
---
### var_apt_cacher_ip
**Type:** IP Address
**Default:** None
**Description:** APT cacher proxy IP.
```bash
var_apt_cacher=yes
var_apt_cacher_ip=192.168.1.100
```
**Setup apt-cacher-ng:**
```bash
apt install apt-cacher-ng
# Runs on port 3142
```
---
### var_container_storage
**Type:** String
**Default:** Auto-detected
**Description:** Storage for container.
```bash
var_container_storage=local
var_container_storage=local-zfs
var_container_storage=pve-storage
```
**List available storage:**
```bash
pvesm status
```
---
### var_template_storage
**Type:** String
**Default:** Auto-detected
**Description:** Storage for templates.
```bash
var_template_storage=local
var_template_storage=nfs-templates
```
---
## Quick Reference Table
| Variable | Type | Default | Example |
|----------|------|---------|---------|
| `var_unprivileged` | 0/1 | 1 | `var_unprivileged=1` |
| `var_cpu` | int | varies | `var_cpu=4` |
| `var_ram` | int (MB) | varies | `var_ram=4096` |
| `var_disk` | int (GB) | varies | `var_disk=20` |
| `var_hostname` | string | app name | `var_hostname=server` |
| `var_brg` | string | vmbr0 | `var_brg=vmbr1` |
| `var_net` | dhcp/static | dhcp | `var_net=dhcp` |
| `var_gateway` | IP | auto | `var_gateway=192.168.1.1` |
| `var_ipv6_method` | string | none | `var_ipv6_method=disable` |
| `var_vlan` | int | - | `var_vlan=100` |
| `var_mtu` | int | 1500 | `var_mtu=9000` |
| `var_mac` | MAC | auto | `var_mac=02:00:00:00:00:01` |
| `var_ns` | IP | auto | `var_ns=8.8.8.8` |
| `var_ssh` | yes/no | no | `var_ssh=yes` |
| `var_ssh_authorized_key` | string | - | `var_ssh_authorized_key=ssh-rsa...` |
| `var_pw` | string | empty | `var_pw=password` |
| `var_nesting` | 0/1 | 1 | `var_nesting=1` |
| `var_keyctl` | 0/1 | 0 | `var_keyctl=1` |
| `var_fuse` | 0/1 | 0 | `var_fuse=1` |
| `var_mknod` | 0/1 | 0 | `var_mknod=1` |
| `var_mount_fs` | string | - | `var_mount_fs=nfs,cifs` |
| `var_protection` | yes/no | no | `var_protection=yes` |
| `var_tags` | string | community-script | `var_tags=prod,web` |
| `var_timezone` | string | host TZ | `var_timezone=Europe/Berlin` |
| `var_verbose` | yes/no | no | `var_verbose=yes` |
| `var_apt_cacher` | yes/no | no | `var_apt_cacher=yes` |
| `var_apt_cacher_ip` | IP | - | `var_apt_cacher_ip=192.168.1.10` |
| `var_container_storage` | string | auto | `var_container_storage=local-zfs` |
| `var_template_storage` | string | auto | `var_template_storage=local` |
---
## See Also
- [Defaults System Guide](DEFAULTS_GUIDE.md)
- [Unattended Deployments](UNATTENDED_DEPLOYMENTS.md)
- [Security Best Practices](SECURITY_GUIDE.md)
- [Network Configuration](NETWORK_GUIDE.md)

View File

@@ -0,0 +1,760 @@
# Configuration & Defaults System - User Guide
> **Complete Guide to App Defaults and User Defaults**
>
> *Learn how to configure, save, and reuse your installation settings*
---
## Table of Contents
1. [Quick Start](#quick-start)
2. [Understanding the Defaults System](#understanding-the-defaults-system)
3. [Installation Modes](#installation-modes)
4. [How to Save Defaults](#how-to-save-defaults)
5. [How to Use Saved Defaults](#how-to-use-saved-defaults)
6. [Managing Your Defaults](#managing-your-defaults)
7. [Advanced Configuration](#advanced-configuration)
8. [Troubleshooting](#troubleshooting)
---
## Quick Start
### 30-Second Setup
```bash
# 1. Run any container installation script
bash pihole-install.sh
# 2. When prompted, select: "Advanced Settings"
# (This allows you to customize everything)
# 3. Answer all configuration questions
# 4. At the end, when asked "Save as App Defaults?"
# Select: YES
# 5. Done! Your settings are now saved
```
**Next Time**: Run the same script again, select **"App Defaults"** and your settings will be applied automatically!
---
## Understanding the Defaults System
### The Three-Tier System
Your installation settings are managed through three layers:
#### 🔷 **Tier 1: Built-in Defaults** (Fallback)
```
These are hardcoded in the scripts
Provide sensible defaults for each application
Example: PiHole uses 2 CPU cores by default
```
#### 🔶 **Tier 2: User Defaults** (Global)
```
Your personal global defaults
Applied to ALL container installations
Location: /usr/local/community-scripts/default.vars
Example: "I always want 4 CPU cores and 2GB RAM"
```
#### 🔴 **Tier 3: App Defaults** (Specific)
```
Application-specific saved settings
Only applied when installing that specific app
Location: /usr/local/community-scripts/defaults/<appname>.vars
Example: "Whenever I install PiHole, use these exact settings"
```
### Priority System
When installing a container, settings are applied in this order:
```
┌─────────────────────────────────────┐
│ 1. Environment Variables (HIGHEST) │ Set in shell: export var_cpu=8
│ (these override everything) │
├─────────────────────────────────────┤
│ 2. App Defaults │ From: defaults/pihole.vars
│ (app-specific saved settings) │
├─────────────────────────────────────┤
│ 3. User Defaults │ From: default.vars
│ (your global defaults) │
├─────────────────────────────────────┤
│ 4. Built-in Defaults (LOWEST) │ Hardcoded in script
│ (failsafe, always available) │
└─────────────────────────────────────┘
```
**In Plain English**:
- If you set an environment variable → it wins
- Otherwise, if you have app-specific defaults → use those
- Otherwise, if you have user defaults → use those
- Otherwise, use the hardcoded defaults
---
## Installation Modes
When you run any installation script, you'll be presented with a menu:
### Option 1⃣ : **Default Settings**
```
Quick installation with standard settings
├─ Best for: First-time users, quick deployments
├─ What happens:
│ 1. Script uses built-in defaults
│ 2. Container created immediately
│ 3. No questions asked
└─ Time: ~2 minutes
```
**When to use**: You want a standard installation, don't need customization
---
### Option 2⃣ : **Advanced Settings**
```
Full customization with 19 configuration steps
├─ Best for: Power users, custom requirements
├─ What happens:
│ 1. Script asks for EVERY setting
│ 2. You control: CPU, RAM, Disk, Network, SSH, etc.
│ 3. Shows summary before creating
│ 4. Offers to save as App Defaults
└─ Time: ~5-10 minutes
```
**When to use**: You want full control over the configuration
**Available Settings**:
- CPU cores, RAM amount, Disk size
- Container name, network settings
- SSH access, API access, Features
- Password, SSH keys, Tags
---
### Option 3⃣ : **User Defaults**
```
Use your saved global defaults
├─ Best for: Consistent deployments across many containers
├─ Requires: You've previously saved User Defaults
├─ What happens:
│ 1. Loads settings from: /usr/local/community-scripts/default.vars
│ 2. Shows you the loaded settings
│ 3. Creates container immediately
└─ Time: ~2 minutes
```
**When to use**: You have preferred defaults you want to use for every app
---
### Option 4⃣ : **App Defaults** (if available)
```
Use previously saved app-specific defaults
├─ Best for: Repeating the same configuration multiple times
├─ Requires: You've previously saved App Defaults for this app
├─ What happens:
│ 1. Loads settings from: /usr/local/community-scripts/defaults/<app>.vars
│ 2. Shows you the loaded settings
│ 3. Creates container immediately
└─ Time: ~2 minutes
```
**When to use**: You've installed this app before and want identical settings
---
### Option 5⃣ : **Settings Menu**
```
Manage your saved configurations
├─ Functions:
│ • View current settings
│ • Edit storage selections
│ • Manage defaults location
│ • See what's currently configured
└─ Time: ~1 minute
```
**When to use**: You want to review or modify saved settings
---
## How to Save Defaults
### Method 1: Save While Installing
This is the easiest way:
#### Step-by-Step: Create App Defaults
```bash
# 1. Run the installation script
bash pihole-install.sh
# 2. Choose installation mode
# ┌─────────────────────────┐
# │ Select installation mode:│
# │ 1) Default Settings │
# │ 2) Advanced Settings │
# │ 3) User Defaults │
# │ 4) App Defaults │
# │ 5) Settings Menu │
# └─────────────────────────┘
#
# Enter: 2 (Advanced Settings)
# 3. Answer all configuration questions
# • Container name? → my-pihole
# • CPU cores? → 4
# • RAM amount? → 2048
# • Disk size? → 20
# • SSH access? → yes
# ... (more options)
# 4. Review summary (shown before creation)
# ✓ Confirm to proceed
# 5. After creation completes, you'll see:
# ┌──────────────────────────────────┐
# │ Save as App Defaults for PiHole? │
# │ (Yes/No) │
# └──────────────────────────────────┘
#
# Select: Yes
# 6. Done! Settings saved to:
# /usr/local/community-scripts/defaults/pihole.vars
```
#### Step-by-Step: Create User Defaults
```bash
# Same as App Defaults, but:
# When you select "Advanced Settings"
# FIRST app you run with this selection will offer
# to save as "User Defaults" additionally
# This saves to: /usr/local/community-scripts/default.vars
```
---
### Method 2: Manual File Creation
For advanced users who want to create defaults without running installation:
```bash
# Create User Defaults manually
sudo tee /usr/local/community-scripts/default.vars > /dev/null << 'EOF'
# Global User Defaults
var_cpu=4
var_ram=2048
var_disk=20
var_unprivileged=1
var_brg=vmbr0
var_gateway=192.168.1.1
var_timezone=Europe/Berlin
var_ssh=yes
var_container_storage=local
var_template_storage=local
EOF
# Create App Defaults manually
sudo tee /usr/local/community-scripts/defaults/pihole.vars > /dev/null << 'EOF'
# App-specific defaults for PiHole
var_unprivileged=1
var_cpu=2
var_ram=1024
var_disk=10
var_brg=vmbr0
var_gateway=192.168.1.1
var_hostname=pihole
var_container_storage=local
var_template_storage=local
EOF
```
---
### Method 3: Using Environment Variables
Set defaults via environment before running:
```bash
# Set as environment variables
export var_cpu=4
export var_ram=2048
export var_disk=20
export var_hostname=my-container
# Run installation
bash pihole-install.sh
# These settings will be used
# (Can still be overridden by saved defaults)
```
---
## How to Use Saved Defaults
### Using User Defaults
```bash
# 1. Run any installation script
bash pihole-install.sh
# 2. When asked for mode, select:
# Option: 3 (User Defaults)
# 3. Your settings from default.vars are applied
# 4. Container created with your saved settings
```
### Using App Defaults
```bash
# 1. Run the app you configured before
bash pihole-install.sh
# 2. When asked for mode, select:
# Option: 4 (App Defaults)
# 3. Your settings from defaults/pihole.vars are applied
# 4. Container created with exact same settings
```
### Overriding Saved Defaults
```bash
# Even if you have defaults saved,
# you can override them with environment variables
export var_cpu=8 # Override saved defaults
export var_hostname=custom-name
bash pihole-install.sh
# Installation will use these values instead of saved defaults
```
---
## Managing Your Defaults
### View Your Settings
#### View User Defaults
```bash
cat /usr/local/community-scripts/default.vars
```
#### View App Defaults
```bash
cat /usr/local/community-scripts/defaults/pihole.vars
```
#### List All Saved App Defaults
```bash
ls -la /usr/local/community-scripts/defaults/
```
### Edit Your Settings
#### Edit User Defaults
```bash
sudo nano /usr/local/community-scripts/default.vars
```
#### Edit App Defaults
```bash
sudo nano /usr/local/community-scripts/defaults/pihole.vars
```
### Update Existing Defaults
```bash
# Run installation again with your app
bash pihole-install.sh
# Select: Advanced Settings
# Make desired changes
# At end, when asked to save:
# "Defaults already exist, Update?"
# Select: Yes
# Your saved defaults are updated
```
### Delete Defaults
#### Delete User Defaults
```bash
sudo rm /usr/local/community-scripts/default.vars
```
#### Delete App Defaults
```bash
sudo rm /usr/local/community-scripts/defaults/pihole.vars
```
#### Delete All App Defaults
```bash
sudo rm /usr/local/community-scripts/defaults/*
```
---
## Advanced Configuration
### Available Variables
All configurable variables start with `var_`:
#### Resource Allocation
```bash
var_cpu=4 # CPU cores
var_ram=2048 # RAM in MB
var_disk=20 # Disk in GB
var_unprivileged=1 # 0=privileged, 1=unprivileged
```
#### Network
```bash
var_brg=vmbr0 # Bridge interface
var_net=dhcp # dhcp, static IP/CIDR, or IP range (see below)
var_gateway=192.168.1.1 # Default gateway (required for static IP)
var_mtu=1500 # MTU size
var_vlan=100 # VLAN ID
```
#### IP Range Scanning
You can specify an IP range instead of a static IP. The system will ping each IP in the range and automatically assign the first free IP:
```bash
# Format: START_IP/CIDR-END_IP/CIDR
var_net=192.168.1.100/24-192.168.1.200/24
var_gateway=192.168.1.1
```
This is useful for automated deployments where you want static IPs but don't want to track which IPs are already in use.
#### System
```bash
var_hostname=pihole # Container name
var_timezone=Europe/Berlin # Timezone
var_pw=SecurePass123 # Root password
var_tags=dns,pihole # Tags for organization
var_verbose=yes # Enable verbose output
```
#### Security & Access
```bash
var_ssh=yes # Enable SSH
var_ssh_authorized_key="ssh-rsa AA..." # SSH public key
var_protection=1 # Enable protection flag
```
#### Features
```bash
var_fuse=1 # FUSE filesystem support
var_tun=1 # TUN device support
var_nesting=1 # Nesting (Docker in LXC)
var_keyctl=1 # Keyctl syscall
var_mknod=1 # Device node creation
```
#### Storage
```bash
var_container_storage=local # Where to store container
var_template_storage=local # Where to store templates
```
### Example Configuration Files
#### Gaming Server Defaults
```bash
# High performance for gaming containers
var_cpu=8
var_ram=4096
var_disk=50
var_unprivileged=0
var_fuse=1
var_nesting=1
var_tags=gaming
```
#### Development Server
```bash
# Development with Docker support
var_cpu=4
var_ram=2048
var_disk=30
var_unprivileged=1
var_nesting=1
var_ssh=yes
var_tags=development
```
#### IoT/Monitoring
```bash
# Low-resource, always-on containers
var_cpu=2
var_ram=512
var_disk=10
var_unprivileged=1
var_nesting=0
var_fuse=0
var_tun=0
var_tags=iot,monitoring
```
---
## Troubleshooting
### "App Defaults not available" Message
**Problem**: You want to use App Defaults, but option says they're not available
**Solution**:
1. You haven't created App Defaults yet for this app
2. Run the app with "Advanced Settings"
3. When finished, save as App Defaults
4. Next time, App Defaults will be available
---
### "Settings not being applied"
**Problem**: You saved defaults, but they're not being used
**Checklist**:
```bash
# 1. Verify files exist
ls -la /usr/local/community-scripts/default.vars
ls -la /usr/local/community-scripts/defaults/<app>.vars
# 2. Check file permissions (should be readable)
stat /usr/local/community-scripts/default.vars
# 3. Verify correct mode selected
# (Make sure you selected "User Defaults" or "App Defaults")
# 4. Check for environment variable override
env | grep var_
# If you have var_* set in environment,
# those override your saved defaults
```
---
### "Cannot write to defaults location"
**Problem**: Permission denied when saving defaults
**Solution**:
```bash
# Create the defaults directory if missing
sudo mkdir -p /usr/local/community-scripts/defaults
# Fix permissions
sudo chmod 755 /usr/local/community-scripts
sudo chmod 755 /usr/local/community-scripts/defaults
# Make sure you're running as root
sudo bash pihole-install.sh
```
---
### "Defaults directory doesn't exist"
**Problem**: Script can't find where to save defaults
**Solution**:
```bash
# Create the directory
sudo mkdir -p /usr/local/community-scripts/defaults
# Verify
ls -la /usr/local/community-scripts/
```
---
### Settings seem random or wrong
**Problem**: Container gets different settings than expected
**Possible Causes & Solutions**:
```bash
# 1. Check if environment variables are set
env | grep var_
# If you see var_* entries, those override your defaults
# Clear them: unset var_cpu var_ram (etc)
# 2. Verify correct defaults are in files
cat /usr/local/community-scripts/default.vars
cat /usr/local/community-scripts/defaults/pihole.vars
# 3. Check which mode you actually selected
# (Script output shows which defaults were applied)
# 4. Check Proxmox logs for errors
sudo journalctl -u pve-daemon -n 50
```
---
### "Variable not recognized"
**Problem**: You set a variable that doesn't work
**Solution**:
Only certain variables are allowed (security whitelist):
```
Allowed variables (starting with var_):
✓ var_cpu, var_ram, var_disk, var_unprivileged
✓ var_brg, var_gateway, var_mtu, var_vlan, var_net
✓ var_hostname, var_pw, var_timezone
✓ var_ssh, var_ssh_authorized_key
✓ var_fuse, var_tun, var_nesting, var_keyctl
✓ var_container_storage, var_template_storage
✓ var_tags, var_verbose
✓ var_apt_cacher, var_apt_cacher_ip
✓ var_protection, var_mount_fs
✗ Other variables are NOT supported
```
---
## Best Practices
### ✅ Do's
✓ Use **App Defaults** when you want app-specific settings
✓ Use **User Defaults** for your global preferences
✓ Edit defaults files directly with `nano` (safe)
✓ Keep separate App Defaults for each app
✓ Back up your defaults regularly
✓ Use environment variables for temporary overrides
### ❌ Don'ts
✗ Don't use `source` on defaults files (security risk)
✗ Don't put sensitive passwords in defaults (use SSH keys)
✗ Don't modify defaults while installation is running
✗ Don't delete defaults.d while containers are being created
✗ Don't use special characters without escaping
---
## Quick Reference
### Defaults Locations
| Type | Location | Example |
|------|----------|---------|
| User Defaults | `/usr/local/community-scripts/default.vars` | Global settings |
| App Defaults | `/usr/local/community-scripts/defaults/<app>.vars` | PiHole-specific |
| Backup Dir | `/usr/local/community-scripts/defaults/` | All app defaults |
### File Format
```bash
# Comments start with #
var_name=value
# No spaces around =
var_cpu=4
var_cpu = 4
# String values don't need quotes
var_hostname=mycontainer
var_hostname='mycontainer'
# Values with spaces need quotes
var_tags="docker,production,testing"
var_tags=docker,production,testing
```
### Command Reference
```bash
# View defaults
cat /usr/local/community-scripts/default.vars
# Edit defaults
sudo nano /usr/local/community-scripts/default.vars
# List all app defaults
ls /usr/local/community-scripts/defaults/
# Backup your defaults
cp -r /usr/local/community-scripts/defaults/ ~/defaults-backup/
# Set temporary override
export var_cpu=8
bash pihole-install.sh
# Create custom defaults
sudo tee /usr/local/community-scripts/defaults/custom.vars << 'EOF'
var_cpu=4
var_ram=2048
EOF
```
---
## Getting Help
### Need More Information?
- 📖 [Main Documentation](../../docs/)
- 🐛 [Report Issues](https://github.com/community-scripts/ProxmoxVE/issues)
- 💬 [Discussions](https://github.com/community-scripts/ProxmoxVE/discussions)
### Useful Commands
```bash
# Check what variables are available
grep "var_" /path/to/app-install.sh | head -20
# Verify defaults syntax
cat /usr/local/community-scripts/default.vars
# Monitor installation with defaults
bash pihole-install.sh 2>&1 | tee installation.log
```
---
## Document Information
| Field | Value |
|-------|-------|
| Version | 1.0 |
| Last Updated | November 28, 2025 |
| Status | Current |
| License | MIT |
---
**Happy configuring! 🚀**

58
docs/guides/README.md Normal file
View File

@@ -0,0 +1,58 @@
# Configuration & Deployment Guides
This directory contains comprehensive guides for configuring and deploying Proxmox VE containers using community-scripts.
## 📚 Available Guides
### [Configuration Reference](CONFIGURATION_REFERENCE.md)
Complete reference for all configuration options, environment variables, and advanced settings available in the build system.
**Topics covered:**
- Container specifications (CPU, RAM, Disk)
- Network configuration (IPv4/IPv6, VLAN, MTU)
- Storage selection and management
- Privilege modes and features
- OS selection and versions
### [Defaults System Guide](DEFAULTS_SYSTEM_GUIDE.md)
Understanding and customizing default settings for container deployments.
**Topics covered:**
- Default system settings
- Per-script overrides
- Custom defaults configuration
- Environment variable precedence
### [Unattended Deployments](UNATTENDED_DEPLOYMENTS.md)
Automating container deployments without user interaction.
**Topics covered:**
- Environment variable configuration
- Batch deployments
- CI/CD integration
- Scripted installations
- Pre-configured templates
## 🔗 Related Documentation
- **[CT Scripts Guide](../ct/)** - Container script structure and usage
- **[Install Scripts Guide](../install/)** - Installation script internals
- **[API Documentation](../api/)** - API integration and endpoints
- **[Build Functions](../misc/build.func/)** - Build system functions reference
- **[Tools Functions](../misc/tools.func/)** - Utility functions reference
## 💡 Quick Start
For most users, start with the **Unattended Deployments** guide to learn how to automate your container setups.
For advanced configuration options, refer to the **Configuration Reference**.
## 🤝 Contributing
If you'd like to improve these guides or add new ones, please see our [Contribution Guide](../contribution/).

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
<div align="center">
<a href="#">
<img src="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo.png" height="100px" />
</a>
</div>
<h2 align="center">User Submitted Guides </h2>
<sub> In order to contribute a guide on installing with Proxmox VE Helper Scripts, you should open a pull request that adds the guide to the `USER_SUBMITTED_GUIDES.md` file. </sub>
[Proxmox Automation with Proxmox Helper Scripts!](https://www.youtube.com/watch?v=kcpu4z5eSEU)
[Installing Home Assistant OS using Proxmox 8](https://community.home-assistant.io/t/installing-home-assistant-os-using-proxmox-8/201835)
[How To Separate Zigbee2MQTT From Home Assistant In Proxmox](https://smarthomescene.com/guides/how-to-separate-zigbee2mqtt-from-home-assistant-in-proxmox/)
[How To Install Home Assistant On Proxmox: The Easy Way](https://smarthomescene.com/guides/how-to-install-home-assistant-on-proxmox-the-easy-way/)
[Home Assistant: Installing InfluxDB (LXC)](https://www.derekseaman.com/2023/04/home-assistant-installing-influxdb-lxc.html)
[Home Assistant: Proxmox Quick Start Guide](https://www.derekseaman.com/2023/10/home-assistant-proxmox-ve-8-0-quick-start-guide-2.html)
[Home Assistant: Installing Grafana (LXC) with Lets Encrypt SSL](https://www.derekseaman.com/2023/04/home-assistant-installing-grafana-lxc.html)
[Proxmox: Plex LXC with Alder Lake Transcoding](https://www.derekseaman.com/2023/04/proxmox-plex-lxc-with-alder-lake-transcoding.html)
[How To Backup Home Assistant In Proxmox](https://smarthomescene.com/guides/how-to-backup-home-assistant-in-proxmox/)
[Running Frigate on Proxmox](https://www.homeautomationguy.io/blog/running-frigate-on-proxmox)
[Frigate VM on Proxmox with PCIe Coral TPU](https://www.derekseaman.com/2023/06/home-assistant-frigate-vm-on-proxmox-with-pcie-coral-tpu.html)
[Moving Home Assistants Database To MariaDB On Proxmox](https://smarthomescene.com/guides/moving-home-assistants-database-to-mariadb-on-proxmox/)
[How-to: Proxmox VE 7.4 to 8.0 Upgrade](https://www.derekseaman.com/2023/06/how-to-proxmox-7-4-to-8-0-upgrade.html)
[iGPU Transcoding In Proxmox with Jellyfin](https://www.youtube.com/watch?v=XAa_qpNmzZs)
[Proxmox + NetData](<https://dbt3ch.com/books/proxmox-netdata-for-better-insights-and-notifications/page/proxmox-netdata-for-better-insights-and-notifications>)
[Proxmox Homelab Series](<https://blog.kye.dev/proxmox-series>)
[The fastest installation of Docker and Portainer on Proxmox VE](https://lavr.site/en-fastest-install-docker-portainer-proxmox/)
[How To Setup Proxmox Backuper Server Using Helper Scripts](<https://youtu.be/6C2JOsrZZZw?si=kkrrcL_nLCDBJkOB>)

View File

@@ -0,0 +1,647 @@
# 🛠️ **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-2026 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-2026 community-scripts ORG
# Author: YourUsername
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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
setup_mariadb # Uses distribution packages (recommended)
# Or for specific version: 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**: ProxmoxVE with install.func v3+

160
docs/install/README.md Normal file
View File

@@ -0,0 +1,160 @@
# Installation Scripts Documentation (/install)
This directory contains comprehensive documentation for installation scripts in the `/install` directory.
## Overview
Installation scripts (`install/*.sh`) run inside LXC containers and handle application-specific setup, configuration, and deployment.
## Documentation Structure
Each installation script category has documentation following the project pattern.
## Key Resources
- **[DETAILED_GUIDE.md](DETAILED_GUIDE.md)** - Complete reference for creating install scripts
- **[../contribution/README.md](../contribution/README.md)** - How to contribute
- **[../misc/install.func/](../misc/install.func/)** - Installation workflow documentation
- **[../misc/tools.func/](../misc/tools.func/)** - Package installation documentation
## Installation Script Flow
```
install/appname-install.sh (container-side)
├─ Sources: $FUNCTIONS_FILE_PATH
│ ├─ core.func (messaging)
│ ├─ error_handler.func (error handling)
│ ├─ install.func (setup)
│ └─ tools.func (packages & tools)
├─ 10-Phase Installation:
│ 1. OS Setup
│ 2. Base Dependencies
│ 3. Tool Setup
│ 4. Application Download
│ 5. Configuration
│ 6. Database Setup
│ 7. Permissions
│ 8. Services
│ 9. Version Tracking
│ 10. Final Cleanup
└─ Result: Application ready
```
## Available Installation Scripts
See `/install` directory for all installation scripts. Examples:
- `pihole-install.sh` - Pi-hole installation
- `docker-install.sh` - Docker installation
- `wallabag-install.sh` - Wallabag setup
- `nextcloud-install.sh` - Nextcloud deployment
- `debian-install.sh` - Base Debian setup
- And 30+ more...
## Quick Start
To understand how to create an installation script:
1. Read: [UPDATED_APP-install.md](../UPDATED_APP-install.md)
2. Study: A similar existing script in `/install`
3. Copy template and customize
4. Test in container
5. Submit PR
## 10-Phase Installation Pattern
Every installation script follows this structure:
### Phase 1: OS Setup
```bash
setting_up_container
network_check
update_os
```
### Phase 2: Base Dependencies
```bash
pkg_update
pkg_install curl wget git
```
### Phase 3: Tool Setup
```bash
setup_nodejs "20"
setup_php "8.3"
setup_mariadb # Uses distribution packages (recommended)
# MARIADB_VERSION="11.4" setup_mariadb # For specific version
```
### Phase 4: Application Download
```bash
git clone https://github.com/user/app /opt/app
cd /opt/app
```
### Phase 5: Configuration
```bash
# Create .env files, config files, etc.
cat > .env <<EOF
SETTING=value
EOF
```
### Phase 6: Database Setup
```bash
# Create databases, users, etc.
mysql -e "CREATE DATABASE appdb"
```
### Phase 7: Permissions
```bash
chown -R appuser:appgroup /opt/app
chmod -R 755 /opt/app
```
### Phase 8: Services
```bash
systemctl enable app
systemctl start app
```
### Phase 9: Version Tracking
```bash
echo "1.0.0" > /opt/app_version.txt
```
### Phase 10: Final Cleanup
```bash
motd_ssh
customize
cleanup_lxc
```
## Contributing an Installation Script
1. Create `ct/myapp.sh` (host script)
2. Create `install/myapp-install.sh` (container script)
3. Follow 10-phase pattern in [UPDATED_APP-install.md](../UPDATED_APP-install.md)
4. Test in actual container
5. Submit PR with both files
## Common Tasks
- **Create new installation script** → [UPDATED_APP-install.md](../UPDATED_APP-install.md)
- **Install Node.js/PHP/Database** → [misc/tools.func/](../misc/tools.func/)
- **Setup Alpine container** → [misc/alpine-install.func/](../misc/alpine-install.func/)
- **Debug installation errors** → [EXIT_CODES.md](../EXIT_CODES.md)
- **Use dev mode** → [DEV_MODE.md](../DEV_MODE.md)
## Alpine vs Debian
- **Debian-based** → Use `tools.func`, `install.func`, `systemctl`
- **Alpine-based** → Use `alpine-tools.func`, `alpine-install.func`, `rc-service`
---
**Last Updated**: December 2025
**Maintainers**: community-scripts team

283
docs/misc/README.md Normal file
View File

@@ -0,0 +1,283 @@
# Misc Documentation
This directory contains comprehensive documentation for all function libraries and components of the Proxmox Community Scripts project. Each section is organized as a dedicated subdirectory with detailed references, examples, and integration guides.
---
## 🏗️ **Core Function Libraries**
### 📁 [build.func/](./build.func/)
**Core LXC Container Orchestration** - Main orchestrator for Proxmox LXC container creation
**Contents:**
- BUILD_FUNC_FLOWCHART.md - Visual execution flows and decision trees
- BUILD_FUNC_ARCHITECTURE.md - System architecture and design
- BUILD_FUNC_ENVIRONMENT_VARIABLES.md - Complete environment variable reference
- BUILD_FUNC_FUNCTIONS_REFERENCE.md - Alphabetical function reference
- BUILD_FUNC_EXECUTION_FLOWS.md - Detailed execution flows
- BUILD_FUNC_USAGE_EXAMPLES.md - Practical usage examples
- README.md - Overview and quick reference
**Key Functions**: `variables()`, `start()`, `build_container()`, `build_defaults()`, `advanced_settings()`
---
### 📁 [core.func/](./core.func/)
**System Utilities & Foundation** - Essential utility functions and system checks
**Contents:**
- CORE_FLOWCHART.md - Visual execution flows
- CORE_FUNCTIONS_REFERENCE.md - Complete function reference
- CORE_INTEGRATION.md - Integration points
- CORE_USAGE_EXAMPLES.md - Practical examples
- README.md - Overview and quick reference
**Key Functions**: `color()`, `msg_info()`, `msg_ok()`, `msg_error()`, `root_check()`, `pve_check()`, `parse_dev_mode()`
---
### 📁 [error_handler.func/](./error_handler.func/)
**Error Handling & Signal Management** - Comprehensive error handling and signal trapping
**Contents:**
- ERROR_HANDLER_FLOWCHART.md - Visual error handling flows
- ERROR_HANDLER_FUNCTIONS_REFERENCE.md - Function reference
- ERROR_HANDLER_INTEGRATION.md - Integration with other components
- ERROR_HANDLER_USAGE_EXAMPLES.md - Practical examples
- README.md - Overview and quick reference
**Key Functions**: `catch_errors()`, `error_handler()`, `explain_exit_code()`, `signal_handler()`
---
### 📁 [api.func/](./api.func/)
**Proxmox API Integration** - API communication and diagnostic reporting
**Contents:**
- API_FLOWCHART.md - API communication flows
- API_FUNCTIONS_REFERENCE.md - Function reference
- API_INTEGRATION.md - Integration points
- API_USAGE_EXAMPLES.md - Practical examples
- README.md - Overview and quick reference
**Key Functions**: `post_to_api()`, `post_update_to_api()`, `get_error_description()`
---
## 📦 **Installation & Setup Function Libraries**
### 📁 [install.func/](./install.func/)
**Container Installation Workflow** - Installation orchestration for container-internal setup
**Contents:**
- INSTALL_FUNC_FLOWCHART.md - Installation workflow diagrams
- INSTALL_FUNC_FUNCTIONS_REFERENCE.md - Complete function reference
- INSTALL_FUNC_INTEGRATION.md - Integration with build and tools
- INSTALL_FUNC_USAGE_EXAMPLES.md - Practical examples
- README.md - Overview and quick reference
**Key Functions**: `setting_up_container()`, `network_check()`, `update_os()`, `motd_ssh()`, `cleanup_lxc()`
---
### 📁 [tools.func/](./tools.func/)
**Package & Tool Installation** - Robust package management and 30+ tool installation functions
**Contents:**
- TOOLS_FUNC_FLOWCHART.md - Package management flows
- TOOLS_FUNC_FUNCTIONS_REFERENCE.md - 30+ function reference
- TOOLS_FUNC_INTEGRATION.md - Integration with install workflows
- TOOLS_FUNC_USAGE_EXAMPLES.md - Practical examples
- TOOLS_FUNC_ENVIRONMENT_VARIABLES.md - Configuration reference
- README.md - Overview and quick reference
**Key Functions**: `setup_nodejs()`, `setup_php()`, `setup_mariadb()`, `setup_docker()`, `setup_deb822_repo()`, `pkg_install()`, `pkg_update()`
---
### 📁 [alpine-install.func/](./alpine-install.func/)
**Alpine Container Setup** - Alpine Linux-specific installation functions
**Contents:**
- ALPINE_INSTALL_FUNC_FLOWCHART.md - Alpine setup flows
- ALPINE_INSTALL_FUNC_FUNCTIONS_REFERENCE.md - Function reference
- ALPINE_INSTALL_FUNC_INTEGRATION.md - Integration points
- ALPINE_INSTALL_FUNC_USAGE_EXAMPLES.md - Practical examples
- README.md - Overview and quick reference
**Key Functions**: `update_os()` (apk version), `verb_ip6()`, `motd_ssh()` (Alpine), `customize()`
---
### 📁 [alpine-tools.func/](./alpine-tools.func/)
**Alpine Tool Installation** - Alpine-specific package and tool installation
**Contents:**
- ALPINE_TOOLS_FUNC_FLOWCHART.md - Alpine package flows
- ALPINE_TOOLS_FUNC_FUNCTIONS_REFERENCE.md - Function reference
- ALPINE_TOOLS_FUNC_INTEGRATION.md - Integration with Alpine workflows
- ALPINE_TOOLS_FUNC_USAGE_EXAMPLES.md - Practical examples
- README.md - Overview and quick reference
**Key Functions**: `apk_add()`, `apk_update()`, `apk_del()`, `add_community_repo()`, Alpine tool setup functions
---
### 📁 [cloud-init.func/](./cloud-init.func/)
**VM Cloud-Init Configuration** - Cloud-init and VM provisioning functions
**Contents:**
- CLOUD_INIT_FUNC_FLOWCHART.md - Cloud-init flows
- CLOUD_INIT_FUNC_FUNCTIONS_REFERENCE.md - Function reference
- CLOUD_INIT_FUNC_INTEGRATION.md - Integration points
- CLOUD_INIT_FUNC_USAGE_EXAMPLES.md - Practical examples
- README.md - Overview and quick reference
**Key Functions**: `generate_cloud_init()`, `generate_user_data()`, `setup_ssh_keys()`, `setup_static_ip()`
---
## 🔗 **Function Library Relationships**
```
┌─────────────────────────────────────────────┐
│ Container Creation Flow │
├─────────────────────────────────────────────┤
│ │
│ ct/AppName.sh │
│ ↓ (sources) │
│ build.func │
│ ├─ variables() │
│ ├─ build_container() │
│ └─ advanced_settings() │
│ ↓ (calls pct create with) │
│ install/appname-install.sh │
│ ↓ (sources) │
│ ├─ core.func (colors, messaging) │
│ ├─ error_handler.func (error trapping) │
│ ├─ install.func (setup/network) │
│ └─ tools.func (packages/tools) │
│ │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ Alpine Container Flow │
├─────────────────────────────────────────────┤
│ │
│ install/appname-install.sh (Alpine) │
│ ↓ (sources) │
│ ├─ core.func (colors) │
│ ├─ error_handler.func (errors) │
│ ├─ alpine-install.func (apk setup) │
│ └─ alpine-tools.func (apk tools) │
│ │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ VM Provisioning Flow │
├─────────────────────────────────────────────┤
│ │
│ vm/OsName-vm.sh │
│ ↓ (uses) │
│ cloud-init.func │
│ ├─ generate_cloud_init() │
│ ├─ setup_ssh_keys() │
│ └─ configure_network() │
│ │
└─────────────────────────────────────────────┘
```
---
## 📊 **Documentation Quick Stats**
| Library | Files | Functions | Status |
|---------|:---:|:---:|:---:|
| build.func | 7 | 50+ | ✅ Complete |
| core.func | 5 | 20+ | ✅ Complete |
| error_handler.func | 5 | 10+ | ✅ Complete |
| api.func | 5 | 5+ | ✅ Complete |
| install.func | 5 | 8+ | ✅ Complete |
| tools.func | 6 | 30+ | ✅ Complete |
| alpine-install.func | 5 | 6+ | ✅ Complete |
| alpine-tools.func | 5 | 15+ | ✅ Complete |
| cloud-init.func | 5 | 12+ | ✅ Complete |
**Total**: 9 function libraries, 48 documentation files, 150+ functions
---
## 🚀 **Getting Started**
### For Container Creation Scripts
Start with: **[build.func/](./build.func/)** → **[tools.func/](./tools.func/)** → **[install.func/](./install.func/)**
### For Alpine Containers
Start with: **[alpine-install.func/](./alpine-install.func/)** → **[alpine-tools.func/](./alpine-tools.func/)**
### For VM Provisioning
Start with: **[cloud-init.func/](./cloud-init.func/)**
### For Troubleshooting
Start with: **[error_handler.func/](./error_handler.func/)** → **[EXIT_CODES.md](../EXIT_CODES.md)**
---
## 📚 **Related Top-Level Documentation**
- **[CONTRIBUTION_GUIDE.md](../CONTRIBUTION_GUIDE.md)** - How to contribute to ProxmoxVE
- **[UPDATED_APP-ct.md](../UPDATED_APP-ct.md)** - Container script guide
- **[UPDATED_APP-install.md](../UPDATED_APP-install.md)** - Installation script guide
- **[DEFAULTS_SYSTEM_GUIDE.md](../DEFAULTS_SYSTEM_GUIDE.md)** - Configuration system
- **[TECHNICAL_REFERENCE.md](../TECHNICAL_REFERENCE.md)** - Architecture reference
- **[EXIT_CODES.md](../EXIT_CODES.md)** - Complete exit code reference
- **[DEV_MODE.md](../DEV_MODE.md)** - Development debugging modes
- **[CHANGELOG_MISC.md](../CHANGELOG_MISC.md)** - Change history
---
## 🔄 **Standardized Documentation Structure**
Each function library follows the same documentation pattern:
```
function-library/
├── README.md # Quick reference & overview
├── FUNCTION_LIBRARY_FLOWCHART.md # Visual execution flows
├── FUNCTION_LIBRARY_FUNCTIONS_REFERENCE.md # Alphabetical reference
├── FUNCTION_LIBRARY_INTEGRATION.md # Integration points
├── FUNCTION_LIBRARY_USAGE_EXAMPLES.md # Practical examples
└── [FUNCTION_LIBRARY_ENVIRONMENT_VARIABLES.md] # (if applicable)
```
**Advantages**:
- ✅ Consistent navigation across all libraries
- ✅ Quick reference sections in each README
- ✅ Visual flowcharts for understanding
- ✅ Complete function references
- ✅ Real-world usage examples
- ✅ Integration guides for connecting libraries
---
## 📝 **Documentation Standards**
All documentation follows these standards:
1. **README.md** - Quick overview, key features, quick reference
2. **FLOWCHART.md** - ASCII flowcharts and visual diagrams
3. **FUNCTIONS_REFERENCE.md** - Every function with full details
4. **INTEGRATION.md** - How this library connects to others
5. **USAGE_EXAMPLES.md** - Copy-paste ready examples
6. **ENVIRONMENT_VARIABLES.md** - (if applicable) Configuration reference
---
## ✅ **Last Updated**: December 2025
**Maintainers**: community-scripts team
**License**: MIT
**Status**: All 9 libraries fully documented and standardized
---
*This directory contains specialized documentation for specific components of the Proxmox Community Scripts project.*

View File

@@ -0,0 +1,29 @@
# alpine-install.func Flowchart
Alpine container initialization flow (apk-based, OpenRC init system).
## Alpine Container Setup Flow
```
Alpine Container Started
setting_up_container()
verb_ip6() [optional - IPv6]
update_os() [apk update/upgrade]
network_check()
Application Installation
motd_ssh()
customize()
cleanup_lxc()
Complete ✓
```
**Last Updated**: December 2025

View File

@@ -0,0 +1,30 @@
# alpine-install.func Functions Reference
Alpine Linux-specific installation functions (apk-based, OpenRC).
## Core Functions
### setting_up_container()
Initialize Alpine container setup.
### update_os()
Update Alpine packages via `apk update && apk upgrade`.
### verb_ip6()
Enable IPv6 on Alpine with persistent configuration.
### network_check()
Verify network connectivity in Alpine.
### motd_ssh()
Configure SSH daemon and MOTD on Alpine.
### customize()
Apply Alpine-specific customizations.
### cleanup_lxc()
Final cleanup (Alpine-specific).
---
**Last Updated**: December 2025

View File

@@ -0,0 +1,14 @@
# alpine-install.func Integration Guide
Integration of alpine-install.func with Alpine container workflows.
## Alpine-Specific Integration
Alpine containers use:
- `apk` instead of `apt-get`
- `OpenRC` instead of `systemd`
- Alpine-specific package names
---
**Last Updated**: December 2025

View File

@@ -0,0 +1,24 @@
# alpine-install.func Usage Examples
Basic examples for Alpine container installation.
### Example: Basic Alpine Setup
```bash
#!/usr/bin/env bash
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
setting_up_container
update_os
# Install Alpine packages
apk add --no-cache curl wget git
motd_ssh
customize
cleanup_lxc
```
---
**Last Updated**: December 2025

View File

@@ -0,0 +1,273 @@
# alpine-install.func Documentation
## Overview
The `alpine-install.func` file provides Alpine Linux-specific installation and configuration functions for LXC containers. It complements the standard `install.func` with Alpine-specific operations using the apk package manager instead of apt.
## Purpose and Use Cases
- **Alpine Container Setup**: Initialize Alpine Linux containers with proper configuration
- **IPv6 Management**: Enable or disable IPv6 in Alpine with persistent configuration
- **Network Verification**: Verify connectivity in Alpine environments
- **SSH Configuration**: Setup SSH daemon on Alpine
- **Auto-Login Setup**: Configure passwordless root login for Alpine containers
- **Package Management**: Safe apk operations with error handling
## Quick Reference
### Key Function Groups
- **Initialization**: `setting_up_container()` - Alpine setup message
- **Network**: `verb_ip6()`, `network_check()` - IPv6 and connectivity
- **OS Configuration**: `update_os()` - Alpine package updates
- **SSH/MOTD**: `motd_ssh()` - SSH and login message setup
- **Container Customization**: `customize()`, `cleanup_lxc()` - Final setup
### Dependencies
- **External**: `apk`, `curl`, `wget`, `ping`
- **Internal**: Uses functions from `core.func`, `error_handler.func`
### Integration Points
- Used by: Alpine-based install scripts (alpine.sh, alpine-ntfy.sh, etc.)
- Uses: Environment variables from build.func
- Provides: Alpine-specific installation and management services
## Documentation Files
### 📊 [ALPINE_INSTALL_FUNC_FLOWCHART.md](./ALPINE_INSTALL_FUNC_FLOWCHART.md)
Visual execution flows showing Alpine container initialization and setup workflows.
### 📚 [ALPINE_INSTALL_FUNC_FUNCTIONS_REFERENCE.md](./ALPINE_INSTALL_FUNC_FUNCTIONS_REFERENCE.md)
Complete alphabetical reference of all functions with parameters and usage details.
### 💡 [ALPINE_INSTALL_FUNC_USAGE_EXAMPLES.md](./ALPINE_INSTALL_FUNC_USAGE_EXAMPLES.md)
Practical examples showing how to use Alpine installation functions.
### 🔗 [ALPINE_INSTALL_FUNC_INTEGRATION.md](./ALPINE_INSTALL_FUNC_INTEGRATION.md)
How alpine-install.func integrates with standard install workflows.
## Key Features
### Alpine-Specific Functions
- **apk Package Manager**: Alpine package operations (instead of apt-get)
- **OpenRC Support**: Alpine uses OpenRC init instead of systemd
- **Lightweight Setup**: Minimal dependencies appropriate for Alpine
- **IPv6 Configuration**: Persistent IPv6 settings via `/etc/network/interfaces`
### Network & Connectivity
- **IPv6 Toggle**: Enable/disable with persistent configuration
- **Connectivity Check**: Verify internet access in Alpine
- **DNS Verification**: Resolve domain names correctly
- **Retry Logic**: Automatic recovery from transient failures
### SSH & Auto-Login
- **SSH Daemon**: Setup and start sshd on Alpine
- **Root Keys**: Configure root SSH access
- **Auto-Login**: Optional automatic login without password
- **MOTD**: Custom login message on Alpine
## Function Categories
### 🔹 Core Functions
- `setting_up_container()` - Alpine container setup message
- `update_os()` - Update Alpine packages via apk
- `verb_ip6()` - Enable/disable IPv6 persistently
- `network_check()` - Verify network connectivity
### 🔹 SSH & Configuration Functions
- `motd_ssh()` - Configure SSH daemon on Alpine
- `customize()` - Apply Alpine-specific customizations
- `cleanup_lxc()` - Final cleanup
### 🔹 Service Management (OpenRC)
- `rc-update` - Enable/disable services for Alpine
- `rc-service` - Start/stop services on Alpine
- Service configuration files in `/etc/init.d/`
## Differences from Debian Install
| Feature | Debian (install.func) | Alpine (alpine-install.func) |
|---------|:---:|:---:|
| Package Manager | apt-get | apk |
| Init System | systemd | OpenRC |
| SSH Service | systemctl | rc-service |
| Config Files | /etc/systemd/ | /etc/init.d/ |
| Network Config | /etc/network/ or Netplan | /etc/network/interfaces |
| IPv6 Setup | netplan files | /etc/network/interfaces |
| Auto-Login | getty override | `/etc/inittab` or shell config |
| Size | ~200MB | ~100MB |
## Execution Flow for Alpine
```
Alpine Container Started
source $FUNCTIONS_FILE_PATH
setting_up_container() ← Alpine setup message
update_os() ← apk update
verb_ip6() ← IPv6 configuration (optional)
network_check() ← Verify connectivity
[Application-Specific Installation]
motd_ssh() ← Configure SSH/MOTD
customize() ← Apply customizations
cleanup_lxc() ← Final cleanup
Alpine Installation Complete
```
## Common Usage Patterns
### Basic Alpine Setup
```bash
#!/usr/bin/env bash
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
setting_up_container
update_os
# Install Alpine-specific packages
apk add --no-cache curl wget git
# ... application installation ...
motd_ssh
customize
cleanup_lxc
```
### With IPv6 Enabled
```bash
#!/usr/bin/env bash
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
setting_up_container
verb_ip6
update_os
network_check
# ... application installation ...
motd_ssh
customize
cleanup_lxc
```
### Installing Services
```bash
#!/usr/bin/env bash
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
setting_up_container
update_os
# Install via apk
apk add --no-cache nginx
# Enable and start service on Alpine
rc-update add nginx
rc-service nginx start
motd_ssh
customize
cleanup_lxc
```
## Best Practices
### ✅ DO
- Use `apk add --no-cache` to reduce image size
- Enable IPv6 if application needs it (`verb_ip6`)
- Use `rc-service` for service management on Alpine
- Check `/etc/network/interfaces` for IPv6 persistence
- Test network connectivity before critical operations
- Use `$STD` for output suppression in production
### ❌ DON'T
- Use `apt-get` commands (Alpine doesn't have apt)
- Use `systemctl` (Alpine uses OpenRC, not systemd)
- Use `service` command (it may not exist on Alpine)
- Assume systemd exists on Alpine
- Forget to add `--no-cache` flag to `apk add`
- Hardcode paths from Debian (different on Alpine)
## Alpine-Specific Considerations
### Package Names
Some packages have different names on Alpine:
```bash
# Debian → Alpine
# curl → curl (same)
# wget → wget (same)
# python3 → python3 (same)
# libpq5 → postgresql-client
# libmariadb3 → mariadb-client
```
### Service Management
```bash
# Debian (systemd) → Alpine (OpenRC)
systemctl start nginx → rc-service nginx start
systemctl enable nginx → rc-update add nginx
systemctl status nginx → rc-service nginx status
```
### Network Configuration
```bash
# Debian (Netplan) → Alpine (/etc/network/interfaces)
/etc/netplan/01-*.yaml → /etc/network/interfaces
netplan apply → Configure directly in interfaces
# Enable IPv6 persistently on Alpine:
# Add to /etc/network/interfaces:
# iface eth0 inet6 static
# address <IPv6_ADDRESS>
```
## Troubleshooting
### "apk command not found"
- This is Alpine Linux, not Debian
- Install packages with `apk add` instead of `apt-get install`
- Example: `apk add --no-cache curl wget`
### "IPv6 not persisting after reboot"
- IPv6 must be configured in `/etc/network/interfaces`
- The `verb_ip6()` function handles this automatically
- Verify: `cat /etc/network/interfaces`
### "Service won't start on Alpine"
- Alpine uses OpenRC, not systemd
- Use `rc-service nginx start` instead of `systemctl start nginx`
- Enable service: `rc-update add nginx`
- Check logs: `/var/log/` or `rc-service nginx status`
### "Container too large"
- Alpine should be much smaller than Debian
- Verify using `apk add --no-cache` (removes package cache)
- Example: `apk add --no-cache nginx` (not `apk add nginx`)
## Related Documentation
- **[alpine-tools.func/](../alpine-tools.func/)** - Alpine tool installation
- **[install.func/](../install.func/)** - Standard installation functions
- **[core.func/](../core.func/)** - Utility functions
- **[error_handler.func/](../error_handler.func/)** - Error handling
- **[UPDATED_APP-install.md](../../UPDATED_APP-install.md)** - Application script guide
## Recent Updates
### Version 2.0 (Dec 2025)
- ✅ Enhanced IPv6 persistence configuration
- ✅ Improved OpenRC service management
- ✅ Better apk error handling
- ✅ Added Alpine-specific best practices documentation
- ✅ Streamlined SSH setup for Alpine
---
**Last Updated**: December 2025
**Maintainers**: community-scripts team
**License**: MIT

View File

@@ -0,0 +1,25 @@
# alpine-tools.func Flowchart
Alpine tool installation and package management flow.
## Tool Installation on Alpine
```
apk_update()
add_community_repo() [optional]
apk_add PACKAGES
Tool Installation
rc-service start
rc-update add [enable at boot]
Complete ✓
```
---
**Last Updated**: December 2025

View File

@@ -0,0 +1,31 @@
# alpine-tools.func Functions Reference
Alpine-specific tool installation functions.
## Core Functions
### apk_update()
Update Alpine package lists.
### apk_add(PACKAGES)
Install Alpine packages.
### apk_del(PACKAGES)
Remove Alpine packages.
### add_community_repo()
Enable Alpine community repository.
### add_testing_repo()
Enable Alpine testing repository.
### Alpine Tool Functions
- `setup_nodejs()` - Alpine Node.js
- `setup_php()` - Alpine PHP
- `setup_mariadb()` - Alpine MariaDB
- `setup_postgresql()` - Alpine PostgreSQL
- (+ more Alpine-specific setups)
---
**Last Updated**: December 2025

View File

@@ -0,0 +1,7 @@
# alpine-tools.func Integration Guide
Alpine tool installation integration with container workflows.
---
**Last Updated**: December 2025

View File

@@ -0,0 +1,19 @@
# alpine-tools.func Usage Examples
Examples for Alpine tool installation.
### Example: Alpine Setup with Tools
```bash
#!/usr/bin/env bash
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
apk_update
setup_nodejs "20"
setup_php "8.3"
setup_mariadb "11"
```
---
**Last Updated**: December 2025

View File

@@ -0,0 +1,297 @@
# alpine-tools.func Documentation
## Overview
The `alpine-tools.func` file provides Alpine Linux-specific tool installation functions for package and service management within Alpine LXC containers. It complements `tools.func` with Alpine-specific implementations using the apk package manager.
## Purpose and Use Cases
- **Alpine Tool Installation**: Install services and tools using apk on Alpine
- **Package Management**: Safe apk operations with error handling
- **Service Setup**: Install and configure common services on Alpine
- **Dependency Management**: Handle Alpine-specific package dependencies
- **Repository Management**: Setup and manage Alpine package repositories
## Quick Reference
### Key Function Groups
- **Package Operations**: Alpine-specific apk commands with error handling
- **Service Installation**: Install databases, web servers, tools on Alpine
- **Repository Setup**: Configure Alpine community and testing repositories
- **Tool Setup**: Install development tools and utilities
### Dependencies
- **External**: `apk`, `curl`, `wget`
- **Internal**: Uses functions from `core.func`, `error_handler.func`
### Integration Points
- Used by: Alpine-based application install scripts
- Uses: Environment variables from build.func
- Provides: Alpine package and tool installation services
## Documentation Files
### 📊 [ALPINE_TOOLS_FUNC_FLOWCHART.md](./ALPINE_TOOLS_FUNC_FLOWCHART.md)
Visual execution flows for package operations and tool installation on Alpine.
### 📚 [ALPINE_TOOLS_FUNC_FUNCTIONS_REFERENCE.md](./ALPINE_TOOLS_FUNC_FUNCTIONS_REFERENCE.md)
Complete alphabetical reference of all Alpine tool functions.
### 💡 [ALPINE_TOOLS_FUNC_USAGE_EXAMPLES.md](./ALPINE_TOOLS_FUNC_USAGE_EXAMPLES.md)
Practical examples for common Alpine installation patterns.
### 🔗 [ALPINE_TOOLS_FUNC_INTEGRATION.md](./ALPINE_TOOLS_FUNC_INTEGRATION.md)
How alpine-tools.func integrates with Alpine installation workflows.
## Key Features
### Alpine Package Management
- **apk Add**: Safe package installation with error handling
- **apk Update**: Update package lists with retry logic
- **apk Del**: Remove packages and dependencies
- **Repository Configuration**: Add community and testing repos
### Alpine Tool Coverage
- **Web Servers**: nginx, lighttpd
- **Databases**: mariadb, postgresql, sqlite
- **Development**: gcc, make, git, node.js (via apk)
- **Services**: sshd, docker, podman
- **Utilities**: curl, wget, htop, vim
### Error Handling
- **Retry Logic**: Automatic recovery from transient failures
- **Dependency Resolution**: Handle missing dependencies
- **Lock Management**: Wait for apk locks to release
- **Error Reporting**: Clear error messages
## Function Categories
### 🔹 Package Management
- `apk_update()` - Update Alpine packages with retry
- `apk_add()` - Install packages safely
- `apk_del()` - Remove packages completely
### 🔹 Repository Functions
- `add_community_repo()` - Enable community repositories
- `add_testing_repo()` - Enable testing repositories
- `setup_apk_repo()` - Configure custom apk repositories
### 🔹 Service Installation Functions
- `setup_nginx()` - Install and configure nginx
- `setup_mariadb()` - Install MariaDB on Alpine
- `setup_postgresql()` - Install PostgreSQL
- `setup_docker()` - Install Docker on Alpine
- `setup_nodejs()` - Install Node.js from Alpine repos
### 🔹 Development Tools
- `setup_build_tools()` - Install gcc, make, build-essential
- `setup_git()` - Install git version control
- `setup_python()` - Install Python 3 and pip
## Alpine vs Debian Package Differences
| Package | Debian | Alpine |
|---------|:---:|:---:|
| nginx | `apt-get install nginx` | `apk add nginx` |
| mariadb | `apt-get install mariadb-server` | `apk add mariadb` |
| PostgreSQL | `apt-get install postgresql` | `apk add postgresql` |
| Node.js | `apt-get install nodejs npm` | `apk add nodejs npm` |
| Docker | Special setup | `apk add docker` |
| Python | `apt-get install python3 python3-pip` | `apk add python3 py3-pip` |
## Common Usage Patterns
### Basic Alpine Tool Installation
```bash
#!/usr/bin/env bash
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
# Update package lists
apk_update
# Install nginx
apk_add nginx
# Start service
rc-service nginx start
rc-update add nginx
```
### With Community Repository
```bash
#!/usr/bin/env bash
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
# Enable community repo for more packages
add_community_repo
# Update and install
apk_update
apk_add postgresql postgresql-client
# Start service
rc-service postgresql start
```
### Development Environment
```bash
#!/usr/bin/env bash
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
# Install build tools
setup_build_tools
setup_git
setup_nodejs "20"
# Install application
git clone https://example.com/app
cd app
npm install
```
## Best Practices
### ✅ DO
- Always use `apk add --no-cache` to keep images small
- Call `apk_update()` before installing packages
- Use community repository for more packages (`add_community_repo`)
- Handle apk locks gracefully with retry logic
- Use `$STD` variable for output control
- Check if tool already installed before reinstalling
### ❌ DON'T
- Use `apt-get` commands (Alpine doesn't have apt)
- Install packages without `--no-cache` flag
- Hardcode Alpine-specific paths
- Mix Alpine and Debian commands
- Forget to enable services with `rc-update`
- Use `systemctl` (Alpine has OpenRC, not systemd)
## Alpine Repository Configuration
### Default Repositories
Alpine comes with main repository enabled by default. Additional repos:
```bash
# Community repository (apk add php, go, rust, etc.)
add_community_repo
# Testing repository (bleeding edge packages)
add_testing_repo
```
### Repository Locations
```bash
/etc/apk/repositories # Main repo list
/etc/apk/keys/ # GPG keys for repos
/var/cache/apk/ # Package cache
```
## Package Size Optimization
Alpine is designed for small container images:
```bash
# DON'T: Leaves package cache (increases image size)
apk add nginx
# DO: Remove cache to reduce size
apk add --no-cache nginx
# Expected sizes:
# Alpine base: ~5MB
# Alpine + nginx: ~10-15MB
# Debian base: ~75MB
# Debian + nginx: ~90-95MB
```
## Service Management on Alpine
### Using OpenRC
```bash
# Start service immediately
rc-service nginx start
# Stop service
rc-service nginx stop
# Restart service
rc-service nginx restart
# Enable at boot
rc-update add nginx
# Disable at boot
rc-update del nginx
# List enabled services
rc-update show
```
## Troubleshooting
### "apk: lock is held by PID"
```bash
# Alpine apk database is locked (another process using apk)
# Wait a moment
sleep 5
apk_update
# Or manually:
rm /var/lib/apk/lock 2>/dev/null || true
apk update
```
### "Package not found"
```bash
# May be in community or testing repository
add_community_repo
apk_update
apk_add package-name
```
### "Repository not responding"
```bash
# Alpine repo may be slow or unreachable
# Try updating again with retry logic
apk_update # Built-in retry logic
# Or manually retry
sleep 10
apk update
```
### "Service fails to start"
```bash
# Check service status on Alpine
rc-service nginx status
# View logs
tail /var/log/nginx/error.log
# Verify configuration
nginx -t
```
## Related Documentation
- **[alpine-install.func/](../alpine-install.func/)** - Alpine installation functions
- **[tools.func/](../tools.func/)** - Debian/standard tool installation
- **[core.func/](../core.func/)** - Utility functions
- **[error_handler.func/](../error_handler.func/)** - Error handling
- **[UPDATED_APP-install.md](../../UPDATED_APP-install.md)** - Application script guide
## Recent Updates
### Version 2.0 (Dec 2025)
- ✅ Enhanced apk error handling and retry logic
- ✅ Improved repository management
- ✅ Better service management with OpenRC
- ✅ Added Alpine-specific optimization guidance
- ✅ Enhanced package cache management
---
**Last Updated**: December 2025
**Maintainers**: community-scripts team
**License**: MIT

View File

@@ -0,0 +1,342 @@
# api.func Execution Flowchart
## Main API Communication Flow
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ API Communication Initialization │
│ Entry point when api.func functions are called by installation scripts │
└─────────────────────┬───────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Prerequisites Check │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ Prerequisites Validation │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Check curl │ │ Check │ │ Check │ │ │
│ │ │ Availability │ │ Diagnostics │ │ Random UUID │ │ │
│ │ │ │ │ Setting │ │ │ │
│ │ │ • command -v │ │ • DIAGNOSTICS │ │ • RANDOM_UUID │ │
│ │ │ curl │ │ = "yes" │ │ not empty │ │
│ │ │ • Return if │ │ • Return if │ │ • Return if │ │
│ │ │ not found │ │ disabled │ │ not set │ │
│ │ │ │ │ │ │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Data Collection │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ System Information Gathering │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Get PVE │ │ Collect │ │ Prepare JSON │ │ │
│ │ │ Version │ │ Environment │ │ Payload │ │
│ │ │ │ │ Variables │ │ │ │
│ │ │ • pveversion │ │ • CT_TYPE │ │ • Create JSON │ │
│ │ │ command │ │ • DISK_SIZE │ │ structure │ │
│ │ │ • Parse version │ │ • CORE_COUNT │ │ • Include all │ │
│ │ │ • Extract │ │ • RAM_SIZE │ │ variables │ │
│ │ │ major.minor │ │ • var_os │ │ • Format for API │ │
│ │ │ │ │ • var_version │ │ │ │
│ │ │ │ │ • NSAPP │ │ │ │
│ │ │ │ │ • METHOD │ │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ API Request Execution │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ HTTP Request Processing │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Prepare │ │ Execute │ │ Handle │ │ │
│ │ │ Request │ │ HTTP Request │ │ Response │ │
│ │ │ │ │ │ │ │ │
│ │ │ • Set API URL │ │ • curl -s -w │ │ • Capture HTTP │ │
│ │ │ • Set headers │ │ "%{http_code}" │ │ status code │ │
│ │ │ • Set payload │ │ • POST request │ │ • Store response │ │
│ │ │ • Content-Type │ │ • JSON data │ │ • Handle errors │ │
│ │ │ application/ │ │ • Follow │ │ gracefully │ │
│ │ │ json │ │ redirects │ │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
```
## LXC API Reporting Flow
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ POST_TO_API() Flow │
│ Send LXC container installation data to API │
└─────────────────────┬───────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ LXC Data Preparation │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ LXC-Specific Data Collection │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Set LXC │ │ Include LXC │ │ Set Status │ │ │
│ │ │ Type │ │ Variables │ │ Information │ │
│ │ │ │ │ │ │ │ │
│ │ │ • ct_type: 1 │ │ • DISK_SIZE │ │ • status: │ │
│ │ │ • type: "lxc" │ │ • CORE_COUNT │ │ "installing" │ │
│ │ │ • Include all │ │ • RAM_SIZE │ │ • Include all │ │
│ │ │ LXC data │ │ • var_os │ │ tracking data │ │
│ │ │ │ │ • var_version │ │ │ │
│ │ │ │ │ • DISABLEIP6 │ │ │ │
│ │ │ │ │ • NSAPP │ │ │ │
│ │ │ │ │ • METHOD │ │ │ │
│ │ │ │ │ • pve_version │ │ │ │
│ │ │ │ │ • random_id │ │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ JSON Payload Creation │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ JSON Structure Generation │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Create JSON │ │ Validate │ │ Format for │ │ │
│ │ │ Structure │ │ Data │ │ API Request │ │
│ │ │ │ │ │ │ │ │
│ │ │ • Use heredoc │ │ • Check all │ │ • Ensure proper │ │
│ │ │ syntax │ │ variables │ │ JSON format │ │
│ │ │ • Include all │ │ are set │ │ • Escape special │ │
│ │ │ required │ │ • Validate │ │ characters │ │
│ │ │ fields │ │ data types │ │ • Set content │ │
│ │ │ • Format │ │ • Handle │ │ type │ │
│ │ │ properly │ │ missing │ │ │ │
│ │ │ │ │ values │ │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
```
## VM API Reporting Flow
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ POST_TO_API_VM() Flow │
│ Send VM installation data to API │
└─────────────────────┬───────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ VM Data Preparation │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ VM-Specific Data Collection │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Check │ │ Set VM │ │ Process Disk │ │ │
│ │ │ Diagnostics │ │ Type │ │ Size │ │
│ │ │ File │ │ │ │ │ │
│ │ │ │ │ • ct_type: 2 │ │ • Remove 'G' │ │
│ │ │ • Check file │ │ • type: "vm" │ │ suffix │ │
│ │ │ existence │ │ • Include all │ │ • Convert to │ │
│ │ │ • Read │ │ VM data │ │ numeric value │ │
│ │ │ DIAGNOSTICS │ │ │ │ • Store in │ │
│ │ │ setting │ │ │ │ DISK_SIZE_API │ │
│ │ │ • Parse value │ │ │ │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ VM JSON Payload Creation │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ VM-Specific JSON Structure │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Include VM │ │ Set VM │ │ Format VM │ │ │
│ │ │ Variables │ │ Status │ │ Data for API │ │
│ │ │ │ │ │ │ │ │
│ │ │ • DISK_SIZE_API │ │ • status: │ │ • Ensure proper │ │
│ │ │ • CORE_COUNT │ │ "installing" │ │ JSON format │ │
│ │ │ • RAM_SIZE │ │ • Include all │ │ • Handle VM- │ │
│ │ │ • var_os │ │ tracking │ │ specific data │ │
│ │ │ • var_version │ │ information │ │ • Set appropriate │ │
│ │ │ • NSAPP │ │ │ │ content type │ │
│ │ │ • METHOD │ │ │ │ │ │
│ │ │ • pve_version │ │ │ │ │ │
│ │ │ • random_id │ │ │ │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
```
## Status Update Flow
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ POST_UPDATE_TO_API() Flow │
│ Send installation completion status to API │
└─────────────────────┬───────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Update Prevention Check │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ Duplicate Update Prevention │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Check │ │ Set Flag │ │ Return Early │ │ │
│ │ │ POST_UPDATE_ │ │ if First │ │ if Already │ │
│ │ │ DONE │ │ Update │ │ Updated │ │
│ │ │ │ │ │ │ │ │
│ │ │ • Check if │ │ • Set │ │ • Return 0 │ │
│ │ │ already │ │ POST_UPDATE_ │ │ • Skip API call │ │
│ │ │ updated │ │ DONE=true │ │ • Prevent │ │
│ │ │ • Prevent │ │ • Continue │ │ duplicate │ │
│ │ │ duplicate │ │ with update │ │ requests │ │
│ │ │ requests │ │ │ │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Status and Error Processing │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ Status Determination │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Determine │ │ Get Error │ │ Prepare Status │ │ │
│ │ │ Status │ │ Description │ │ Data │ │
│ │ │ │ │ │ │ │ │
│ │ │ • status: │ │ • Call │ │ • Include status │ │
│ │ │ "success" or │ │ get_error_ │ │ • Include error │ │
│ │ │ "failed" │ │ description() │ │ description │ │
│ │ │ • Set exit │ │ • Get human- │ │ • Include random │ │
│ │ │ code based │ │ readable │ │ ID for tracking │ │
│ │ │ on status │ │ error message │ │ │ │
│ │ │ • Default to │ │ • Handle │ │ │ │
│ │ │ error if │ │ unknown │ │ │ │
│ │ │ not set │ │ errors │ │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Status Update API Request │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ Status Update Payload Creation │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Create │ │ Send Status │ │ Mark Update │ │ │
│ │ │ Status JSON │ │ Update │ │ Complete │ │
│ │ │ │ │ │ │ │ │
│ │ │ • Include │ │ • POST to │ │ • Set │ │
│ │ │ status │ │ updatestatus │ │ POST_UPDATE_ │ │
│ │ │ • Include │ │ endpoint │ │ DONE=true │ │
│ │ │ error │ │ • Include JSON │ │ • Prevent further │ │
│ │ │ description │ │ payload │ │ updates │ │
│ │ │ • Include │ │ • Handle │ │ • Complete │ │
│ │ │ random_id │ │ response │ │ process │ │
│ │ │ │ │ gracefully │ │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
```
## Error Description Flow
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ GET_ERROR_DESCRIPTION() Flow │
│ Convert numeric exit codes to human-readable explanations │
└─────────────────────┬───────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Error Code Classification │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ Error Code Categories │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │
│ │ │ General │ │ Network │ │ LXC-Specific │ │ │
│ │ │ System │ │ Errors │ │ Errors │ │
│ │ │ Errors │ │ │ │ │ │
│ │ │ │ │ • 18: Connection│ │ • 100-101: LXC │ │
│ │ │ • 0-9: Basic │ │ failed │ │ install errors │ │
│ │ │ errors │ │ • 22: Invalid │ │ • 200-209: LXC │ │
│ │ │ • 126-128: │ │ argument │ │ creation errors │ │
│ │ │ Command │ │ • 28: No space │ │ │ │
│ │ │ errors │ │ • 35: Timeout │ │ │ │
│ │ │ • 129-143: │ │ • 56: TLS error │ │ │ │
│ │ │ Signal │ │ • 60: SSL cert │ │ │ │
│ │ │ errors │ │ error │ │ │ │
│ │ │ • 152: Resource │ │ │ │ │ │
│ │ │ limit │ │ │ │ │ │
│ │ │ • 255: Unknown │ │ │ │ │ │
│ │ │ critical │ │ │ │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Error Message Return │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ Error Message Formatting │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Match Error │ │ Return │ │ Default Case │ │ │
│ │ │ Code │ │ Description │ │ │ │
│ │ │ │ │ │ │ │ │
│ │ │ • Use case │ │ • Return │ │ • Return "Unknown │ │
│ │ │ statement │ │ human- │ │ error code │ │
│ │ │ • Match │ │ readable │ │ (exit_code)" │ │
│ │ │ specific │ │ message │ │ • Handle │ │
│ │ │ codes │ │ • Include │ │ unrecognized │ │
│ │ │ • Handle │ │ context │ │ codes │ │
│ │ │ ranges │ │ information │ │ • Provide fallback │ │
│ │ │ │ │ │ │ message │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
```
## Integration Points
### With Installation Scripts
- **build.func**: Sends LXC installation data
- **vm-core.func**: Sends VM installation data
- **install.func**: Reports installation status
- **alpine-install.func**: Reports Alpine installation data
### With Error Handling
- **error_handler.func**: Provides error explanations
- **core.func**: Uses error descriptions in silent execution
- **Diagnostic reporting**: Tracks error patterns
### External Dependencies
- **curl**: HTTP client for API communication
- **Community Scripts API**: External API endpoint
- **Network connectivity**: Required for API communication

View File

@@ -0,0 +1,433 @@
# api.func Functions Reference
## Overview
This document provides a comprehensive alphabetical reference of all functions in `api.func`, including parameters, dependencies, usage examples, and error handling.
## Function Categories
### Error Description Functions
#### `get_error_description()`
**Purpose**: Convert numeric exit codes to human-readable explanations
**Parameters**:
- `$1` - Exit code to explain
**Returns**: Human-readable error explanation string
**Side Effects**: None
**Dependencies**: None
**Environment Variables Used**: None
**Supported Exit Codes**:
- **General System**: 0-9, 18, 22, 28, 35, 56, 60, 125-128, 129-143, 152, 255
- **LXC-Specific**: 100-101, 200-209
- **Docker**: 125
**Usage Example**:
```bash
error_msg=$(get_error_description 127)
echo "Error 127: $error_msg"
# Output: Error 127: Command not found: Incorrect path or missing dependency.
```
**Error Code Examples**:
```bash
get_error_description 0 # " " (space)
get_error_description 1 # "General error: An unspecified error occurred."
get_error_description 127 # "Command not found: Incorrect path or missing dependency."
get_error_description 200 # "LXC creation failed."
get_error_description 255 # "Unknown critical error, often due to missing permissions or broken scripts."
```
### API Communication Functions
#### `post_to_api()`
**Purpose**: Send LXC container installation data to community-scripts.org API
**Parameters**: None (uses environment variables)
**Returns**: None
**Side Effects**:
- Sends HTTP POST request to API
- Stores response in RESPONSE variable
- Requires curl command and network connectivity
**Dependencies**: `curl` command
**Environment Variables Used**: `DIAGNOSTICS`, `RANDOM_UUID`, `CT_TYPE`, `DISK_SIZE`, `CORE_COUNT`, `RAM_SIZE`, `var_os`, `var_version`, `DISABLEIP6`, `NSAPP`, `METHOD`
**Prerequisites**:
- `curl` command must be available
- `DIAGNOSTICS` must be set to "yes"
- `RANDOM_UUID` must be set and not empty
**API Endpoint**: `https://api.community-scripts.org/dev/upload`
**JSON Payload Structure**:
```json
{
"ct_type": 1,
"type": "lxc",
"disk_size": 8,
"core_count": 2,
"ram_size": 2048,
"os_type": "debian",
"os_version": "12",
"disableip6": "true",
"nsapp": "plex",
"method": "install",
"pve_version": "8.0",
"status": "installing",
"random_id": "uuid-string"
}
```
**Usage Example**:
```bash
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
export CT_TYPE=1
export DISK_SIZE=8
export CORE_COUNT=2
export RAM_SIZE=2048
export var_os="debian"
export var_version="12"
export NSAPP="plex"
export METHOD="install"
post_to_api
```
#### `post_to_api_vm()`
**Purpose**: Send VM installation data to community-scripts.org API
**Parameters**: None (uses environment variables)
**Returns**: None
**Side Effects**:
- Sends HTTP POST request to API
- Stores response in RESPONSE variable
- Requires curl command and network connectivity
**Dependencies**: `curl` command, diagnostics file
**Environment Variables Used**: `DIAGNOSTICS`, `RANDOM_UUID`, `DISK_SIZE`, `CORE_COUNT`, `RAM_SIZE`, `var_os`, `var_version`, `NSAPP`, `METHOD`
**Prerequisites**:
- `/usr/local/community-scripts/diagnostics` file must exist
- `DIAGNOSTICS` must be set to "yes" in diagnostics file
- `curl` command must be available
- `RANDOM_UUID` must be set and not empty
**API Endpoint**: `https://api.community-scripts.org/dev/upload`
**JSON Payload Structure**:
```json
{
"ct_type": 2,
"type": "vm",
"disk_size": 8,
"core_count": 2,
"ram_size": 2048,
"os_type": "debian",
"os_version": "12",
"disableip6": "",
"nsapp": "plex",
"method": "install",
"pve_version": "8.0",
"status": "installing",
"random_id": "uuid-string"
}
```
**Usage Example**:
```bash
# Create diagnostics file
echo "DIAGNOSTICS=yes" > /usr/local/community-scripts/diagnostics
export RANDOM_UUID="$(uuidgen)"
export DISK_SIZE="8G"
export CORE_COUNT=2
export RAM_SIZE=2048
export var_os="debian"
export var_version="12"
export NSAPP="plex"
export METHOD="install"
post_to_api_vm
```
#### `post_update_to_api()`
**Purpose**: Send installation completion status to community-scripts.org API
**Parameters**:
- `$1` - Status ("success" or "failed", default: "failed")
- `$2` - Exit code (default: 1)
**Returns**: None
**Side Effects**:
- Sends HTTP POST request to API
- Sets POST_UPDATE_DONE=true to prevent duplicates
- Stores response in RESPONSE variable
**Dependencies**: `curl` command, `get_error_description()`
**Environment Variables Used**: `DIAGNOSTICS`, `RANDOM_UUID`
**Prerequisites**:
- `curl` command must be available
- `DIAGNOSTICS` must be set to "yes"
- `RANDOM_UUID` must be set and not empty
- POST_UPDATE_DONE must be false (prevents duplicates)
**API Endpoint**: `https://api.community-scripts.org/dev/upload/updatestatus`
**JSON Payload Structure**:
```json
{
"status": "success",
"error": "Error description from get_error_description()",
"random_id": "uuid-string"
}
```
**Usage Example**:
```bash
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
# Report successful installation
post_update_to_api "success" 0
# Report failed installation
post_update_to_api "failed" 127
```
## Function Call Hierarchy
### API Communication Flow
```
post_to_api()
├── Check curl availability
├── Check DIAGNOSTICS setting
├── Check RANDOM_UUID
├── Get PVE version
├── Create JSON payload
└── Send HTTP POST request
post_to_api_vm()
├── Check diagnostics file
├── Check curl availability
├── Check DIAGNOSTICS setting
├── Check RANDOM_UUID
├── Process disk size
├── Get PVE version
├── Create JSON payload
└── Send HTTP POST request
post_update_to_api()
├── Check POST_UPDATE_DONE flag
├── Check curl availability
├── Check DIAGNOSTICS setting
├── Check RANDOM_UUID
├── Determine status and exit code
├── Get error description
├── Create JSON payload
├── Send HTTP POST request
└── Set POST_UPDATE_DONE=true
```
### Error Description Flow
```
get_error_description()
├── Match exit code
├── Return appropriate description
└── Handle unknown codes
```
## Error Code Reference
### General System Errors
| Code | Description |
|------|-------------|
| 0 | (space) |
| 1 | General error: An unspecified error occurred. |
| 2 | Incorrect shell usage or invalid command arguments. |
| 3 | Unexecuted function or invalid shell condition. |
| 4 | Error opening a file or invalid path. |
| 5 | I/O error: An input/output failure occurred. |
| 6 | No such device or address. |
| 7 | Insufficient memory or resource exhaustion. |
| 8 | Non-executable file or invalid file format. |
| 9 | Failed child process execution. |
| 18 | Connection to a remote server failed. |
| 22 | Invalid argument or faulty network connection. |
| 28 | No space left on device. |
| 35 | Timeout while establishing a connection. |
| 56 | Faulty TLS connection. |
| 60 | SSL certificate error. |
### Command Execution Errors
| Code | Description |
|------|-------------|
| 125 | Docker error: Container could not start. |
| 126 | Command not executable: Incorrect permissions or missing dependencies. |
| 127 | Command not found: Incorrect path or missing dependency. |
| 128 | Invalid exit signal, e.g., incorrect Git command. |
### Signal Errors
| Code | Description |
|------|-------------|
| 129 | Signal 1 (SIGHUP): Process terminated due to hangup. |
| 130 | Signal 2 (SIGINT): Manual termination via Ctrl+C. |
| 132 | Signal 4 (SIGILL): Illegal machine instruction. |
| 133 | Signal 5 (SIGTRAP): Debugging error or invalid breakpoint signal. |
| 134 | Signal 6 (SIGABRT): Program aborted itself. |
| 135 | Signal 7 (SIGBUS): Memory error, invalid memory address. |
| 137 | Signal 9 (SIGKILL): Process forcibly terminated (OOM-killer or 'kill -9'). |
| 139 | Signal 11 (SIGSEGV): Segmentation fault, possibly due to invalid pointer access. |
| 141 | Signal 13 (SIGPIPE): Pipe closed unexpectedly. |
| 143 | Signal 15 (SIGTERM): Process terminated normally. |
| 152 | Signal 24 (SIGXCPU): CPU time limit exceeded. |
### LXC-Specific Errors
| Code | Description |
|------|-------------|
| 100 | LXC install error: Unexpected error in create_lxc.sh. |
| 101 | LXC install error: No network connection detected. |
| 200 | LXC creation failed. |
| 201 | LXC error: Invalid Storage class. |
| 202 | User aborted menu in create_lxc.sh. |
| 203 | CTID not set in create_lxc.sh. |
| 204 | PCT_OSTYPE not set in create_lxc.sh. |
| 205 | CTID cannot be less than 100 in create_lxc.sh. |
| 206 | CTID already in use in create_lxc.sh. |
| 207 | Template not found in create_lxc.sh. |
| 208 | Error downloading template in create_lxc.sh. |
| 209 | Container creation failed, but template is intact in create_lxc.sh. |
### Other Errors
| Code | Description |
|------|-------------|
| 255 | Unknown critical error, often due to missing permissions or broken scripts. |
| * | Unknown error code (exit_code). |
## Environment Variable Dependencies
### Required Variables
- **`DIAGNOSTICS`**: Enable/disable diagnostic reporting ("yes"/"no")
- **`RANDOM_UUID`**: Unique identifier for tracking
### Optional Variables
- **`CT_TYPE`**: Container type (1 for LXC, 2 for VM)
- **`DISK_SIZE`**: Disk size in GB (or GB with 'G' suffix for VM)
- **`CORE_COUNT`**: Number of CPU cores
- **`RAM_SIZE`**: RAM size in MB
- **`var_os`**: Operating system type
- **`var_version`**: OS version
- **`DISABLEIP6`**: IPv6 disable setting
- **`NSAPP`**: Namespace application name
- **`METHOD`**: Installation method
### Internal Variables
- **`POST_UPDATE_DONE`**: Prevents duplicate status updates
- **`API_URL`**: Community scripts API endpoint
- **`JSON_PAYLOAD`**: API request payload
- **`RESPONSE`**: API response
- **`DISK_SIZE_API`**: Processed disk size for VM API
## Error Handling Patterns
### API Communication Errors
- All API functions handle curl failures gracefully
- Network errors don't block installation process
- Missing prerequisites cause early return
- Duplicate updates are prevented
### Error Description Errors
- Unknown error codes return generic message
- All error codes are handled with case statement
- Fallback message includes the actual error code
### Prerequisites Validation
- Check curl availability before API calls
- Validate DIAGNOSTICS setting
- Ensure RANDOM_UUID is set
- Check for duplicate updates
## Integration Examples
### With build.func
```bash
#!/usr/bin/env bash
source core.func
source api.func
source build.func
# Set up API reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
# Report installation start
post_to_api
# Container creation...
# ... build.func code ...
# Report completion
if [[ $? -eq 0 ]]; then
post_update_to_api "success" 0
else
post_update_to_api "failed" $?
fi
```
### With vm-core.func
```bash
#!/usr/bin/env bash
source core.func
source api.func
source vm-core.func
# Set up API reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
# Report VM installation start
post_to_api_vm
# VM creation...
# ... vm-core.func code ...
# Report completion
post_update_to_api "success" 0
```
### With error_handler.func
```bash
#!/usr/bin/env bash
source core.func
source error_handler.func
source api.func
# Use error descriptions
error_code=127
error_msg=$(get_error_description $error_code)
echo "Error $error_code: $error_msg"
# Report error to API
post_update_to_api "failed" $error_code
```
## Best Practices
### API Usage
1. Always check prerequisites before API calls
2. Use unique identifiers for tracking
3. Handle API failures gracefully
4. Don't block installation on API failures
### Error Reporting
1. Use appropriate error codes
2. Provide meaningful error descriptions
3. Report both success and failure cases
4. Prevent duplicate status updates
### Diagnostic Reporting
1. Respect user privacy settings
2. Only send data when diagnostics enabled
3. Use anonymous tracking identifiers
4. Include relevant system information
### Error Handling
1. Handle unknown error codes gracefully
2. Provide fallback error messages
3. Include error code in unknown error messages
4. Use consistent error message format

View File

@@ -0,0 +1,643 @@
# api.func Integration Guide
## Overview
This document describes how `api.func` integrates with other components in the Proxmox Community Scripts project, including dependencies, data flow, and API surface.
## Dependencies
### External Dependencies
#### Required Commands
- **`curl`**: HTTP client for API communication
- **`uuidgen`**: Generate unique identifiers (optional, can use other methods)
#### Optional Commands
- **None**: No other external command dependencies
### Internal Dependencies
#### Environment Variables from Other Scripts
- **build.func**: Provides container creation variables
- **vm-core.func**: Provides VM creation variables
- **core.func**: Provides system information variables
- **Installation scripts**: Provide application-specific variables
## Integration Points
### With build.func
#### LXC Container Reporting
```bash
# build.func uses api.func for container reporting
source core.func
source api.func
source build.func
# Set up API reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
# Container creation with API reporting
create_container() {
# Set container parameters
export CT_TYPE=1
export DISK_SIZE="$var_disk"
export CORE_COUNT="$var_cpu"
export RAM_SIZE="$var_ram"
export var_os="$var_os"
export var_version="$var_version"
export NSAPP="$APP"
export METHOD="install"
# Report installation start
post_to_api
# Container creation using build.func
# ... build.func container creation logic ...
# Report completion
if [[ $? -eq 0 ]]; then
post_update_to_api "success" 0
else
post_update_to_api "failed" $?
fi
}
```
#### Error Reporting Integration
```bash
# build.func uses api.func for error reporting
handle_container_error() {
local exit_code=$1
local error_msg=$(get_error_description $exit_code)
echo "Container creation failed: $error_msg"
post_update_to_api "failed" $exit_code
}
```
### With vm-core.func
#### VM Installation Reporting
```bash
# vm-core.func uses api.func for VM reporting
source core.func
source api.func
source vm-core.func
# Set up VM API reporting
mkdir -p /usr/local/community-scripts
echo "DIAGNOSTICS=yes" > /usr/local/community-scripts/diagnostics
export RANDOM_UUID="$(uuidgen)"
# VM creation with API reporting
create_vm() {
# Set VM parameters
export DISK_SIZE="${var_disk}G"
export CORE_COUNT="$var_cpu"
export RAM_SIZE="$var_ram"
export var_os="$var_os"
export var_version="$var_version"
export NSAPP="$APP"
export METHOD="install"
# Report VM installation start
post_to_api_vm
# VM creation using vm-core.func
# ... vm-core.func VM creation logic ...
# Report completion
post_update_to_api "success" 0
}
```
### With core.func
#### System Information Integration
```bash
# core.func provides system information for api.func
source core.func
source api.func
# Get system information for API reporting
get_system_info_for_api() {
# Get PVE version using core.func utilities
local pve_version=$(pveversion | awk -F'[/ ]' '{print $2}')
# Set API parameters
export var_os="$var_os"
export var_version="$var_version"
# Use core.func error handling with api.func reporting
if silent apt-get update; then
post_update_to_api "success" 0
else
post_update_to_api "failed" $?
fi
}
```
### With error_handler.func
#### Error Description Integration
```bash
# error_handler.func uses api.func for error descriptions
source core.func
source error_handler.func
source api.func
# Enhanced error handler with API reporting
enhanced_error_handler() {
local exit_code=${1:-$?}
local command=${2:-${BASH_COMMAND:-unknown}}
# Get error description from api.func
local error_msg=$(get_error_description $exit_code)
# Display error information
echo "Error $exit_code: $error_msg"
echo "Command: $command"
# Report error to API
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
post_update_to_api "failed" $exit_code
# Use standard error handler
error_handler $exit_code $command
}
```
### With install.func
#### Installation Process Reporting
```bash
# install.func uses api.func for installation reporting
source core.func
source api.func
source install.func
# Installation with API reporting
install_package_with_reporting() {
local package="$1"
# Set up API reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
export NSAPP="$package"
export METHOD="install"
# Report installation start
post_to_api
# Package installation using install.func
if install_package "$package"; then
echo "$package installed successfully"
post_update_to_api "success" 0
return 0
else
local exit_code=$?
local error_msg=$(get_error_description $exit_code)
echo "$package installation failed: $error_msg"
post_update_to_api "failed" $exit_code
return $exit_code
fi
}
```
### With alpine-install.func
#### Alpine Installation Reporting
```bash
# alpine-install.func uses api.func for Alpine reporting
source core.func
source api.func
source alpine-install.func
# Alpine installation with API reporting
install_alpine_with_reporting() {
local app="$1"
# Set up API reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
export NSAPP="$app"
export METHOD="install"
export var_os="alpine"
# Report Alpine installation start
post_to_api
# Alpine installation using alpine-install.func
if install_alpine_app "$app"; then
echo "Alpine $app installed successfully"
post_update_to_api "success" 0
return 0
else
local exit_code=$?
local error_msg=$(get_error_description $exit_code)
echo "Alpine $app installation failed: $error_msg"
post_update_to_api "failed" $exit_code
return $exit_code
fi
}
```
### With alpine-tools.func
#### Alpine Tools Reporting
```bash
# alpine-tools.func uses api.func for Alpine tools reporting
source core.func
source api.func
source alpine-tools.func
# Alpine tools with API reporting
run_alpine_tool_with_reporting() {
local tool="$1"
# Set up API reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
export NSAPP="alpine-tools"
export METHOD="tool"
# Report tool execution start
post_to_api
# Run Alpine tool using alpine-tools.func
if run_alpine_tool "$tool"; then
echo "Alpine tool $tool executed successfully"
post_update_to_api "success" 0
return 0
else
local exit_code=$?
local error_msg=$(get_error_description $exit_code)
echo "Alpine tool $tool failed: $error_msg"
post_update_to_api "failed" $exit_code
return $exit_code
fi
}
```
### With passthrough.func
#### Hardware Passthrough Reporting
```bash
# passthrough.func uses api.func for hardware reporting
source core.func
source api.func
source passthrough.func
# Hardware passthrough with API reporting
configure_passthrough_with_reporting() {
local hardware_type="$1"
# Set up API reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
export NSAPP="passthrough"
export METHOD="hardware"
# Report passthrough configuration start
post_to_api
# Configure passthrough using passthrough.func
if configure_passthrough "$hardware_type"; then
echo "Hardware passthrough configured successfully"
post_update_to_api "success" 0
return 0
else
local exit_code=$?
local error_msg=$(get_error_description $exit_code)
echo "Hardware passthrough failed: $error_msg"
post_update_to_api "failed" $exit_code
return $exit_code
fi
}
```
### With tools.func
#### Maintenance Operations Reporting
```bash
# tools.func uses api.func for maintenance reporting
source core.func
source api.func
source tools.func
# Maintenance operations with API reporting
run_maintenance_with_reporting() {
local operation="$1"
# Set up API reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
export NSAPP="maintenance"
export METHOD="tool"
# Report maintenance start
post_to_api
# Run maintenance using tools.func
if run_maintenance_operation "$operation"; then
echo "Maintenance operation $operation completed successfully"
post_update_to_api "success" 0
return 0
else
local exit_code=$?
local error_msg=$(get_error_description $exit_code)
echo "Maintenance operation $operation failed: $error_msg"
post_update_to_api "failed" $exit_code
return $exit_code
fi
}
```
## Data Flow
### Input Data
#### Environment Variables from Other Scripts
- **`CT_TYPE`**: Container type (1 for LXC, 2 for VM)
- **`DISK_SIZE`**: Disk size in GB
- **`CORE_COUNT`**: Number of CPU cores
- **`RAM_SIZE`**: RAM size in MB
- **`var_os`**: Operating system type
- **`var_version`**: OS version
- **`DISABLEIP6`**: IPv6 disable setting
- **`NSAPP`**: Namespace application name
- **`METHOD`**: Installation method
- **`DIAGNOSTICS`**: Enable/disable diagnostic reporting
- **`RANDOM_UUID`**: Unique identifier for tracking
#### Function Parameters
- **Exit codes**: Passed to `get_error_description()` and `post_update_to_api()`
- **Status information**: Passed to `post_update_to_api()`
- **API endpoints**: Hardcoded in functions
#### System Information
- **PVE version**: Retrieved from `pveversion` command
- **Disk size processing**: Processed for VM API (removes 'G' suffix)
- **Error codes**: Retrieved from command exit codes
### Processing Data
#### API Request Preparation
- **JSON payload creation**: Format data for API consumption
- **Data validation**: Ensure required fields are present
- **Error handling**: Handle missing or invalid data
- **Content type setting**: Set appropriate HTTP headers
#### Error Processing
- **Error code mapping**: Map numeric codes to descriptions
- **Error message formatting**: Format error descriptions
- **Unknown error handling**: Handle unrecognized error codes
- **Fallback messages**: Provide default error messages
#### API Communication
- **HTTP request preparation**: Prepare curl commands
- **Response handling**: Capture HTTP response codes
- **Error handling**: Handle network and API errors
- **Duplicate prevention**: Prevent duplicate status updates
### Output Data
#### API Communication
- **HTTP requests**: Sent to community-scripts.org API
- **Response codes**: Captured from API responses
- **Error information**: Reported to API
- **Status updates**: Sent to API
#### Error Information
- **Error descriptions**: Human-readable error messages
- **Error codes**: Mapped to descriptions
- **Context information**: Error context and details
- **Fallback messages**: Default error messages
#### System State
- **POST_UPDATE_DONE**: Prevents duplicate updates
- **RESPONSE**: Stores API response
- **JSON_PAYLOAD**: Stores formatted API data
- **API_URL**: Stores API endpoint
## API Surface
### Public Functions
#### Error Description
- **`get_error_description()`**: Convert exit codes to explanations
- **Parameters**: Exit code to explain
- **Returns**: Human-readable explanation string
- **Usage**: Called by other functions and scripts
#### API Communication
- **`post_to_api()`**: Send LXC installation data
- **`post_to_api_vm()`**: Send VM installation data
- **`post_update_to_api()`**: Send status updates
- **Parameters**: Status and exit code (for updates)
- **Returns**: None
- **Usage**: Called by installation scripts
### Internal Functions
#### None
- All functions in api.func are public
- No internal helper functions
- Direct implementation of all functionality
### Global Variables
#### Configuration Variables
- **`DIAGNOSTICS`**: Diagnostic reporting setting
- **`RANDOM_UUID`**: Unique tracking identifier
- **`POST_UPDATE_DONE`**: Duplicate update prevention
#### Data Variables
- **`CT_TYPE`**: Container type
- **`DISK_SIZE`**: Disk size
- **`CORE_COUNT`**: CPU core count
- **`RAM_SIZE`**: RAM size
- **`var_os`**: Operating system
- **`var_version`**: OS version
- **`DISABLEIP6`**: IPv6 setting
- **`NSAPP`**: Application namespace
- **`METHOD`**: Installation method
#### Internal Variables
- **`API_URL`**: API endpoint URL
- **`JSON_PAYLOAD`**: API request payload
- **`RESPONSE`**: API response
- **`DISK_SIZE_API`**: Processed disk size for VM API
## Integration Patterns
### Standard Integration Pattern
```bash
#!/usr/bin/env bash
# Standard integration pattern
# 1. Source core.func first
source core.func
# 2. Source api.func
source api.func
# 3. Set up API reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
# 4. Set application parameters
export NSAPP="$APP"
export METHOD="install"
# 5. Report installation start
post_to_api
# 6. Perform installation
# ... installation logic ...
# 7. Report completion
post_update_to_api "success" 0
```
### Minimal Integration Pattern
```bash
#!/usr/bin/env bash
# Minimal integration pattern
source api.func
# Basic error reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
# Report failure
post_update_to_api "failed" 127
```
### Advanced Integration Pattern
```bash
#!/usr/bin/env bash
# Advanced integration pattern
source core.func
source api.func
source error_handler.func
# Set up comprehensive API reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
export CT_TYPE=1
export DISK_SIZE=8
export CORE_COUNT=2
export RAM_SIZE=2048
export var_os="debian"
export var_version="12"
export METHOD="install"
# Enhanced error handling with API reporting
enhanced_error_handler() {
local exit_code=${1:-$?}
local command=${2:-${BASH_COMMAND:-unknown}}
local error_msg=$(get_error_description $exit_code)
echo "Error $exit_code: $error_msg"
post_update_to_api "failed" $exit_code
error_handler $exit_code $command
}
trap 'enhanced_error_handler' ERR
# Advanced operations with API reporting
post_to_api
# ... operations ...
post_update_to_api "success" 0
```
## Error Handling Integration
### Automatic Error Reporting
- **Error Descriptions**: Provides human-readable error messages
- **API Integration**: Reports errors to community-scripts.org API
- **Error Tracking**: Tracks error patterns for project improvement
- **Diagnostic Data**: Contributes to anonymous usage analytics
### Manual Error Reporting
- **Custom Error Codes**: Use appropriate error codes for different scenarios
- **Error Context**: Provide context information for errors
- **Status Updates**: Report both success and failure cases
- **Error Analysis**: Analyze error patterns and trends
### API Communication Errors
- **Network Failures**: Handle API communication failures gracefully
- **Missing Prerequisites**: Check prerequisites before API calls
- **Duplicate Prevention**: Prevent duplicate status updates
- **Error Recovery**: Handle API errors without blocking installation
## Performance Considerations
### API Communication Overhead
- **Minimal Impact**: API calls add minimal overhead
- **Asynchronous**: API calls don't block installation process
- **Error Handling**: API failures don't affect installation
- **Optional**: API reporting is optional and can be disabled
### Memory Usage
- **Minimal Footprint**: API functions use minimal memory
- **Variable Reuse**: Global variables reused across functions
- **No Memory Leaks**: Proper cleanup prevents memory leaks
- **Efficient Processing**: Efficient JSON payload creation
### Execution Speed
- **Fast API Calls**: Quick API communication
- **Efficient Error Processing**: Fast error code processing
- **Minimal Delay**: Minimal delay in API operations
- **Non-blocking**: API calls don't block installation
## Security Considerations
### Data Privacy
- **Anonymous Reporting**: Only anonymous data is sent
- **No Sensitive Data**: No sensitive information is transmitted
- **User Control**: Users can disable diagnostic reporting
- **Data Minimization**: Only necessary data is sent
### API Security
- **HTTPS**: API communication uses secure protocols
- **Data Validation**: API data is validated before sending
- **Error Handling**: API errors are handled securely
- **No Credentials**: No authentication credentials are sent
### Network Security
- **Secure Communication**: Uses secure HTTP protocols
- **Error Handling**: Network errors are handled gracefully
- **No Data Leakage**: No sensitive data is leaked
- **Secure Endpoints**: Uses trusted API endpoints
## Future Integration Considerations
### Extensibility
- **New API Endpoints**: Easy to add new API endpoints
- **Additional Data**: Easy to add new data fields
- **Error Codes**: Easy to add new error code descriptions
- **API Versions**: Easy to support new API versions
### Compatibility
- **API Versioning**: Compatible with different API versions
- **Data Format**: Compatible with different data formats
- **Error Codes**: Compatible with different error code systems
- **Network Protocols**: Compatible with different network protocols
### Performance
- **Optimization**: API communication can be optimized
- **Caching**: API responses can be cached
- **Batch Operations**: Multiple operations can be batched
- **Async Processing**: API calls can be made asynchronous

View File

@@ -0,0 +1,794 @@
# api.func Usage Examples
## Overview
This document provides practical usage examples for `api.func` functions, covering common scenarios, integration patterns, and best practices.
## Basic API Setup
### Standard API Initialization
```bash
#!/usr/bin/env bash
# Standard API setup for LXC containers
source api.func
# Set up diagnostic reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
# Set container parameters
export CT_TYPE=1
export DISK_SIZE=8
export CORE_COUNT=2
export RAM_SIZE=2048
export var_os="debian"
export var_version="12"
export NSAPP="plex"
export METHOD="install"
# Report installation start
post_to_api
# Your installation code here
# ... installation logic ...
# Report completion
if [[ $? -eq 0 ]]; then
post_update_to_api "success" 0
else
post_update_to_api "failed" $?
fi
```
### VM API Setup
```bash
#!/usr/bin/env bash
# API setup for VMs
source api.func
# Create diagnostics file for VM
mkdir -p /usr/local/community-scripts
echo "DIAGNOSTICS=yes" > /usr/local/community-scripts/diagnostics
# Set up VM parameters
export RANDOM_UUID="$(uuidgen)"
export DISK_SIZE="20G"
export CORE_COUNT=4
export RAM_SIZE=4096
export var_os="ubuntu"
export var_version="22.04"
export NSAPP="nextcloud"
export METHOD="install"
# Report VM installation start
post_to_api_vm
# Your VM installation code here
# ... VM creation logic ...
# Report completion
post_update_to_api "success" 0
```
## Error Description Examples
### Basic Error Explanation
```bash
#!/usr/bin/env bash
source api.func
# Explain common error codes
echo "Error 0: '$(get_error_description 0)'"
echo "Error 1: $(get_error_description 1)"
echo "Error 127: $(get_error_description 127)"
echo "Error 200: $(get_error_description 200)"
echo "Error 255: $(get_error_description 255)"
```
### Error Code Testing
```bash
#!/usr/bin/env bash
source api.func
# Test all error codes
test_error_codes() {
local codes=(0 1 2 127 128 130 137 139 143 200 203 205 255)
for code in "${codes[@]}"; do
echo "Code $code: $(get_error_description $code)"
done
}
test_error_codes
```
### Error Handling with Descriptions
```bash
#!/usr/bin/env bash
source api.func
# Function with error handling
run_command_with_error_handling() {
local command="$1"
local description="$2"
echo "Running: $description"
if $command; then
echo "Success: $description"
return 0
else
local exit_code=$?
local error_msg=$(get_error_description $exit_code)
echo "Error $exit_code: $error_msg"
return $exit_code
fi
}
# Usage
run_command_with_error_handling "apt-get update" "Package list update"
run_command_with_error_handling "nonexistent_command" "Test command"
```
## API Communication Examples
### LXC Installation Reporting
```bash
#!/usr/bin/env bash
source api.func
# Complete LXC installation with API reporting
install_lxc_with_reporting() {
local app="$1"
local ctid="$2"
# Set up API reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
export CT_TYPE=1
export DISK_SIZE=10
export CORE_COUNT=2
export RAM_SIZE=2048
export var_os="debian"
export var_version="12"
export NSAPP="$app"
export METHOD="install"
# Report installation start
post_to_api
# Installation process
echo "Installing $app container (ID: $ctid)..."
# Simulate installation
sleep 2
# Check if installation succeeded
if [[ $? -eq 0 ]]; then
echo "Installation completed successfully"
post_update_to_api "success" 0
return 0
else
echo "Installation failed"
post_update_to_api "failed" $?
return 1
fi
}
# Install multiple containers
install_lxc_with_reporting "plex" "100"
install_lxc_with_reporting "nextcloud" "101"
install_lxc_with_reporting "nginx" "102"
```
### VM Installation Reporting
```bash
#!/usr/bin/env bash
source api.func
# Complete VM installation with API reporting
install_vm_with_reporting() {
local app="$1"
local vmid="$2"
# Create diagnostics file
mkdir -p /usr/local/community-scripts
echo "DIAGNOSTICS=yes" > /usr/local/community-scripts/diagnostics
# Set up API reporting
export RANDOM_UUID="$(uuidgen)"
export DISK_SIZE="20G"
export CORE_COUNT=4
export RAM_SIZE=4096
export var_os="ubuntu"
export var_version="22.04"
export NSAPP="$app"
export METHOD="install"
# Report VM installation start
post_to_api_vm
# VM installation process
echo "Installing $app VM (ID: $vmid)..."
# Simulate VM creation
sleep 3
# Check if VM creation succeeded
if [[ $? -eq 0 ]]; then
echo "VM installation completed successfully"
post_update_to_api "success" 0
return 0
else
echo "VM installation failed"
post_update_to_api "failed" $?
return 1
fi
}
# Install multiple VMs
install_vm_with_reporting "nextcloud" "200"
install_vm_with_reporting "wordpress" "201"
```
## Status Update Examples
### Success Reporting
```bash
#!/usr/bin/env bash
source api.func
# Report successful installation
report_success() {
local operation="$1"
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
echo "Reporting successful $operation"
post_update_to_api "success" 0
}
# Usage
report_success "container installation"
report_success "package installation"
report_success "service configuration"
```
### Failure Reporting
```bash
#!/usr/bin/env bash
source api.func
# Report failed installation
report_failure() {
local operation="$1"
local exit_code="$2"
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
local error_msg=$(get_error_description $exit_code)
echo "Reporting failed $operation: $error_msg"
post_update_to_api "failed" $exit_code
}
# Usage
report_failure "container creation" 200
report_failure "package installation" 127
report_failure "service start" 1
```
### Conditional Status Reporting
```bash
#!/usr/bin/env bash
source api.func
# Conditional status reporting
report_installation_status() {
local operation="$1"
local exit_code="$2"
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
if [[ $exit_code -eq 0 ]]; then
echo "Reporting successful $operation"
post_update_to_api "success" 0
else
local error_msg=$(get_error_description $exit_code)
echo "Reporting failed $operation: $error_msg"
post_update_to_api "failed" $exit_code
fi
}
# Usage
report_installation_status "container creation" 0
report_installation_status "package installation" 127
```
## Advanced Usage Examples
### Batch Installation with API Reporting
```bash
#!/usr/bin/env bash
source api.func
# Batch installation with comprehensive API reporting
batch_install_with_reporting() {
local apps=("plex" "nextcloud" "nginx" "mysql")
local ctids=(100 101 102 103)
# Set up API reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
export CT_TYPE=1
export DISK_SIZE=8
export CORE_COUNT=2
export RAM_SIZE=2048
export var_os="debian"
export var_version="12"
export METHOD="install"
local success_count=0
local failure_count=0
for i in "${!apps[@]}"; do
local app="${apps[$i]}"
local ctid="${ctids[$i]}"
echo "Installing $app (ID: $ctid)..."
# Set app-specific parameters
export NSAPP="$app"
# Report installation start
post_to_api
# Simulate installation
if install_app "$app" "$ctid"; then
echo "$app installed successfully"
post_update_to_api "success" 0
((success_count++))
else
echo "$app installation failed"
post_update_to_api "failed" $?
((failure_count++))
fi
echo "---"
done
echo "Batch installation completed: $success_count successful, $failure_count failed"
}
# Mock installation function
install_app() {
local app="$1"
local ctid="$2"
# Simulate installation
sleep 1
# Simulate occasional failures
if [[ $((RANDOM % 10)) -eq 0 ]]; then
return 1
fi
return 0
}
batch_install_with_reporting
```
### Error Analysis and Reporting
```bash
#!/usr/bin/env bash
source api.func
# Analyze and report errors
analyze_and_report_errors() {
local log_file="$1"
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
if [[ ! -f "$log_file" ]]; then
echo "Log file not found: $log_file"
return 1
fi
# Extract error codes from log
local error_codes=$(grep -o 'exit code [0-9]\+' "$log_file" | grep -o '[0-9]\+' | sort -u)
if [[ -z "$error_codes" ]]; then
echo "No errors found in log"
post_update_to_api "success" 0
return 0
fi
echo "Found error codes: $error_codes"
# Report each unique error
for code in $error_codes; do
local error_msg=$(get_error_description $code)
echo "Error $code: $error_msg"
post_update_to_api "failed" $code
done
}
# Usage
analyze_and_report_errors "/var/log/installation.log"
```
### API Health Check
```bash
#!/usr/bin/env bash
source api.func
# Check API connectivity and functionality
check_api_health() {
echo "Checking API health..."
# Test prerequisites
if ! command -v curl >/dev/null 2>&1; then
echo "ERROR: curl not available"
return 1
fi
# Test error description function
local test_error=$(get_error_description 127)
if [[ -z "$test_error" ]]; then
echo "ERROR: Error description function not working"
return 1
fi
echo "Error description test: $test_error"
# Test API connectivity (without sending data)
local api_url="https://api.community-scripts.org/dev/upload"
if curl -s --head "$api_url" >/dev/null 2>&1; then
echo "API endpoint is reachable"
else
echo "WARNING: API endpoint not reachable"
fi
echo "API health check completed"
}
check_api_health
```
## Integration Examples
### With build.func
```bash
#!/usr/bin/env bash
# Integration with build.func
source core.func
source api.func
source build.func
# Set up API reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
# Container creation with API reporting
create_container_with_reporting() {
local app="$1"
local ctid="$2"
# Set container parameters
export APP="$app"
export CTID="$ctid"
export var_hostname="${app}-server"
export var_os="debian"
export var_version="12"
export var_cpu="2"
export var_ram="2048"
export var_disk="10"
export var_net="vmbr0"
export var_gateway="192.168.1.1"
export var_ip="192.168.1.$ctid"
export var_template_storage="local"
export var_container_storage="local"
# Report installation start
post_to_api
# Create container using build.func
if source build.func; then
echo "Container $app created successfully"
post_update_to_api "success" 0
return 0
else
echo "Container $app creation failed"
post_update_to_api "failed" $?
return 1
fi
}
# Create containers
create_container_with_reporting "plex" "100"
create_container_with_reporting "nextcloud" "101"
```
### With vm-core.func
```bash
#!/usr/bin/env bash
# Integration with vm-core.func
source core.func
source api.func
source vm-core.func
# Set up VM API reporting
mkdir -p /usr/local/community-scripts
echo "DIAGNOSTICS=yes" > /usr/local/community-scripts/diagnostics
export RANDOM_UUID="$(uuidgen)"
# VM creation with API reporting
create_vm_with_reporting() {
local app="$1"
local vmid="$2"
# Set VM parameters
export APP="$app"
export VMID="$vmid"
export var_hostname="${app}-vm"
export var_os="ubuntu"
export var_version="22.04"
export var_cpu="4"
export var_ram="4096"
export var_disk="20"
# Report VM installation start
post_to_api_vm
# Create VM using vm-core.func
if source vm-core.func; then
echo "VM $app created successfully"
post_update_to_api "success" 0
return 0
else
echo "VM $app creation failed"
post_update_to_api "failed" $?
return 1
fi
}
# Create VMs
create_vm_with_reporting "nextcloud" "200"
create_vm_with_reporting "wordpress" "201"
```
### With error_handler.func
```bash
#!/usr/bin/env bash
# Integration with error_handler.func
source core.func
source error_handler.func
source api.func
# Enhanced error handling with API reporting
enhanced_error_handler() {
local exit_code=${1:-$?}
local command=${2:-${BASH_COMMAND:-unknown}}
# Get error description from api.func
local error_msg=$(get_error_description $exit_code)
# Display error information
echo "Error $exit_code: $error_msg"
echo "Command: $command"
# Report error to API
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
post_update_to_api "failed" $exit_code
# Use standard error handler
error_handler $exit_code $command
}
# Set up enhanced error handling
trap 'enhanced_error_handler' ERR
# Test enhanced error handling
nonexistent_command
```
## Best Practices Examples
### Comprehensive API Integration
```bash
#!/usr/bin/env bash
# Comprehensive API integration example
source core.func
source api.func
# Set up comprehensive API reporting
setup_api_reporting() {
# Enable diagnostics
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
# Set common parameters
export CT_TYPE=1
export DISK_SIZE=8
export CORE_COUNT=2
export RAM_SIZE=2048
export var_os="debian"
export var_version="12"
export METHOD="install"
echo "API reporting configured"
}
# Installation with comprehensive reporting
install_with_comprehensive_reporting() {
local app="$1"
local ctid="$2"
# Set up API reporting
setup_api_reporting
export NSAPP="$app"
# Report installation start
post_to_api
# Installation process
echo "Installing $app..."
# Simulate installation steps
local steps=("Downloading" "Installing" "Configuring" "Starting")
for step in "${steps[@]}"; do
echo "$step $app..."
sleep 1
done
# Check installation result
if [[ $? -eq 0 ]]; then
echo "$app installation completed successfully"
post_update_to_api "success" 0
return 0
else
echo "$app installation failed"
post_update_to_api "failed" $?
return 1
fi
}
# Install multiple applications
apps=("plex" "nextcloud" "nginx" "mysql")
ctids=(100 101 102 103)
for i in "${!apps[@]}"; do
install_with_comprehensive_reporting "${apps[$i]}" "${ctids[$i]}"
echo "---"
done
```
### Error Recovery with API Reporting
```bash
#!/usr/bin/env bash
source api.func
# Error recovery with API reporting
retry_with_api_reporting() {
local operation="$1"
local max_attempts=3
local attempt=1
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
while [[ $attempt -le $max_attempts ]]; do
echo "Attempt $attempt of $max_attempts: $operation"
if $operation; then
echo "Operation succeeded on attempt $attempt"
post_update_to_api "success" 0
return 0
else
local exit_code=$?
local error_msg=$(get_error_description $exit_code)
echo "Attempt $attempt failed: $error_msg"
post_update_to_api "failed" $exit_code
((attempt++))
if [[ $attempt -le $max_attempts ]]; then
echo "Retrying in 5 seconds..."
sleep 5
fi
fi
done
echo "Operation failed after $max_attempts attempts"
return 1
}
# Usage
retry_with_api_reporting "apt-get update"
retry_with_api_reporting "apt-get install -y package"
```
### API Reporting with Logging
```bash
#!/usr/bin/env bash
source api.func
# API reporting with detailed logging
install_with_logging_and_api() {
local app="$1"
local log_file="/var/log/${app}_installation.log"
# Set up API reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
export NSAPP="$app"
# Start logging
exec > >(tee -a "$log_file")
exec 2>&1
echo "Starting $app installation at $(date)"
# Report installation start
post_to_api
# Installation process
echo "Installing $app..."
# Simulate installation
if install_app "$app"; then
echo "$app installation completed successfully at $(date)"
post_update_to_api "success" 0
return 0
else
local exit_code=$?
local error_msg=$(get_error_description $exit_code)
echo "$app installation failed at $(date): $error_msg"
post_update_to_api "failed" $exit_code
return $exit_code
fi
}
# Mock installation function
install_app() {
local app="$1"
echo "Installing $app..."
sleep 2
return 0
}
# Install with logging and API reporting
install_with_logging_and_api "plex"
```

View File

@@ -0,0 +1,199 @@
# api.func Documentation
## Overview
The `api.func` file provides Proxmox API integration and diagnostic reporting functionality for the Community Scripts project. It handles API communication, error reporting, and status updates to the community-scripts.org API.
## Purpose and Use Cases
- **API Communication**: Send installation and status data to community-scripts.org API
- **Diagnostic Reporting**: Report installation progress and errors for analytics
- **Error Description**: Provide detailed error code explanations
- **Status Updates**: Track installation success/failure status
- **Analytics**: Contribute anonymous usage data for project improvement
## Quick Reference
### Key Function Groups
- **Error Handling**: `get_error_description()` - Convert exit codes to human-readable messages
- **API Communication**: `post_to_api()`, `post_to_api_vm()` - Send installation data
- **Status Updates**: `post_update_to_api()` - Report installation completion status
### Dependencies
- **External**: `curl` command for HTTP requests
- **Internal**: Uses environment variables from other scripts
### Integration Points
- Used by: All installation scripts for diagnostic reporting
- Uses: Environment variables from build.func and other scripts
- Provides: API communication and error reporting services
## Documentation Files
### 📊 [API_FLOWCHART.md](./API_FLOWCHART.md)
Visual execution flows showing API communication processes and error handling.
### 📚 [API_FUNCTIONS_REFERENCE.md](./API_FUNCTIONS_REFERENCE.md)
Complete alphabetical reference of all functions with parameters, dependencies, and usage details.
### 💡 [API_USAGE_EXAMPLES.md](./API_USAGE_EXAMPLES.md)
Practical examples showing how to use API functions and common patterns.
### 🔗 [API_INTEGRATION.md](./API_INTEGRATION.md)
How api.func integrates with other components and provides API services.
## Key Features
### Error Code Descriptions
- **Comprehensive Coverage**: 50+ error codes with detailed explanations
- **LXC-Specific Errors**: Container creation and management errors
- **System Errors**: General system and network errors
- **Signal Errors**: Process termination and signal errors
### API Communication
- **LXC Reporting**: Send LXC container installation data
- **VM Reporting**: Send VM installation data
- **Status Updates**: Report installation success/failure
- **Diagnostic Data**: Anonymous usage analytics
### Diagnostic Integration
- **Optional Reporting**: Only sends data when diagnostics enabled
- **Privacy Respect**: Respects user privacy settings
- **Error Tracking**: Tracks installation errors for improvement
- **Usage Analytics**: Contributes to project statistics
## Common Usage Patterns
### Basic API Setup
```bash
#!/usr/bin/env bash
# Basic API setup
source api.func
# Set up diagnostic reporting
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
# Report installation start
post_to_api
```
### Error Reporting
```bash
#!/usr/bin/env bash
source api.func
# Get error description
error_msg=$(get_error_description 127)
echo "Error 127: $error_msg"
# Output: Error 127: Command not found: Incorrect path or missing dependency.
```
### Status Updates
```bash
#!/usr/bin/env bash
source api.func
# Report successful installation
post_update_to_api "success" 0
# Report failed installation
post_update_to_api "failed" 127
```
## Environment Variables
### Required Variables
- `DIAGNOSTICS`: Enable/disable diagnostic reporting ("yes"/"no")
- `RANDOM_UUID`: Unique identifier for tracking
### Optional Variables
- `CT_TYPE`: Container type (1 for LXC, 2 for VM)
- `DISK_SIZE`: Disk size in GB
- `CORE_COUNT`: Number of CPU cores
- `RAM_SIZE`: RAM size in MB
- `var_os`: Operating system type
- `var_version`: OS version
- `DISABLEIP6`: IPv6 disable setting
- `NSAPP`: Namespace application name
- `METHOD`: Installation method
### Internal Variables
- `POST_UPDATE_DONE`: Prevents duplicate status updates
- `API_URL`: Community scripts API endpoint
- `JSON_PAYLOAD`: API request payload
- `RESPONSE`: API response
## Error Code Categories
### General System Errors
- **0-9**: Basic system errors
- **18, 22, 28, 35**: Network and I/O errors
- **56, 60**: TLS/SSL errors
- **125-128**: Command execution errors
- **129-143**: Signal errors
- **152**: Resource limit errors
- **255**: Unknown critical errors
### LXC-Specific Errors
- **100-101**: LXC installation errors
- **200-209**: LXC creation and management errors
### Docker Errors
- **125**: Docker container start errors
## Best Practices
### Diagnostic Reporting
1. Always check if diagnostics are enabled
2. Respect user privacy settings
3. Use unique identifiers for tracking
4. Report both success and failure cases
### Error Handling
1. Use appropriate error codes
2. Provide meaningful error descriptions
3. Handle API communication failures gracefully
4. Don't block installation on API failures
### API Usage
1. Check for curl availability
2. Handle network failures gracefully
3. Use appropriate HTTP methods
4. Include all required data
## Troubleshooting
### Common Issues
1. **API Communication Fails**: Check network connectivity and curl availability
2. **Diagnostics Not Working**: Verify DIAGNOSTICS setting and RANDOM_UUID
3. **Missing Error Descriptions**: Check error code coverage
4. **Duplicate Updates**: POST_UPDATE_DONE prevents duplicates
### Debug Mode
Enable diagnostic reporting for debugging:
```bash
export DIAGNOSTICS="yes"
export RANDOM_UUID="$(uuidgen)"
```
### API Testing
Test API communication:
```bash
source api.func
export DIAGNOSTICS="yes"
export RANDOM_UUID="test-$(date +%s)"
post_to_api
```
## Related Documentation
- [core.func](../core.func/) - Core utilities and error handling
- [error_handler.func](../error_handler.func/) - Error handling utilities
- [build.func](../build.func/) - Container creation with API integration
- [tools.func](../tools.func/) - Extended utilities with API integration
---
*This documentation covers the api.func file which provides API communication and diagnostic reporting for all Proxmox Community Scripts.*

View File

@@ -0,0 +1,164 @@
# Advanced Settings Wizard Reference
## Overview
The Advanced Settings wizard provides a 28-step interactive configuration for LXC container creation. It allows users to customize every aspect of the container while inheriting sensible defaults from the CT script.
## Key Features
- **Inherit App Defaults**: All `var_*` values from CT scripts pre-populate wizard fields
- **Back Navigation**: Press Cancel/Back to return to previous step
- **App Default Hints**: Each dialog shows `(App default: X)` to indicate script defaults
- **Full Customization**: Every configurable option is accessible
## Wizard Steps
| Step | Title | Variable(s) | Description |
| ---- | ------------------------ | --------------------------------- | ----------------------------------------------------- |
| 1 | Container Type | `var_unprivileged` | Privileged (0) or Unprivileged (1) container |
| 2 | Root Password | `var_pw` | Set password or use automatic login |
| 3 | Container ID | `var_ctid` | Unique container ID (auto-suggested) |
| 4 | Hostname | `var_hostname` | Container hostname |
| 5 | Disk Size | `var_disk` | Disk size in GB |
| 6 | CPU Cores | `var_cpu` | Number of CPU cores |
| 7 | RAM Size | `var_ram` | RAM size in MiB |
| 8 | Network Bridge | `var_brg` | Network bridge (vmbr0, etc.) |
| 9 | IPv4 Configuration | `var_net`, `var_gateway` | DHCP or static IP with gateway |
| 10 | IPv6 Configuration | `var_ipv6_method` | Auto, DHCP, Static, or None |
| 11 | MTU Size | `var_mtu` | Network MTU (default: 1500) |
| 12 | DNS Search Domain | `var_searchdomain` | DNS search domain |
| 13 | DNS Server | `var_ns` | Custom DNS server IP |
| 14 | MAC Address | `var_mac` | Custom MAC address (auto-generated if empty) |
| 15 | VLAN Tag | `var_vlan` | VLAN tag ID |
| 16 | Tags | `var_tags` | Container tags (comma/semicolon separated) |
| 17 | SSH Settings | `var_ssh` | SSH key selection and root access |
| 18 | FUSE Support | `var_fuse` | Enable FUSE for rclone, mergerfs, AppImage |
| 19 | TUN/TAP Support | `var_tun` | Enable for VPN apps (WireGuard, OpenVPN, Tailscale) |
| 20 | Nesting Support | `var_nesting` | Enable for Docker, LXC in LXC, Podman |
| 21 | GPU Passthrough | `var_gpu` | Auto-detect and pass through Intel/AMD/NVIDIA GPUs |
| 22 | Keyctl Support | `var_keyctl` | Enable for Docker, systemd-networkd |
| 23 | APT Cacher Proxy | `var_apt_cacher`, `var_apt_cacher_ip` | Use apt-cacher-ng for faster downloads |
| 24 | Container Timezone | `var_timezone` | Set timezone (e.g., Europe/Berlin) |
| 25 | Container Protection | `var_protection` | Prevent accidental deletion |
| 26 | Device Node Creation | `var_mknod` | Allow mknod (experimental, kernel 5.3+) |
| 27 | Mount Filesystems | `var_mount_fs` | Allow specific mounts: nfs, cifs, fuse, etc. |
| 28 | Verbose Mode & Confirm | `var_verbose` | Enable verbose output + final confirmation |
## Default Value Inheritance
The wizard inherits defaults from multiple sources:
```text
CT Script (var_*) → default.vars → app.vars → User Input
```
### Example: VPN Container (alpine-wireguard.sh)
```bash
# CT script sets:
var_tun="${var_tun:-1}" # TUN enabled by default
# In Advanced Settings Step 19:
# Dialog shows: "(App default: 1)" and pre-selects "Yes"
```
### Example: Media Server (jellyfin.sh)
```bash
# CT script sets:
var_gpu="${var_gpu:-yes}" # GPU enabled by default
# In Advanced Settings Step 21:
# Dialog shows: "(App default: yes)" and pre-selects "Yes"
```
## Feature Matrix
| Feature | Variable | When to Enable |
| ----------------- | ---------------- | --------------------------------------------------- |
| FUSE | `var_fuse` | rclone, mergerfs, AppImage, SSHFS |
| TUN/TAP | `var_tun` | WireGuard, OpenVPN, Tailscale, VPN containers |
| Nesting | `var_nesting` | Docker, Podman, LXC-in-LXC, systemd-nspawn |
| GPU Passthrough | `var_gpu` | Plex, Jellyfin, Emby, Frigate, Ollama, ComfyUI |
| Keyctl | `var_keyctl` | Docker (unprivileged), systemd-networkd |
| Protection | `var_protection` | Production containers, prevent accidental deletion |
| Mknod | `var_mknod` | Device node creation (experimental) |
| Mount FS | `var_mount_fs` | NFS mounts, CIFS shares, custom filesystems |
| APT Cacher | `var_apt_cacher` | Speed up downloads with local apt-cacher-ng |
## Confirmation Summary
Step 28 displays a comprehensive summary before creation:
```text
Container Type: Unprivileged
Container ID: 100
Hostname: jellyfin
Resources:
Disk: 8 GB
CPU: 2 cores
RAM: 2048 MiB
Network:
Bridge: vmbr0
IPv4: dhcp
IPv6: auto
Features:
FUSE: no | TUN: no
Nesting: Enabled | Keyctl: Disabled
GPU: yes | Protection: No
Advanced:
Timezone: Europe/Berlin
APT Cacher: no
Verbose: no
```
## Usage Examples
### Skip to Advanced Settings
```bash
# Run script, select "Advanced" from menu
bash -c "$(curl -fsSL https://...jellyfin.sh)"
# Then select option 3 "Advanced"
```
### Pre-set Defaults via Environment
```bash
# Set defaults before running
export var_cpu=4
export var_ram=4096
export var_gpu=yes
bash -c "$(curl -fsSL https://...jellyfin.sh)"
# Advanced settings will inherit these values
```
### Non-Interactive with All Options
```bash
# Set all variables for fully automated deployment
export var_unprivileged=1
export var_cpu=2
export var_ram=2048
export var_disk=8
export var_net=dhcp
export var_fuse=no
export var_tun=no
export var_gpu=yes
export var_nesting=1
export var_protection=no
export var_verbose=no
bash -c "$(curl -fsSL https://...jellyfin.sh)"
```
## Notes
- **Cancel at Step 1**: Exits the script entirely
- **Cancel at Steps 2-28**: Goes back to previous step
- **Empty fields**: Use default value
- **Keyctl**: Automatically enabled for unprivileged containers
- **Nesting**: Enabled by default (required for many apps)

View File

@@ -0,0 +1,410 @@
# build.func Architecture Guide
## Overview
This document provides a high-level architectural overview of `build.func`, including module dependencies, data flow, integration points, and system architecture.
## High-Level Architecture
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Proxmox Host System │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ build.func │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────────┐ │ │
│ │ │ Entry Point │ │ Configuration │ │ Container Creation │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ • start() │ │ • variables() │ │ • build_container() │ │ │
│ │ │ • install_ │ │ • base_ │ │ • create_lxc_container() │ │ │
│ │ │ script() │ │ settings() │ │ • configure_gpu_ │ │ │
│ │ │ • advanced_ │ │ • select_ │ │ passthrough() │ │ │
│ │ │ settings() │ │ storage() │ │ • fix_gpu_gids() │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ Module Dependencies │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────────┐ │ │
│ │ │ core.func │ │ error_handler. │ │ api.func │ │ │
│ │ │ │ │ func │ │ │ │ │
│ │ │ • Basic │ │ • Error │ │ • Proxmox API │ │ │
│ │ │ utilities │ │ handling │ │ interactions │ │ │
│ │ │ • Common │ │ • Error │ │ • Container │ │ │
│ │ │ functions │ │ recovery │ │ management │ │ │
│ │ │ • System │ │ • Cleanup │ │ • Status │ │ │
│ │ │ utilities │ │ functions │ │ monitoring │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────────────────┐ │ │
│ │ │ tools.func │ │ │
│ │ │ │ │ │
│ │ │ • Additional utilities │ │ │
│ │ │ • Helper functions │ │ │
│ │ │ • System tools │ │ │
│ │ └─────────────────────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
```
## Module Dependencies
### Core Dependencies
```
build.func Dependencies:
├── core.func
│ ├── Basic system utilities
│ ├── Common functions
│ ├── System information
│ └── File operations
├── error_handler.func
│ ├── Error handling
│ ├── Error recovery
│ ├── Cleanup functions
│ └── Error logging
├── api.func
│ ├── Proxmox API interactions
│ ├── Container management
│ ├── Status monitoring
│ └── Configuration updates
└── tools.func
├── Additional utilities
├── Helper functions
├── System tools
└── Custom functions
```
### Dependency Flow
```
Dependency Flow:
├── build.func
│ ├── Sources core.func
│ ├── Sources error_handler.func
│ ├── Sources api.func
│ └── Sources tools.func
├── core.func
│ ├── Basic utilities
│ └── System functions
├── error_handler.func
│ ├── Error management
│ └── Recovery functions
├── api.func
│ ├── Proxmox integration
│ └── Container operations
└── tools.func
├── Additional tools
└── Helper functions
```
## Data Flow Architecture
### Configuration Data Flow
```
Configuration Data Flow:
├── Environment Variables
│ ├── Hard environment variables
│ ├── App-specific .vars
│ ├── Global default.vars
│ └── Built-in defaults
├── Variable Resolution
│ ├── Apply precedence chain
│ ├── Validate settings
│ └── Resolve conflicts
├── Configuration Storage
│ ├── Memory variables
│ ├── Temporary files
│ └── Persistent storage
└── Configuration Usage
├── Container creation
├── Feature configuration
└── Settings persistence
```
### Container Data Flow
```
Container Data Flow:
├── Input Data
│ ├── Configuration variables
│ ├── Resource specifications
│ ├── Network settings
│ └── Storage requirements
├── Processing
│ ├── Validation
│ ├── Conflict resolution
│ ├── Resource allocation
│ └── Configuration generation
├── Container Creation
│ ├── LXC container creation
│ ├── Network configuration
│ ├── Storage setup
│ └── Feature configuration
└── Output
├── Container status
├── Access information
├── Configuration files
└── Log files
```
## Integration Architecture
### With Proxmox System
```
Proxmox Integration:
├── Proxmox Host
│ ├── LXC container management
│ ├── Storage management
│ ├── Network management
│ └── Resource management
├── Proxmox API
│ ├── Container operations
│ ├── Configuration updates
│ ├── Status monitoring
│ └── Error handling
├── Proxmox Configuration
│ ├── /etc/pve/lxc/<ctid>.conf
│ ├── Storage configuration
│ ├── Network configuration
│ └── Resource configuration
└── Proxmox Services
├── Container services
├── Network services
├── Storage services
└── Monitoring services
```
### With Install Scripts
```
Install Script Integration:
├── build.func
│ ├── Creates container
│ ├── Configures basic settings
│ ├── Starts container
│ └── Provides access
├── Install Scripts
│ ├── <app>-install.sh
│ ├── Downloads application
│ ├── Configures application
│ └── Sets up services
├── Container
│ ├── Running application
│ ├── Configured services
│ ├── Network access
│ └── Storage access
└── Integration Points
├── Container creation
├── Network configuration
├── Storage setup
└── Service configuration
```
## System Architecture Components
### Core Components
```
System Components:
├── Entry Point
│ ├── start() function
│ ├── Context detection
│ ├── Environment capture
│ └── Workflow routing
├── Configuration Management
│ ├── Variable resolution
│ ├── Settings persistence
│ ├── Default management
│ └── Validation
├── Container Creation
│ ├── LXC container creation
│ ├── Network configuration
│ ├── Storage setup
│ └── Feature configuration
├── Hardware Integration
│ ├── GPU passthrough
│ ├── USB passthrough
│ ├── Storage management
│ └── Network management
└── Error Handling
├── Error detection
├── Error recovery
├── Cleanup functions
└── User notification
```
### User Interface Components
```
UI Components:
├── Menu System
│ ├── Installation mode selection
│ ├── Configuration menus
│ ├── Storage selection
│ └── GPU configuration
├── Interactive Elements
│ ├── Whiptail menus
│ ├── User prompts
│ ├── Confirmation dialogs
│ └── Error messages
├── Non-Interactive Mode
│ ├── Environment variable driven
│ ├── Silent execution
│ ├── Automated configuration
│ └── Error handling
└── Output
├── Status messages
├── Progress indicators
├── Completion information
└── Access details
```
## Security Architecture
### Security Considerations
```
Security Architecture:
├── Container Security
│ ├── Unprivileged containers (default)
│ ├── Privileged containers (when needed)
│ ├── Resource limits
│ └── Access controls
├── Network Security
│ ├── Network isolation
│ ├── VLAN support
│ ├── Firewall integration
│ └── Access controls
├── Storage Security
│ ├── Storage isolation
│ ├── Access controls
│ ├── Encryption support
│ └── Backup integration
├── GPU Security
│ ├── Device isolation
│ ├── Permission management
│ ├── Access controls
│ └── Security validation
└── API Security
├── Authentication
├── Authorization
├── Input validation
└── Error handling
```
## Performance Architecture
### Performance Considerations
```
Performance Architecture:
├── Execution Optimization
│ ├── Parallel operations
│ ├── Efficient algorithms
│ ├── Minimal user interaction
│ └── Optimized validation
├── Resource Management
│ ├── Memory efficiency
│ ├── CPU optimization
│ ├── Disk usage optimization
│ └── Network efficiency
├── Caching
│ ├── Configuration caching
│ ├── Template caching
│ ├── Storage caching
│ └── GPU detection caching
└── Monitoring
├── Performance monitoring
├── Resource monitoring
├── Error monitoring
└── Status monitoring
```
## Deployment Architecture
### Deployment Scenarios
```
Deployment Scenarios:
├── Single Container
│ ├── Individual application
│ ├── Standard configuration
│ ├── Basic networking
│ └── Standard storage
├── Multiple Containers
│ ├── Application stack
│ ├── Shared networking
│ ├── Shared storage
│ └── Coordinated deployment
├── High Availability
│ ├── Redundant containers
│ ├── Load balancing
│ ├── Failover support
│ └── Monitoring integration
└── Development Environment
├── Development containers
├── Testing containers
├── Staging containers
└── Production containers
```
## Maintenance Architecture
### Maintenance Components
```
Maintenance Architecture:
├── Updates
│ ├── Container updates
│ ├── Application updates
│ ├── Configuration updates
│ └── Security updates
├── Monitoring
│ ├── Container monitoring
│ ├── Resource monitoring
│ ├── Performance monitoring
│ └── Error monitoring
├── Backup
│ ├── Configuration backup
│ ├── Container backup
│ ├── Storage backup
│ └── Recovery procedures
└── Troubleshooting
├── Error diagnosis
├── Log analysis
├── Performance analysis
└── Recovery procedures
```
## Future Architecture Considerations
### Scalability
```
Scalability Considerations:
├── Horizontal Scaling
│ ├── Multiple containers
│ ├── Load balancing
│ ├── Distributed deployment
│ └── Resource distribution
├── Vertical Scaling
│ ├── Resource scaling
│ ├── Performance optimization
│ ├── Capacity planning
│ └── Resource management
├── Automation
│ ├── Automated deployment
│ ├── Automated scaling
│ ├── Automated monitoring
│ └── Automated recovery
└── Integration
├── External systems
├── Cloud integration
├── Container orchestration
└── Service mesh
```

Some files were not shown because too many files have changed in this diff Show More