Compare commits
75 Commits
MickLesk-p
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e76681ed8e | ||
|
|
87bb2a34ca | ||
|
|
2b907821a7 | ||
|
|
96d9835d79 | ||
|
|
bba8577237 | ||
|
|
b4a824b9a1 | ||
|
|
bd5e20237f | ||
|
|
96fc169f4b | ||
|
|
74007d3f72 | ||
|
|
7fec6ed156 | ||
|
|
a6921a33f3 | ||
|
|
fde17c12ed | ||
|
|
16f7904371 | ||
|
|
eb0a973c62 | ||
|
|
0deb262d5f | ||
|
|
91950cc983 | ||
|
|
f0fc1aff4e | ||
|
|
13a836c44d | ||
|
|
7df3ff5ece | ||
|
|
1f3970fcf7 | ||
|
|
8c3ebdd166 | ||
|
|
8883957393 | ||
|
|
a21f901a1a | ||
|
|
d2c4288395 | ||
|
|
9066f6511a | ||
|
|
c281d7ce68 | ||
|
|
e7f51e92d2 | ||
|
|
70914c20a2 | ||
|
|
97b44d8a26 | ||
|
|
055abcb99f | ||
|
|
b76e25910d | ||
|
|
34250d6adf | ||
|
|
7738065237 | ||
|
|
b833eb68eb | ||
|
|
cc8dd29f63 | ||
|
|
4b3d9366d2 | ||
|
|
0527db122b | ||
|
|
b689917eee | ||
|
|
8bb2f28b48 | ||
|
|
71c02e052b | ||
|
|
105dceb42e | ||
|
|
8ba7b55cd5 | ||
|
|
6a7da073f8 | ||
|
|
366626be9c | ||
|
|
599aa97a92 | ||
|
|
3981500e65 | ||
|
|
b96c20db88 | ||
|
|
b365a78807 | ||
|
|
f19a59e4f1 | ||
|
|
47b5bd40f8 | ||
|
|
170dce61d2 | ||
|
|
85de978ea4 | ||
|
|
e275cafc13 | ||
|
|
0762e41e83 | ||
|
|
c4670a25c2 | ||
|
|
e6e3c47beb | ||
|
|
19d7d58a64 | ||
|
|
7ab160ff75 | ||
|
|
8a5acacd52 | ||
|
|
aaaf18de91 | ||
|
|
67de69f8bb | ||
|
|
67e0db6d48 | ||
|
|
11055a22fb | ||
|
|
b4b8f1c118 | ||
|
|
b8f490d8c8 | ||
|
|
b3e9814d79 | ||
|
|
7393d85f74 | ||
|
|
549789a6a7 | ||
|
|
fbd9cfa90c | ||
|
|
be57260532 | ||
|
|
d694185e17 | ||
|
|
33185f12c1 | ||
|
|
ec12d0f31a | ||
|
|
fdd9a22992 | ||
|
|
88f4f966d2 |
19
.github/workflows/move-to-main-repo.yaml
generated
vendored
19
.github/workflows/move-to-main-repo.yaml
generated
vendored
@@ -39,11 +39,22 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
echo "Filtering Issues with Label Migration To ProxmoxVE"
|
echo "Resolving issue with label Migration To ProxmoxVE"
|
||||||
raw_output=$(gh issue list --json title,labels,number,body)
|
|
||||||
filtered_issue=$(echo "$raw_output" | jq -r '[.[] | select(.labels[]?.name == "Migration To ProxmoxVE")][0]')
|
|
||||||
|
|
||||||
if [ "$filtered_issue" == "null" ] || [ -z "$filtered_issue" ]; then
|
if [[ "${{ github.event_name }}" == "issues" ]]; then
|
||||||
|
# For labeled issue events, use the exact issue from event payload.
|
||||||
|
filtered_issue='${{ toJson(github.event.issue) }}'
|
||||||
|
else
|
||||||
|
# Fallback for workflow_dispatch: query explicitly by label and raise limit.
|
||||||
|
raw_output=$(gh issue list \
|
||||||
|
--label "Migration To ProxmoxVE" \
|
||||||
|
--state open \
|
||||||
|
--limit 500 \
|
||||||
|
--json title,labels,number,body)
|
||||||
|
filtered_issue=$(echo "$raw_output" | jq -c '.[0]')
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$filtered_issue" == "null" ]] || [[ -z "$filtered_issue" ]]; then
|
||||||
echo "No issues found with label 'Migration To ProxmoxVE'."
|
echo "No issues found with label 'Migration To ProxmoxVE'."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
676
.github/workflows/pocketbase-bot.yml
generated
vendored
Normal file
676
.github/workflows/pocketbase-bot.yml
generated
vendored
Normal file
@@ -0,0 +1,676 @@
|
|||||||
|
name: PocketBase Bot
|
||||||
|
|
||||||
|
on:
|
||||||
|
issue_comment:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pocketbase-bot:
|
||||||
|
runs-on: self-hosted
|
||||||
|
|
||||||
|
# Only act on /pocketbase commands
|
||||||
|
if: startsWith(github.event.comment.body, '/pocketbase')
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Execute PocketBase bot command
|
||||||
|
env:
|
||||||
|
POCKETBASE_URL: ${{ secrets.POCKETBASE_URL }}
|
||||||
|
POCKETBASE_COLLECTION: ${{ secrets.POCKETBASE_COLLECTION }}
|
||||||
|
POCKETBASE_ADMIN_EMAIL: ${{ secrets.POCKETBASE_ADMIN_EMAIL }}
|
||||||
|
POCKETBASE_ADMIN_PASSWORD: ${{ secrets.POCKETBASE_ADMIN_PASSWORD }}
|
||||||
|
COMMENT_BODY: ${{ github.event.comment.body }}
|
||||||
|
COMMENT_ID: ${{ github.event.comment.id }}
|
||||||
|
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||||
|
REPO_OWNER: ${{ github.repository_owner }}
|
||||||
|
REPO_NAME: ${{ github.event.repository.name }}
|
||||||
|
ACTOR: ${{ github.event.comment.user.login }}
|
||||||
|
ACTOR_ASSOCIATION: ${{ github.event.comment.author_association }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
node << 'ENDSCRIPT'
|
||||||
|
(async function () {
|
||||||
|
const https = require('https');
|
||||||
|
const http = require('http');
|
||||||
|
const url = require('url');
|
||||||
|
|
||||||
|
// ── HTTP helper with redirect following ────────────────────────────
|
||||||
|
function request(fullUrl, opts, redirectCount) {
|
||||||
|
redirectCount = redirectCount || 0;
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
const u = url.parse(fullUrl);
|
||||||
|
const isHttps = u.protocol === 'https:';
|
||||||
|
const body = opts.body;
|
||||||
|
const options = {
|
||||||
|
hostname: u.hostname,
|
||||||
|
port: u.port || (isHttps ? 443 : 80),
|
||||||
|
path: u.path,
|
||||||
|
method: opts.method || 'GET',
|
||||||
|
headers: opts.headers || {}
|
||||||
|
};
|
||||||
|
if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
|
||||||
|
const lib = isHttps ? https : http;
|
||||||
|
const req = lib.request(options, function (res) {
|
||||||
|
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||||
|
if (redirectCount >= 5) return reject(new Error('Too many redirects from ' + fullUrl));
|
||||||
|
const redirectUrl = url.resolve(fullUrl, res.headers.location);
|
||||||
|
res.resume();
|
||||||
|
resolve(request(redirectUrl, opts, redirectCount + 1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let data = '';
|
||||||
|
res.on('data', function (chunk) { data += chunk; });
|
||||||
|
res.on('end', function () {
|
||||||
|
resolve({ ok: res.statusCode >= 200 && res.statusCode < 300, statusCode: res.statusCode, body: data });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
req.on('error', reject);
|
||||||
|
if (body) req.write(body);
|
||||||
|
req.end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── GitHub API helpers ─────────────────────────────────────────────
|
||||||
|
const owner = process.env.REPO_OWNER;
|
||||||
|
const repo = process.env.REPO_NAME;
|
||||||
|
const issueNumber = parseInt(process.env.ISSUE_NUMBER, 10);
|
||||||
|
const commentId = parseInt(process.env.COMMENT_ID, 10);
|
||||||
|
const actor = process.env.ACTOR;
|
||||||
|
|
||||||
|
function ghRequest(path, method, body) {
|
||||||
|
const headers = {
|
||||||
|
'Authorization': 'Bearer ' + process.env.GITHUB_TOKEN,
|
||||||
|
'Accept': 'application/vnd.github+json',
|
||||||
|
'X-GitHub-Api-Version': '2022-11-28',
|
||||||
|
'User-Agent': 'PocketBase-Bot'
|
||||||
|
};
|
||||||
|
const bodyStr = body ? JSON.stringify(body) : undefined;
|
||||||
|
if (bodyStr) headers['Content-Type'] = 'application/json';
|
||||||
|
return request('https://api.github.com' + path, { method: method || 'GET', headers, body: bodyStr });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addReaction(content) {
|
||||||
|
try {
|
||||||
|
await ghRequest(
|
||||||
|
'/repos/' + owner + '/' + repo + '/issues/comments/' + commentId + '/reactions',
|
||||||
|
'POST', { content }
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Could not add reaction:', e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function postComment(text) {
|
||||||
|
const res = await ghRequest(
|
||||||
|
'/repos/' + owner + '/' + repo + '/issues/' + issueNumber + '/comments',
|
||||||
|
'POST', { body: text }
|
||||||
|
);
|
||||||
|
if (!res.ok) console.warn('Could not post comment:', res.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 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');
|
||||||
|
await postComment(
|
||||||
|
'❌ **PocketBase Bot**: @' + actor + ' is not authorized to use this command.\n' +
|
||||||
|
'Only org members (Contributors team) can use `/pocketbase`.'
|
||||||
|
);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Acknowledge ────────────────────────────────────────────────────
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
const codeBlockValue = extractCodeBlock(commentBody);
|
||||||
|
|
||||||
|
const HELP_TEXT =
|
||||||
|
'**Field update (simple):** `/pocketbase <slug> field=value [field=value ...]`\n\n' +
|
||||||
|
'**Field update (HTML/multiline) — value from code block:**\n' +
|
||||||
|
'````\n' +
|
||||||
|
'/pocketbase <slug> set description\n' +
|
||||||
|
'```html\n' +
|
||||||
|
'<p>Your <b>HTML</b> or multi-line content here</p>\n' +
|
||||||
|
'```\n' +
|
||||||
|
'````\n\n' +
|
||||||
|
'**Note management:**\n' +
|
||||||
|
'```\n' +
|
||||||
|
'/pocketbase <slug> note list\n' +
|
||||||
|
'/pocketbase <slug> note add <type> "<text>"\n' +
|
||||||
|
'/pocketbase <slug> note edit <type> "<old text>" "<new text>"\n' +
|
||||||
|
'/pocketbase <slug> note remove <type> "<text>"\n' +
|
||||||
|
'```\n\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' +
|
||||||
|
'```\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` ' +
|
||||||
|
'`is_disabled` `disable_message` `is_deleted` `deleted_message`';
|
||||||
|
|
||||||
|
if (!withoutCmd) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment('❌ **PocketBase Bot**: No slug or command specified.\n\n' + HELP_TEXT);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const spaceIdx = withoutCmd.indexOf(' ');
|
||||||
|
const slug = (spaceIdx === -1 ? withoutCmd : withoutCmd.substring(0, spaceIdx)).trim();
|
||||||
|
const rest = spaceIdx === -1 ? '' : withoutCmd.substring(spaceIdx + 1).trim();
|
||||||
|
|
||||||
|
if (!rest) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment('❌ **PocketBase Bot**: No command specified for slug `' + slug + '`.\n\n' + HELP_TEXT);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 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;
|
||||||
|
|
||||||
|
const authRes = await request(apiBase + '/collections/users/auth-with-password', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
identity: process.env.POCKETBASE_ADMIN_EMAIL,
|
||||||
|
password: process.env.POCKETBASE_ADMIN_PASSWORD
|
||||||
|
})
|
||||||
|
});
|
||||||
|
if (!authRes.ok) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment('❌ **PocketBase Bot**: PocketBase authentication failed. CC @' + owner + '/maintainers');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
const token = JSON.parse(authRes.body).token;
|
||||||
|
|
||||||
|
// ── 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', {
|
||||||
|
headers: { 'Authorization': token }
|
||||||
|
});
|
||||||
|
const list = JSON.parse(listRes.body);
|
||||||
|
const record = list.items && list.items[0];
|
||||||
|
|
||||||
|
if (!record) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment(
|
||||||
|
'❌ **PocketBase Bot**: No record found for slug `' + slug + '`.\n\n' +
|
||||||
|
'Make sure the script was already pushed to PocketBase (JSON must exist and have been synced).'
|
||||||
|
);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Route: dispatch to subcommand handler ──────────────────────────
|
||||||
|
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 (noteMatch) {
|
||||||
|
// ── NOTE SUBCOMMAND (reads/writes notes_json on script record) ────
|
||||||
|
const noteAction = noteMatch[1].toLowerCase();
|
||||||
|
const noteArgsStr = rest.substring(noteMatch[0].length).trim();
|
||||||
|
|
||||||
|
// 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' },
|
||||||
|
body: JSON.stringify({ notes_json: JSON.stringify(arr) })
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment('❌ **PocketBase Bot**: Failed to update `notes_json`:\n```\n' + res.body + '\n```');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noteAction === 'list') {
|
||||||
|
await addReaction('+1');
|
||||||
|
await postComment(
|
||||||
|
'ℹ️ **PocketBase Bot**: Notes for **`' + slug + '`** (' + notesArr.length + ' total)\n\n' +
|
||||||
|
formatNotesList(notesArr)
|
||||||
|
);
|
||||||
|
|
||||||
|
} else if (noteAction === 'add') {
|
||||||
|
const tokens = parseNoteTokens(noteArgsStr);
|
||||||
|
if (tokens.length < 2) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment(
|
||||||
|
'❌ **PocketBase Bot**: `note add` requires `<type>` and `"<text>"`.\n\n' +
|
||||||
|
'**Usage:** `/pocketbase ' + slug + ' note add <type> "<text>"`'
|
||||||
|
);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
const noteType = tokens[0].toLowerCase();
|
||||||
|
const noteText = tokens.slice(1).join(' ');
|
||||||
|
notesArr.push({ type: noteType, text: noteText });
|
||||||
|
await patchNotesJson(notesArr);
|
||||||
|
await addReaction('+1');
|
||||||
|
await postComment(
|
||||||
|
'✅ **PocketBase Bot**: Added note to **`' + slug + '`**\n\n' +
|
||||||
|
'- **Type:** `' + noteType + '`\n' +
|
||||||
|
'- **Text:** ' + noteText + '\n\n' +
|
||||||
|
'*Executed by @' + actor + '*'
|
||||||
|
);
|
||||||
|
|
||||||
|
} else if (noteAction === 'edit') {
|
||||||
|
const tokens = parseNoteTokens(noteArgsStr);
|
||||||
|
if (tokens.length < 3) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment(
|
||||||
|
'❌ **PocketBase Bot**: `note edit` requires `<type>`, `"<old text>"`, and `"<new text>"`.\n\n' +
|
||||||
|
'**Usage:** `/pocketbase ' + slug + ' note edit <type> "<old text>" "<new text>"`\n\n' +
|
||||||
|
'Use `/pocketbase ' + slug + ' note list` to see current notes.'
|
||||||
|
);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
const noteType = tokens[0].toLowerCase();
|
||||||
|
const oldText = tokens[1];
|
||||||
|
const newText = tokens[2];
|
||||||
|
const idx = notesArr.findIndex(function (n) {
|
||||||
|
return n.type.toLowerCase() === noteType && n.text === oldText;
|
||||||
|
});
|
||||||
|
if (idx === -1) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment(
|
||||||
|
'❌ **PocketBase Bot**: No `' + noteType + '` note found with that exact text.\n\n' +
|
||||||
|
'**Current notes for `' + slug + '`:**\n' + formatNotesList(notesArr)
|
||||||
|
);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
notesArr[idx].text = newText;
|
||||||
|
await patchNotesJson(notesArr);
|
||||||
|
await addReaction('+1');
|
||||||
|
await postComment(
|
||||||
|
'✅ **PocketBase Bot**: Edited note in **`' + slug + '`**\n\n' +
|
||||||
|
'- **Type:** `' + noteType + '`\n' +
|
||||||
|
'- **Old:** ' + oldText + '\n' +
|
||||||
|
'- **New:** ' + newText + '\n\n' +
|
||||||
|
'*Executed by @' + actor + '*'
|
||||||
|
);
|
||||||
|
|
||||||
|
} else if (noteAction === 'remove') {
|
||||||
|
const tokens = parseNoteTokens(noteArgsStr);
|
||||||
|
if (tokens.length < 2) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment(
|
||||||
|
'❌ **PocketBase Bot**: `note remove` requires `<type>` and `"<text>"`.\n\n' +
|
||||||
|
'**Usage:** `/pocketbase ' + slug + ' note remove <type> "<text>"`\n\n' +
|
||||||
|
'Use `/pocketbase ' + slug + ' note list` to see current notes.'
|
||||||
|
);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
const noteType = tokens[0].toLowerCase();
|
||||||
|
const noteText = tokens[1];
|
||||||
|
const before = notesArr.length;
|
||||||
|
notesArr = notesArr.filter(function (n) {
|
||||||
|
return !(n.type.toLowerCase() === noteType && n.text === noteText);
|
||||||
|
});
|
||||||
|
if (notesArr.length === before) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment(
|
||||||
|
'❌ **PocketBase Bot**: No `' + noteType + '` note found with that exact text.\n\n' +
|
||||||
|
'**Current notes for `' + slug + '`:**\n' + formatNotesList(notesArr)
|
||||||
|
);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
await patchNotesJson(notesArr);
|
||||||
|
await addReaction('+1');
|
||||||
|
await postComment(
|
||||||
|
'✅ **PocketBase Bot**: Removed note from **`' + slug + '`**\n\n' +
|
||||||
|
'- **Type:** `' + noteType + '`\n' +
|
||||||
|
'- **Text:** ' + noteText + '\n\n' +
|
||||||
|
'*Executed by @' + actor + '*'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (methodMatch) {
|
||||||
|
// ── METHOD SUBCOMMAND (reads/writes install_methods_json on script record) ──
|
||||||
|
const methodArgs = rest.replace(/^method\s*/i, '').trim();
|
||||||
|
const methodListMode = !methodArgs || methodArgs.toLowerCase() === 'list';
|
||||||
|
|
||||||
|
// 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 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 patchInstallMethodsJson(arr) {
|
||||||
|
const res = await request(recordsUrl + '/' + record.id, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ install_methods_json: JSON.stringify(arr) })
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment('❌ **PocketBase Bot**: Failed to update `install_methods_json`:\n```\n' + res.body + '\n```');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (methodListMode) {
|
||||||
|
await addReaction('+1');
|
||||||
|
await postComment(
|
||||||
|
'ℹ️ **PocketBase Bot**: Install methods for **`' + slug + '`** (' + methodsArr.length + ' total)\n\n' +
|
||||||
|
formatMethodsList(methodsArr)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Parse: <type> cpu=N ram=N hdd=N
|
||||||
|
const methodParts = methodArgs.match(/^(\S+)\s+(.+)$/);
|
||||||
|
if (!methodParts) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment(
|
||||||
|
'❌ **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 (multi-line / HTML / special chars via code block) ──
|
||||||
|
const fieldName = setMatch[1].toLowerCase();
|
||||||
|
const SET_ALLOWED = {
|
||||||
|
name: 'string', description: 'string', logo: 'string',
|
||||||
|
documentation: 'string', website: 'string', project_url: 'string', github: 'string',
|
||||||
|
config_path: 'string', disable_message: 'string', deleted_message: 'string'
|
||||||
|
};
|
||||||
|
if (!SET_ALLOWED[fieldName]) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment(
|
||||||
|
'❌ **PocketBase Bot**: `set` only supports text fields.\n\n' +
|
||||||
|
'**Allowed:** `' + Object.keys(SET_ALLOWED).join('`, `') + '`\n\n' +
|
||||||
|
'For boolean/number fields use `field=value` syntax instead.'
|
||||||
|
);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
if (!codeBlockValue) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment(
|
||||||
|
'❌ **PocketBase Bot**: `set` requires a code block with the value.\n\n' +
|
||||||
|
'**Usage:**\n````\n/pocketbase ' + slug + ' set ' + fieldName + '\n```\nYour content here (HTML, multiline, special chars all fine)\n```\n````'
|
||||||
|
);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
const setPayload = {};
|
||||||
|
setPayload[fieldName] = codeBlockValue;
|
||||||
|
const setPatchRes = await request(recordsUrl + '/' + record.id, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(setPayload)
|
||||||
|
});
|
||||||
|
if (!setPatchRes.ok) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment('❌ **PocketBase Bot**: PATCH failed for `' + slug + '`:\n```\n' + setPatchRes.body + '\n```');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
const preview = codeBlockValue.length > 300 ? codeBlockValue.substring(0, 300) + '…' : codeBlockValue;
|
||||||
|
await addReaction('+1');
|
||||||
|
await postComment(
|
||||||
|
'✅ **PocketBase Bot**: Set `' + fieldName + '` for **`' + slug + '`**\n\n' +
|
||||||
|
'**Value set:**\n```\n' + preview + '\n```\n\n' +
|
||||||
|
'*Executed by @' + actor + '*'
|
||||||
|
);
|
||||||
|
|
||||||
|
} 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',
|
||||||
|
logo: 'string',
|
||||||
|
documentation: 'string',
|
||||||
|
website: 'string',
|
||||||
|
project_url: 'string',
|
||||||
|
github: 'string',
|
||||||
|
config_path: 'string',
|
||||||
|
port: 'number',
|
||||||
|
default_user: 'nullable_string',
|
||||||
|
default_passwd: 'nullable_string',
|
||||||
|
updateable: 'boolean',
|
||||||
|
privileged: 'boolean',
|
||||||
|
has_arm: 'boolean',
|
||||||
|
is_dev: 'boolean',
|
||||||
|
is_disabled: 'boolean',
|
||||||
|
disable_message: 'string',
|
||||||
|
is_deleted: 'boolean',
|
||||||
|
deleted_message: 'string',
|
||||||
|
version: 'string',
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment(
|
||||||
|
'❌ **PocketBase Bot**: Unknown field(s): `' + unknownFields.join('`, `') + '`\n\n' +
|
||||||
|
'**Allowed fields:** `' + Object.keys(ALLOWED_FIELDS).join('`, `') + '`'
|
||||||
|
);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(parsedFields).length === 0) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment('❌ **PocketBase Bot**: Could not parse any valid `field=value` pairs.\n\n' + HELP_TEXT);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cast values to correct types
|
||||||
|
const payload = {};
|
||||||
|
for (const [key, rawVal] of Object.entries(parsedFields)) {
|
||||||
|
const type = ALLOWED_FIELDS[key];
|
||||||
|
if (type === 'boolean') {
|
||||||
|
if (rawVal === 'true') payload[key] = true;
|
||||||
|
else if (rawVal === 'false') payload[key] = false;
|
||||||
|
else {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment('❌ **PocketBase Bot**: `' + key + '` must be `true` or `false`, got: `' + rawVal + '`');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
} else if (type === 'number') {
|
||||||
|
const n = parseInt(rawVal, 10);
|
||||||
|
if (isNaN(n)) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment('❌ **PocketBase Bot**: `' + key + '` must be a number, got: `' + rawVal + '`');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
payload[key] = n;
|
||||||
|
} else if (type === 'nullable_string') {
|
||||||
|
payload[key] = rawVal === '' ? null : rawVal;
|
||||||
|
} else {
|
||||||
|
payload[key] = rawVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const patchRes = await request(recordsUrl + '/' + record.id, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
});
|
||||||
|
if (!patchRes.ok) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment('❌ **PocketBase Bot**: PATCH failed for `' + slug + '`:\n```\n' + patchRes.body + '\n```');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
await addReaction('+1');
|
||||||
|
const changesLines = Object.entries(payload)
|
||||||
|
.map(function ([k, v]) { return '- `' + k + '` → `' + JSON.stringify(v) + '`'; })
|
||||||
|
.join('\n');
|
||||||
|
await postComment(
|
||||||
|
'✅ **PocketBase Bot**: Updated **`' + slug + '`** successfully!\n\n' +
|
||||||
|
'**Changes applied:**\n' + changesLines + '\n\n' +
|
||||||
|
'*Executed by @' + actor + '*'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Done.');
|
||||||
|
})().catch(function (e) {
|
||||||
|
console.error('Fatal error:', e.message || e);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
ENDSCRIPT
|
||||||
|
shell: bash
|
||||||
90
.github/workflows/push_json_to_pocketbase.yml
generated
vendored
90
.github/workflows/push_json_to_pocketbase.yml
generated
vendored
@@ -1,10 +1,15 @@
|
|||||||
name: Push JSON changes to PocketBase
|
name: Push JSON changes to PocketBase
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- "json/*.json"
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
script_slug:
|
script_slug:
|
||||||
description: 'Script slug (e.g. my-app)'
|
description: "Script slug (e.g. my-app)"
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
@@ -20,6 +25,9 @@ jobs:
|
|||||||
- name: Get JSON file for script
|
- name: Get JSON file for script
|
||||||
id: changed
|
id: changed
|
||||||
run: |
|
run: |
|
||||||
|
: > changed_app_jsons.txt
|
||||||
|
|
||||||
|
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
||||||
script_slug="${{ github.event.inputs.script_slug }}"
|
script_slug="${{ github.event.inputs.script_slug }}"
|
||||||
file="json/${script_slug}.json"
|
file="json/${script_slug}.json"
|
||||||
if [[ ! -f "$file" ]]; then
|
if [[ ! -f "$file" ]]; then
|
||||||
@@ -34,6 +42,35 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
echo "$file" > changed_app_jsons.txt
|
echo "$file" > changed_app_jsons.txt
|
||||||
echo "count=1" >> "$GITHUB_OUTPUT"
|
echo "count=1" >> "$GITHUB_OUTPUT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
changed=$(git diff --name-only "${{ github.event.before }}" "${{ github.event.after }}" -- json/*.json || true)
|
||||||
|
if [[ -z "$changed" ]]; then
|
||||||
|
echo "No JSON files changed under json/*.json."
|
||||||
|
echo "count=0" >> "$GITHUB_OUTPUT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
count=0
|
||||||
|
for file in $changed; do
|
||||||
|
[[ -f "$file" ]] || continue
|
||||||
|
if [[ "$file" == "json/metadata.json" || "$file" == "json/update-apps.json" || "$file" == "json/versions.json" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if jq -e '.slug' "$file" >/dev/null 2>&1; then
|
||||||
|
echo "$file" >> changed_app_jsons.txt
|
||||||
|
count=$((count + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ $count -eq 0 ]]; then
|
||||||
|
echo "No app JSON files with .slug found in this push."
|
||||||
|
echo "count=0" >> "$GITHUB_OUTPUT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "count=$count" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Push to PocketBase
|
- name: Push to PocketBase
|
||||||
if: steps.changed.outputs.count != '0'
|
if: steps.changed.outputs.count != '0'
|
||||||
@@ -49,7 +86,8 @@ jobs:
|
|||||||
const https = require('https');
|
const https = require('https');
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
const url = require('url');
|
const url = require('url');
|
||||||
function request(fullUrl, opts) {
|
function request(fullUrl, opts, redirectCount) {
|
||||||
|
redirectCount = redirectCount || 0;
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
const u = url.parse(fullUrl);
|
const u = url.parse(fullUrl);
|
||||||
const isHttps = u.protocol === 'https:';
|
const isHttps = u.protocol === 'https:';
|
||||||
@@ -64,6 +102,13 @@ jobs:
|
|||||||
if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
|
if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
|
||||||
const lib = isHttps ? https : http;
|
const lib = isHttps ? https : http;
|
||||||
const req = lib.request(options, function(res) {
|
const req = lib.request(options, function(res) {
|
||||||
|
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||||
|
if (redirectCount >= 5) return reject(new Error('Too many redirects from ' + fullUrl));
|
||||||
|
const redirectUrl = url.resolve(fullUrl, res.headers.location);
|
||||||
|
res.resume();
|
||||||
|
resolve(request(redirectUrl, opts, redirectCount + 1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
let data = '';
|
let data = '';
|
||||||
res.on('data', function(chunk) { data += chunk; });
|
res.on('data', function(chunk) { data += chunk; });
|
||||||
res.on('end', function() {
|
res.on('end', function() {
|
||||||
@@ -161,11 +206,40 @@ jobs:
|
|||||||
if (!fs.existsSync(file)) continue;
|
if (!fs.existsSync(file)) continue;
|
||||||
const data = JSON.parse(fs.readFileSync(file, 'utf8'));
|
const data = JSON.parse(fs.readFileSync(file, 'utf8'));
|
||||||
if (!data.slug) { console.log('Skipping', file, '(no slug)'); continue; }
|
if (!data.slug) { console.log('Skipping', file, '(no slug)'); continue; }
|
||||||
|
// execute_in: map type to canonical value
|
||||||
|
var executeInMap = { ct: 'lxc', lxc: 'lxc', turnkey: 'turnkey', pve: 'pve', addon: 'addon', vm: 'vm' };
|
||||||
|
var executeIn = data.type ? (executeInMap[data.type.toLowerCase()] || data.type.toLowerCase()) : null;
|
||||||
|
// github: extract owner/repo from full GitHub URL
|
||||||
|
var githubField = null;
|
||||||
|
var projectUrl = data.github || null;
|
||||||
|
if (data.github) {
|
||||||
|
var ghMatch = data.github.match(/github\.com\/([^/]+\/[^/?#]+)/);
|
||||||
|
if (ghMatch) githubField = ghMatch[1].replace(/\.git$/, '');
|
||||||
|
}
|
||||||
|
// last_update_commit: last commit touching the actual script files (ct/slug.sh, install/slug-install.sh, vm/slug.sh, etc.)
|
||||||
|
var lastCommit = null;
|
||||||
|
try {
|
||||||
|
var cp = require('child_process');
|
||||||
|
var scriptFiles = [];
|
||||||
|
// primary script from install_methods[].script (e.g. "ct/teleport.sh", "vm/teleport.sh")
|
||||||
|
(data.install_methods || []).forEach(function(im) {
|
||||||
|
if (im.script) scriptFiles.push(im.script);
|
||||||
|
});
|
||||||
|
// derive install script from slug (install/slug-install.sh)
|
||||||
|
scriptFiles.push('install/' + data.slug + '-install.sh');
|
||||||
|
// filter to only files that actually exist in git
|
||||||
|
var existingFiles = scriptFiles.filter(function(f) {
|
||||||
|
try { cp.execSync('git ls-files --error-unmatch ' + f, { stdio: 'ignore' }); return true; } catch(e) { return false; }
|
||||||
|
});
|
||||||
|
if (existingFiles.length > 0) {
|
||||||
|
lastCommit = cp.execSync('git log -1 --format=%H -- ' + existingFiles.join(' ')).toString().trim() || null;
|
||||||
|
}
|
||||||
|
} catch(e) { console.warn('Could not get last commit:', e.message); }
|
||||||
var payload = {
|
var payload = {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
slug: data.slug,
|
slug: data.slug,
|
||||||
script_created: data.date_created || data.script_created,
|
script_created: data.date_created || data.script_created,
|
||||||
script_updated: data.date_created || data.script_updated,
|
script_updated: new Date().toISOString().split('T')[0],
|
||||||
updateable: data.updateable,
|
updateable: data.updateable,
|
||||||
privileged: data.privileged,
|
privileged: data.privileged,
|
||||||
port: data.interface_port != null ? data.interface_port : data.port,
|
port: data.interface_port != null ? data.interface_port : data.port,
|
||||||
@@ -174,10 +248,16 @@ jobs:
|
|||||||
logo: data.logo,
|
logo: data.logo,
|
||||||
description: data.description,
|
description: data.description,
|
||||||
config_path: data.config_path,
|
config_path: data.config_path,
|
||||||
default_user: (data.default_credentials && data.default_credentials.username) || data.default_user,
|
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,
|
default_passwd: (data.default_credentials && data.default_credentials.password) || data.default_passwd || null,
|
||||||
|
notes_json: JSON.stringify(data.notes || []),
|
||||||
|
install_methods_json: JSON.stringify(data.install_methods || []),
|
||||||
is_dev: true
|
is_dev: true
|
||||||
};
|
};
|
||||||
|
if (executeIn) payload.execute_in = executeIn;
|
||||||
|
if (githubField) payload.github = githubField;
|
||||||
|
if (projectUrl) payload.project_url = projectUrl;
|
||||||
|
if (lastCommit) payload.last_update_commit = lastCommit;
|
||||||
var resolvedType = typeValueToId[data.type];
|
var resolvedType = typeValueToId[data.type];
|
||||||
if (resolvedType == null && data.type === 'ct') resolvedType = typeValueToId['lxc'];
|
if (resolvedType == null && data.type === 'ct') resolvedType = typeValueToId['lxc'];
|
||||||
if (resolvedType) payload.type = resolvedType;
|
if (resolvedType) payload.type = resolvedType;
|
||||||
|
|||||||
61
.github/workflows/stale_pr_close.yml
generated
vendored
61
.github/workflows/stale_pr_close.yml
generated
vendored
@@ -38,7 +38,7 @@ jobs:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Scheduled run: check all stale PRs ---
|
// --- Scheduled run: fetch all open PRs ---
|
||||||
const { data: prs } = await github.rest.pulls.list({
|
const { data: prs } = await github.rest.pulls.list({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
@@ -47,8 +47,63 @@ jobs:
|
|||||||
});
|
});
|
||||||
|
|
||||||
for (const pr of prs) {
|
for (const pr of prs) {
|
||||||
const hasStale = pr.labels.some(l => l.name === "stale");
|
const labels = pr.labels.map(l => l.name);
|
||||||
if (!hasStale) continue;
|
const hasStale = labels.includes("stale");
|
||||||
|
const hasKeepOpen = labels.includes("keep-open");
|
||||||
|
|
||||||
|
// -------------------------------------------------------
|
||||||
|
// NEW: Auto-label PRs with no activity in the last 14 days
|
||||||
|
// -------------------------------------------------------
|
||||||
|
if (!hasStale && !hasKeepOpen) {
|
||||||
|
// Find the most recent commit date
|
||||||
|
const { data: commits } = await github.rest.pulls.listCommits({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
pull_number: pr.number
|
||||||
|
});
|
||||||
|
const lastCommitDate = commits.length > 0
|
||||||
|
? new Date(commits[commits.length - 1].commit.author.date)
|
||||||
|
: new Date(pr.created_at);
|
||||||
|
|
||||||
|
// Find the most recent non-bot comment date
|
||||||
|
const { data: comments } = await github.rest.issues.listComments({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issue_number: pr.number,
|
||||||
|
per_page: 100
|
||||||
|
});
|
||||||
|
const humanComments = comments.filter(c => c.user?.type !== "Bot");
|
||||||
|
const lastCommentDate = humanComments.length > 0
|
||||||
|
? new Date(humanComments[humanComments.length - 1].created_at)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// Most recent activity across commits and comments
|
||||||
|
const lastActivityDate = lastCommentDate && lastCommentDate > lastCommitDate
|
||||||
|
? lastCommentDate
|
||||||
|
: lastCommitDate;
|
||||||
|
|
||||||
|
const daysSinceActivity = (now - lastActivityDate) / (1000 * 60 * 60 * 24);
|
||||||
|
|
||||||
|
if (daysSinceActivity > 14) {
|
||||||
|
await github.rest.issues.addLabels({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issue_number: pr.number,
|
||||||
|
labels: ["stale"]
|
||||||
|
});
|
||||||
|
// The pull_request_target labeled event will fire the comment automatically.
|
||||||
|
// Skip further processing for this PR in this run.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not stale, nothing else to do for this PR.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------
|
||||||
|
// EXISTING: Manage already-stale PRs
|
||||||
|
// -------------------------------------------------------
|
||||||
|
if (!hasStale) continue; // has keep-open but not stale — skip
|
||||||
|
|
||||||
// Get timeline events to find when stale label was added
|
// Get timeline events to find when stale label was added
|
||||||
const { data: events } = await github.rest.issues.listEvents({
|
const { data: events } = await github.rest.issues.listEvents({
|
||||||
|
|||||||
10
.github/workflows/update-timestamp-on-db.yml
generated
vendored
10
.github/workflows/update-timestamp-on-db.yml
generated
vendored
@@ -83,7 +83,8 @@ jobs:
|
|||||||
const http = require('http');
|
const http = require('http');
|
||||||
const url = require('url');
|
const url = require('url');
|
||||||
|
|
||||||
function request(fullUrl, opts) {
|
function request(fullUrl, opts, redirectCount) {
|
||||||
|
redirectCount = redirectCount || 0;
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
const u = url.parse(fullUrl);
|
const u = url.parse(fullUrl);
|
||||||
const isHttps = u.protocol === 'https:';
|
const isHttps = u.protocol === 'https:';
|
||||||
@@ -98,6 +99,13 @@ jobs:
|
|||||||
if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
|
if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
|
||||||
const lib = isHttps ? https : http;
|
const lib = isHttps ? https : http;
|
||||||
const req = lib.request(options, function(res) {
|
const req = lib.request(options, function(res) {
|
||||||
|
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||||
|
if (redirectCount >= 5) return reject(new Error('Too many redirects from ' + fullUrl));
|
||||||
|
const redirectUrl = url.resolve(fullUrl, res.headers.location);
|
||||||
|
res.resume();
|
||||||
|
resolve(request(redirectUrl, opts, redirectCount + 1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
let data = '';
|
let data = '';
|
||||||
res.on('data', function(chunk) { data += chunk; });
|
res.on('data', function(chunk) { data += chunk; });
|
||||||
res.on('end', function() {
|
res.on('end', function() {
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: cobalt (cobaltgit)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
|
||||||
# Source: https://ntfy.sh/
|
|
||||||
|
|
||||||
APP="Alpine-ntfy"
|
|
||||||
var_tags="${var_tags:-notification}"
|
|
||||||
var_cpu="${var_cpu:-1}"
|
|
||||||
var_ram="${var_ram:-256}"
|
|
||||||
var_disk="${var_disk:-2}"
|
|
||||||
var_os="${var_os:-alpine}"
|
|
||||||
var_version="${var_version:-3.22}"
|
|
||||||
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/ntfy ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
msg_info "Updating ntfy LXC"
|
|
||||||
$STD apk -U upgrade
|
|
||||||
setcap 'cap_net_bind_service=+ep' /usr/bin/ntfy
|
|
||||||
msg_ok "Updated ntfy LXC"
|
|
||||||
|
|
||||||
msg_info "Restarting ntfy"
|
|
||||||
rc-service ntfy restart
|
|
||||||
msg_ok "Restarted ntfy"
|
|
||||||
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}${CL}"
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: Slaviša Arežina (tremor021)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
|
||||||
# Source: https://wakapi.dev/ | https://github.com/muety/wakapi
|
|
||||||
|
|
||||||
APP="Alpine-Wakapi"
|
|
||||||
var_tags="${var_tags:-code;time-tracking}"
|
|
||||||
var_cpu="${var_cpu:-1}"
|
|
||||||
var_ram="${var_ram:-512}"
|
|
||||||
var_disk="${var_disk:-4}"
|
|
||||||
var_os="${var_os:-alpine}"
|
|
||||||
var_version="${var_version:-3.23}"
|
|
||||||
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/wakapi ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
RELEASE=$(curl -s https://api.github.com/repos/muety/wakapi/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
|
|
||||||
if [ "${RELEASE}" != "$(cat ~/.wakapi 2>/dev/null)" ] || [ ! -f ~/.wakapi ]; then
|
|
||||||
msg_info "Stopping Wakapi Service"
|
|
||||||
$STD rc-service wakapi stop
|
|
||||||
msg_ok "Stopped Wakapi Service"
|
|
||||||
|
|
||||||
msg_info "Updating Wakapi LXC"
|
|
||||||
$STD apk -U upgrade
|
|
||||||
msg_ok "Updated Wakapi LXC"
|
|
||||||
|
|
||||||
msg_info "Creating backup"
|
|
||||||
mkdir -p /opt/wakapi-backup
|
|
||||||
cp /opt/wakapi/config.yml /opt/wakapi/wakapi_db.db /opt/wakapi-backup/
|
|
||||||
msg_ok "Created backup"
|
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "wakapi" "muety/wakapi" "tarball"
|
|
||||||
|
|
||||||
msg_info "Configuring Wakapi"
|
|
||||||
cd /opt/wakapi
|
|
||||||
$STD go mod download
|
|
||||||
$STD go build -o wakapi
|
|
||||||
cp /opt/wakapi-backup/config.yml /opt/wakapi/
|
|
||||||
cp /opt/wakapi-backup/wakapi_db.db /opt/wakapi/
|
|
||||||
rm -rf /opt/wakapi-backup
|
|
||||||
msg_ok "Configured Wakapi"
|
|
||||||
|
|
||||||
msg_info "Starting Service"
|
|
||||||
$STD rc-service wakapi start
|
|
||||||
msg_ok "Started Service"
|
|
||||||
msg_ok "Updated successfully"
|
|
||||||
else
|
|
||||||
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
|
||||||
fi
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
|
|
||||||
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}"
|
|
||||||
@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 tteck
|
# Copyright (c) 2021-2026 tteck
|
||||||
# Author: tteck (tteckster) | Co-Author: MickLesk (Canbiz) | Co-Author: CrazyWolf13
|
# Author: tteck (tteckster) | Co-Author: MickLesk (Canbiz) | Co-Author: CrazyWolf13
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://homarr.dev/
|
# Source: https://homarr.dev/
|
||||||
|
|
||||||
APP="alpine-homarr"
|
APP="alpine-homarr"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: MickLesk (Canbiz)
|
# Author: MickLesk (Canbiz)
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://github.com/community-scripts/ProxmoxVE
|
# Source: https://github.com/community-scripts/ProxmoxVE
|
||||||
|
|
||||||
APP="Docspell"
|
APP="Docspell"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: Nícolas Pastorello (opastorello)
|
# Author: Nícolas Pastorello (opastorello)
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://github.com/jumpserver/jumpserver
|
# Source: https://github.com/jumpserver/jumpserver
|
||||||
|
|
||||||
APP="JumpServer"
|
APP="JumpServer"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
||||||
# Copyright (c) 2021-2026 tteck
|
# Copyright (c) 2021-2026 tteck
|
||||||
# Author: tteck (tteckster)
|
# Author: tteck (tteckster)
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://petio.tv/
|
# Source: https://petio.tv/
|
||||||
|
|
||||||
APP="Petio"
|
APP="Petio"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 tteck
|
# Copyright (c) 2021-2026 tteck
|
||||||
# Author: tteck (tteckster)
|
# Author: tteck (tteckster)
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://nginxproxymanager.com/
|
# Source: https://nginxproxymanager.com/
|
||||||
|
|
||||||
APP="Nginx Proxy Manager"
|
APP="Nginx Proxy Manager"
|
||||||
|
|||||||
2
ct/deferred/opencloud.json
generated
2
ct/deferred/opencloud.json
generated
@@ -53,7 +53,7 @@
|
|||||||
"type": "info"
|
"type": "info"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "**Optional Full-text Search with Apache Tika**: requires your own Tika LXC. See `https://community-scripts.github.io/ProxmoxVE/scripts?id=apache-tika`",
|
"text": "**Optional Full-text Search with Apache Tika**: requires your own Tika LXC. See `https://community-scripts.github.io/ProxmoxVED/scripts?id=apache-tika`",
|
||||||
"type": "info"
|
"type": "info"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: MickLesk (CanbiZ)
|
# Author: MickLesk (CanbiZ)
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source:
|
# Source:
|
||||||
|
|
||||||
APP="Roundcubemail"
|
APP="Roundcubemail"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: MickLesk (Canbiz)
|
# Author: MickLesk (Canbiz)
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source:
|
# Source:
|
||||||
|
|
||||||
APP="Squirrel Servers Manager"
|
APP="Squirrel Servers Manager"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: SunFlowerOwl
|
# Author: SunFlowerOwl
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://github.com/haugene/docker-transmission-openvpn
|
# Source: https://github.com/haugene/docker-transmission-openvpn
|
||||||
|
|
||||||
APP="transmission-openvpn"
|
APP="transmission-openvpn"
|
||||||
|
|||||||
73
ct/degoog.sh
Normal file
73
ct/degoog.sh
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
|
# Author: vhsdream
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
|
# Source: https://github.com/fccview/degoog
|
||||||
|
|
||||||
|
APP="degoog"
|
||||||
|
var_tags="${var_tags:-search;privacy;plugins}"
|
||||||
|
var_cpu="${var_cpu:-2}"
|
||||||
|
var_ram="${var_ram:-2048}"
|
||||||
|
var_disk="${var_disk:-6}"
|
||||||
|
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/degoog ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if check_for_gh_release "degoog" "fccview/degoog"; then
|
||||||
|
msg_info "Stopping Service"
|
||||||
|
systemctl stop degoog
|
||||||
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
|
msg_info "Backing up Configuration & Data"
|
||||||
|
[[ -f /opt/degoog/.env ]] && cp /opt/degoog/.env /opt/degoog.env.bak
|
||||||
|
[[ -d /opt/degoog/data ]] && mv /opt/degoog/data /opt/degoog_data_backup
|
||||||
|
msg_ok "Backed up Configuration & Data"
|
||||||
|
|
||||||
|
if ! command -v bun >/dev/null 2>&1; then
|
||||||
|
msg_info "Installing Bun"
|
||||||
|
export BUN_INSTALL="/root/.bun"
|
||||||
|
curl -fsSL https://bun.sh/install | $STD bash
|
||||||
|
ln -sf /root/.bun/bin/bun /usr/local/bin/bun
|
||||||
|
ln -sf /root/.bun/bin/bunx /usr/local/bin/bunx
|
||||||
|
msg_ok "Installed Bun"
|
||||||
|
fi
|
||||||
|
|
||||||
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "degoog" "fccview/degoog" "prebuild" "latest" "/opt/degoog" "degoog_*_prebuild.tar.gz"
|
||||||
|
|
||||||
|
msg_info "Restoring Configuration & Data"
|
||||||
|
[[ -f /opt/degoog.env.bak ]] && mv /opt/degoog.env.bak /opt/degoog/.env
|
||||||
|
[[ -d /opt/degoog_data_backup ]] && mv /opt/degoog_data_backup /opt/degoog/data
|
||||||
|
msg_ok "Restored Configuration & Data"
|
||||||
|
|
||||||
|
msg_info "Starting Service"
|
||||||
|
systemctl start degoog
|
||||||
|
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}:4444${CL}"
|
||||||
@@ -73,5 +73,5 @@ msg_ok "Completed Successfully!\n"
|
|||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
|
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
|
||||||
echo -e "${INFO}${YW} Admin Setup:${CL}"
|
echo -e "${INFO}${YW} Credentials saved in:${CL}"
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}Create the first account in the web UI (use admin@local to match developer emails)${CL}"
|
echo -e "${TAB}/root/discourse.creds"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: Simon Friedrich
|
# Author: Simon Friedrich
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://forgejo.org/
|
# Source: https://forgejo.org/
|
||||||
|
|
||||||
APP="Forgejo-Runner"
|
APP="Forgejo-Runner"
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: Matthew Stern (sternma) | MickLesk (CanbiZ)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/dmunozv04/iSponsorBlockTV
|
|
||||||
|
|
||||||
APP="iSponsorBlockTV"
|
|
||||||
var_tags="${var_tags:-media;automation}"
|
|
||||||
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 /opt/isponsorblocktv ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if check_for_gh_release "isponsorblocktv" "dmunozv04/iSponsorBlockTV"; then
|
|
||||||
msg_info "Stopping Service"
|
|
||||||
systemctl stop isponsorblocktv
|
|
||||||
msg_ok "Stopped Service"
|
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "isponsorblocktv" "dmunozv04/iSponsorBlockTV" "singlefile" "latest" "/opt/isponsorblocktv" "iSponsorBlockTV-*-linux"
|
|
||||||
|
|
||||||
msg_info "Starting Service"
|
|
||||||
systemctl start isponsorblocktv
|
|
||||||
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} Run the setup wizard inside the container with:${CL}"
|
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}iSponsorBlockTV setup${CL}"
|
|
||||||
101
ct/librechat.sh
Normal file
101
ct/librechat.sh
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
|
# Author: MickLesk (CanbiZ)
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
|
# Source: https://github.com/danny-avila/LibreChat
|
||||||
|
|
||||||
|
APP="LibreChat"
|
||||||
|
var_tags="${var_tags:-ai;chat}"
|
||||||
|
var_cpu="${var_cpu:-4}"
|
||||||
|
var_ram="${var_ram:-6144}"
|
||||||
|
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 [[ ! -d /opt/librechat ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if check_for_gh_tag "librechat" "danny-avila/LibreChat" "v"; then
|
||||||
|
msg_info "Stopping Services"
|
||||||
|
systemctl stop librechat rag-api
|
||||||
|
msg_ok "Stopped Services"
|
||||||
|
|
||||||
|
msg_info "Backing up Configuration"
|
||||||
|
cp /opt/librechat/.env /opt/librechat.env.bak
|
||||||
|
msg_ok "Backed up Configuration"
|
||||||
|
|
||||||
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_tag "librechat" "danny-avila/LibreChat"
|
||||||
|
|
||||||
|
msg_info "Installing Dependencies"
|
||||||
|
cd /opt/librechat
|
||||||
|
$STD npm ci
|
||||||
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
|
msg_info "Building Frontend"
|
||||||
|
$STD npm run frontend
|
||||||
|
$STD npm prune --production
|
||||||
|
$STD npm cache clean --force
|
||||||
|
msg_ok "Built Frontend"
|
||||||
|
|
||||||
|
msg_info "Restoring Configuration"
|
||||||
|
cp /opt/librechat.env.bak /opt/librechat/.env
|
||||||
|
rm -f /opt/librechat.env.bak
|
||||||
|
msg_ok "Restored Configuration"
|
||||||
|
|
||||||
|
msg_info "Starting Services"
|
||||||
|
systemctl start rag-api librechat
|
||||||
|
msg_ok "Started Services"
|
||||||
|
msg_ok "Updated LibreChat Successfully!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if check_for_gh_release "rag-api" "danny-avila/rag_api"; then
|
||||||
|
msg_info "Stopping RAG API"
|
||||||
|
systemctl stop rag-api
|
||||||
|
msg_ok "Stopped RAG API"
|
||||||
|
|
||||||
|
msg_info "Backing up RAG API Configuration"
|
||||||
|
cp /opt/rag-api/.env /opt/rag-api.env.bak
|
||||||
|
msg_ok "Backed up RAG API Configuration"
|
||||||
|
|
||||||
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "rag-api" "danny-avila/rag_api" "tarball"
|
||||||
|
|
||||||
|
msg_info "Updating RAG API Dependencies"
|
||||||
|
cd /opt/rag-api
|
||||||
|
$STD .venv/bin/pip install -r requirements.lite.txt
|
||||||
|
msg_ok "Updated RAG API Dependencies"
|
||||||
|
|
||||||
|
msg_info "Restoring RAG API Configuration"
|
||||||
|
cp /opt/rag-api.env.bak /opt/rag-api/.env
|
||||||
|
rm -f /opt/rag-api.env.bak
|
||||||
|
msg_ok "Restored RAG API Configuration"
|
||||||
|
|
||||||
|
msg_info "Starting RAG API"
|
||||||
|
systemctl start rag-api
|
||||||
|
msg_ok "Started RAG API"
|
||||||
|
msg_ok "Updated RAG API 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}:3080${CL}"
|
||||||
@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
|
|
||||||
# Copyright (c) 2021-2025 minthcm
|
# Copyright (c) 2021-2025 minthcm
|
||||||
# Author: MintHCM
|
# Author: MintHCM
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://github.com/minthcm/minthcm
|
# Source: https://github.com/minthcm/minthcm
|
||||||
|
|
||||||
APP="MintHCM"
|
APP="MintHCM"
|
||||||
|
|||||||
87
ct/netboot-xyz.sh
Normal file
87
ct/netboot-xyz.sh
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
|
# Author: Michel Roegl-Brunner (michelroegl-brunner)
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
|
# Source: https://netboot.xyz
|
||||||
|
|
||||||
|
APP="netboot.xyz"
|
||||||
|
var_tags="${var_tags:-network;pxe;boot}"
|
||||||
|
var_cpu="${var_cpu:-1}"
|
||||||
|
var_ram="${var_ram:-512}"
|
||||||
|
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 [[ ! -f ~/.netboot-xyz ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if check_for_gh_release "netboot-xyz" "netbootxyz/netboot.xyz"; then
|
||||||
|
msg_info "Backing up Configuration"
|
||||||
|
cp /var/www/html/boot.cfg /opt/netboot-xyz-boot.cfg.bak
|
||||||
|
msg_ok "Backed up Configuration"
|
||||||
|
|
||||||
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "netboot-xyz" "netbootxyz/netboot.xyz" "prebuild" "latest" "/var/www/html" "menus.tar.gz"
|
||||||
|
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-efi" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-efi-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.efi.dsk"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-snp" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-snp.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-snp-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-snp.efi.dsk"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-snponly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-snponly.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal.efi.dsk"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-snp" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-snp.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-snp-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-snp.efi.dsk"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-snponly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-snponly.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-kpxe" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.kpxe"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-undionly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-undionly.kpxe"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-kpxe" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal.kpxe"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-lkrn" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.lkrn"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-linux-bin" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-linux.bin"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.dsk"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-pdsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.pdsk"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64-snp" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64-snp.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64-snponly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64-snponly.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-arm64" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-arm64.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-arm64-snp" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-arm64-snp.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-arm64-snponly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-arm64-snponly.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-iso" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.iso"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-img" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.img"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64-iso" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64.iso"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64-img" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64.img"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-multiarch-iso" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-multiarch.iso"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-multiarch-img" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-multiarch.img"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-checksums" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-sha256-checksums.txt"
|
||||||
|
|
||||||
|
msg_info "Restoring Configuration"
|
||||||
|
cp /opt/netboot-xyz-boot.cfg.bak /var/www/html/boot.cfg
|
||||||
|
rm -f /opt/netboot-xyz-boot.cfg.bak
|
||||||
|
msg_ok "Restored Configuration"
|
||||||
|
|
||||||
|
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}"
|
||||||
225
ct/nginxproxymanager.sh
Normal file
225
ct/nginxproxymanager.sh
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
|
# Author: tteck (tteckster) | Co-Author: CrazyWolf13
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://nginxproxymanager.com/ | Github: https://github.com/NginxProxyManager/nginx-proxy-manager
|
||||||
|
|
||||||
|
APP="Nginx Proxy Manager"
|
||||||
|
var_tags="${var_tags:-proxy}"
|
||||||
|
var_cpu="${var_cpu:-2}"
|
||||||
|
var_ram="${var_ram:-2048}"
|
||||||
|
var_disk="${var_disk:-8}"
|
||||||
|
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 [[ ! -f /lib/systemd/system/npm.service ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $(grep -E '^VERSION_ID=' /etc/os-release) == *"12"* ]]; then
|
||||||
|
msg_error "Wrong Debian version detected!"
|
||||||
|
msg_error "Please create a snapshot first. You must upgrade your LXC to Debian Trixie before updating. Visit: https://github.com/community-scripts/ProxmoxVE/discussions/7489"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v node &>/dev/null; then
|
||||||
|
CURRENT_NODE_VERSION=$(node --version | cut -d'v' -f2 | cut -d'.' -f1)
|
||||||
|
if [[ "$CURRENT_NODE_VERSION" != "22" ]]; then
|
||||||
|
systemctl stop openresty
|
||||||
|
$STD apt purge -y nodejs npm
|
||||||
|
$STD apt autoremove -y
|
||||||
|
rm -rf /usr/local/bin/node /usr/local/bin/npm
|
||||||
|
rm -rf /usr/local/lib/node_modules
|
||||||
|
rm -rf ~/.npm
|
||||||
|
rm -rf /root/.npm
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
|
||||||
|
|
||||||
|
RELEASE=$(get_latest_github_release "NginxProxyManager/nginx-proxy-manager")
|
||||||
|
|
||||||
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "nginxproxymanager" "NginxProxyManager/nginx-proxy-manager" "tarball" "v${RELEASE}" "/opt/nginxproxymanager"
|
||||||
|
|
||||||
|
msg_info "Stopping Services"
|
||||||
|
systemctl stop openresty
|
||||||
|
systemctl stop npm
|
||||||
|
msg_ok "Stopped Services"
|
||||||
|
|
||||||
|
msg_info "Cleaning old files"
|
||||||
|
$STD rm -rf /app \
|
||||||
|
/var/www/html \
|
||||||
|
/etc/nginx \
|
||||||
|
/var/log/nginx \
|
||||||
|
/var/lib/nginx \
|
||||||
|
/var/cache/nginx
|
||||||
|
msg_ok "Cleaned old files"
|
||||||
|
|
||||||
|
msg_info "Migrating to OpenResty from source"
|
||||||
|
rm -f /etc/apt/trusted.gpg.d/openresty-archive-keyring.gpg /etc/apt/trusted.gpg.d/openresty.gpg
|
||||||
|
rm -f /etc/apt/sources.list.d/openresty.list /etc/apt/sources.list.d/openresty.sources
|
||||||
|
if dpkg -l openresty &>/dev/null; then
|
||||||
|
$STD apt remove -y openresty
|
||||||
|
$STD apt autoremove -y
|
||||||
|
fi
|
||||||
|
$STD apt install -y build-essential libpcre3-dev libssl-dev zlib1g-dev
|
||||||
|
msg_ok "Migrated to OpenResty from source"
|
||||||
|
|
||||||
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "openresty" "openresty/openresty" "prebuild" "latest" "/opt/openresty" "openresty-*.tar.gz"
|
||||||
|
|
||||||
|
msg_info "Building OpenResty"
|
||||||
|
cd /opt/openresty
|
||||||
|
$STD ./configure \
|
||||||
|
--with-http_v2_module \
|
||||||
|
--with-http_realip_module \
|
||||||
|
--with-http_stub_status_module \
|
||||||
|
--with-http_ssl_module \
|
||||||
|
--with-http_sub_module \
|
||||||
|
--with-http_auth_request_module \
|
||||||
|
--with-pcre-jit \
|
||||||
|
--with-stream \
|
||||||
|
--with-stream_ssl_module
|
||||||
|
$STD make -j"$(nproc)"
|
||||||
|
$STD make install
|
||||||
|
rm -rf /opt/openresty
|
||||||
|
cat <<'EOF' >/lib/systemd/system/openresty.service
|
||||||
|
[Unit]
|
||||||
|
Description=The OpenResty Application Platform
|
||||||
|
After=syslog.target network-online.target remote-fs.target nss-lookup.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStartPre=/usr/local/openresty/nginx/sbin/nginx -t
|
||||||
|
ExecStart=/usr/local/openresty/nginx/sbin/nginx -g 'daemon off;'
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl daemon-reload
|
||||||
|
msg_ok "Built OpenResty"
|
||||||
|
|
||||||
|
msg_info "Setting up Environment"
|
||||||
|
ln -sf /usr/bin/python3 /usr/bin/python
|
||||||
|
ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx
|
||||||
|
ln -sf /usr/local/openresty/nginx/ /etc/nginx
|
||||||
|
sed -i "0,/\"version\": \"[^\"]*\"/s|\"version\": \"[^\"]*\"|\"version\": \"$RELEASE\"|" /opt/nginxproxymanager/backend/package.json
|
||||||
|
sed -i "0,/\"version\": \"[^\"]*\"/s|\"version\": \"[^\"]*\"|\"version\": \"$RELEASE\"|" /opt/nginxproxymanager/frontend/package.json
|
||||||
|
sed -i 's+^daemon+#daemon+g' /opt/nginxproxymanager/docker/rootfs/etc/nginx/nginx.conf
|
||||||
|
NGINX_CONFS=$(find /opt/nginxproxymanager -type f -name "*.conf")
|
||||||
|
for NGINX_CONF in $NGINX_CONFS; do
|
||||||
|
sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF"
|
||||||
|
done
|
||||||
|
|
||||||
|
mkdir -p /var/www/html /etc/nginx/logs
|
||||||
|
cp -r /opt/nginxproxymanager/docker/rootfs/var/www/html/* /var/www/html/
|
||||||
|
cp -r /opt/nginxproxymanager/docker/rootfs/etc/nginx/* /etc/nginx/
|
||||||
|
cp /opt/nginxproxymanager/docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini
|
||||||
|
cp /opt/nginxproxymanager/docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager
|
||||||
|
ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf
|
||||||
|
rm -f /etc/nginx/conf.d/dev.conf
|
||||||
|
|
||||||
|
mkdir -p /tmp/nginx/body \
|
||||||
|
/run/nginx \
|
||||||
|
/data/nginx \
|
||||||
|
/data/custom_ssl \
|
||||||
|
/data/logs \
|
||||||
|
/data/access \
|
||||||
|
/data/nginx/default_host \
|
||||||
|
/data/nginx/default_www \
|
||||||
|
/data/nginx/proxy_host \
|
||||||
|
/data/nginx/redirection_host \
|
||||||
|
/data/nginx/stream \
|
||||||
|
/data/nginx/dead_host \
|
||||||
|
/data/nginx/temp \
|
||||||
|
/var/lib/nginx/cache/public \
|
||||||
|
/var/lib/nginx/cache/private \
|
||||||
|
/var/cache/nginx/proxy_temp
|
||||||
|
|
||||||
|
chmod -R 777 /var/cache/nginx
|
||||||
|
chown root /tmp/nginx
|
||||||
|
|
||||||
|
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf
|
||||||
|
|
||||||
|
if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then
|
||||||
|
$STD openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p /app/frontend/images
|
||||||
|
cp -r /opt/nginxproxymanager/backend/* /app
|
||||||
|
msg_ok "Set up Environment"
|
||||||
|
|
||||||
|
msg_info "Building Frontend"
|
||||||
|
export NODE_OPTIONS="--max_old_space_size=2048 --openssl-legacy-provider"
|
||||||
|
cd /opt/nginxproxymanager/frontend
|
||||||
|
# Replace node-sass with sass in package.json before installation
|
||||||
|
sed -E -i 's/"node-sass" *: *"([^"]*)"/"sass": "\1"/g' package.json
|
||||||
|
$STD yarn install --network-timeout 600000
|
||||||
|
$STD yarn locale-compile
|
||||||
|
$STD yarn build
|
||||||
|
cp -r /opt/nginxproxymanager/frontend/dist/* /app/frontend
|
||||||
|
cp -r /opt/nginxproxymanager/frontend/public/images/* /app/frontend/images
|
||||||
|
msg_ok "Built Frontend"
|
||||||
|
|
||||||
|
msg_info "Initializing Backend"
|
||||||
|
rm -rf /app/config/default.json
|
||||||
|
if [ ! -f /app/config/production.json ]; then
|
||||||
|
cat <<'EOF' >/app/config/production.json
|
||||||
|
{
|
||||||
|
"database": {
|
||||||
|
"engine": "knex-native",
|
||||||
|
"knex": {
|
||||||
|
"client": "better-sqlite3",
|
||||||
|
"connection": {
|
||||||
|
"filename": "/data/database.sqlite"
|
||||||
|
},
|
||||||
|
"useNullAsDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
sed -i 's/"client": "sqlite3"/"client": "better-sqlite3"/' /app/config/production.json
|
||||||
|
cd /app
|
||||||
|
$STD yarn install --network-timeout 600000
|
||||||
|
msg_ok "Initialized Backend"
|
||||||
|
|
||||||
|
msg_info "Updating Certbot"
|
||||||
|
if [ -d /opt/certbot ]; then
|
||||||
|
$STD /opt/certbot/bin/pip install --upgrade pip setuptools wheel
|
||||||
|
$STD /opt/certbot/bin/pip install --upgrade certbot certbot-dns-cloudflare
|
||||||
|
fi
|
||||||
|
msg_ok "Updated Certbot"
|
||||||
|
|
||||||
|
msg_info "Starting Services"
|
||||||
|
sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf
|
||||||
|
sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/g;' /etc/logrotate.d/nginx-proxy-manager
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable -q --now openresty
|
||||||
|
systemctl enable -q --now npm
|
||||||
|
msg_ok "Started Services"
|
||||||
|
|
||||||
|
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}:81${CL}"
|
||||||
@@ -53,7 +53,7 @@ function update_script() {
|
|||||||
msg_info "Running Database Migrations"
|
msg_info "Running Database Migrations"
|
||||||
cd /opt/simplelogin
|
cd /opt/simplelogin
|
||||||
cp /opt/simplelogin_env.bak /opt/simplelogin/.env
|
cp /opt/simplelogin_env.bak /opt/simplelogin/.env
|
||||||
$STD .venv/bin/flask db upgrade
|
$STD .venv/bin/alembic upgrade head
|
||||||
msg_ok "Ran Database Migrations"
|
msg_ok "Ran Database Migrations"
|
||||||
|
|
||||||
msg_info "Restoring Data"
|
msg_info "Restoring Data"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
|
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
# Author: KernelSailor
|
# Author: KernelSailor
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://snowflake.torproject.org/
|
# Source: https://snowflake.torproject.org/
|
||||||
|
|
||||||
APP="tor-snowflake"
|
APP="tor-snowflake"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
APP="Twenty"
|
APP="Twenty"
|
||||||
var_tags="${var_tags:-crm;business;contacts}"
|
var_tags="${var_tags:-crm;business;contacts}"
|
||||||
var_cpu="${var_cpu:-4}"
|
var_cpu="${var_cpu:-4}"
|
||||||
var_ram="${var_ram:-8192}"
|
var_ram="${var_ram:-10240}"
|
||||||
var_disk="${var_disk:-20}"
|
var_disk="${var_disk:-20}"
|
||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: MickLesk (CanbiZ)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/versity/versitygw
|
|
||||||
|
|
||||||
APP="VersityGW"
|
|
||||||
var_tags="${var_tags:-s3;storage;gateway}"
|
|
||||||
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 [[ ! -f /usr/bin/versitygw ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if check_for_gh_release "versitygw" "versity/versitygw"; then
|
|
||||||
msg_info "Stopping Service"
|
|
||||||
systemctl stop versitygw@gateway
|
|
||||||
msg_ok "Stopped Service"
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "versitygw" "versity/versitygw" "binary"
|
|
||||||
|
|
||||||
msg_info "Starting Service"
|
|
||||||
systemctl start versitygw@gateway
|
|
||||||
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}:7070${CL}"
|
|
||||||
@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: dave-yap (dave-yap) | Co-author: remz1337
|
# Author: dave-yap (dave-yap) | Co-author: remz1337
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://zitadel.com/
|
# Source: https://zitadel.com/
|
||||||
|
|
||||||
APP="Zitadel"
|
APP="Zitadel"
|
||||||
|
|||||||
@@ -1,106 +1,142 @@
|
|||||||
|
|
||||||
# Community Scripts Contribution Guide
|
# Community Scripts Contribution Guide
|
||||||
|
|
||||||
## **Welcome to the communty-scripts Repository!**
|
## Welcome to the community-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.
|
These documents outline the coding standards and contribution flow for the ProxmoxVED repository.
|
||||||
|
|
||||||
### Why Coding Standards Matter
|
The important reality check is simple:
|
||||||
|
|
||||||
Coding standards are crucial for several reasons:
|
- contributors primarily submit shell scripts
|
||||||
|
- website metadata is **not** contributed as repo JSON files
|
||||||
|
- metadata changes belong to the website / maintainer workflow
|
||||||
|
|
||||||
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.
|
## Scope of these documents
|
||||||
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
|
This contribution guide covers:
|
||||||
|
|
||||||
These documents cover the coding standards for the following types of files in our project:
|
- `ct/$AppName.sh` scripts for container creation and update entrypoints
|
||||||
|
- `install/$AppName-install.sh` scripts for in-container installation logic
|
||||||
|
- the supporting workflow for testing from your fork before opening a PR
|
||||||
|
|
||||||
- **`install/$AppName-install.sh` Scripts**: These scripts are responsible for the installation of applications.
|
## Getting started
|
||||||
- **`ct/$AppName.sh` Scripts**: These scripts handle the creation and updating of containers.
|
|
||||||
- **`json/$AppName.json`**: These files store structured data and are used for the website.
|
|
||||||
|
|
||||||
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.
|
Before contributing, set up:
|
||||||
|
|
||||||
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. 📚🔍
|
1. Visual Studio Code or another editor with ShellCheck support
|
||||||
|
2. a fork of `community-scripts/ProxmoxVED`
|
||||||
|
3. a local clone of your fork
|
||||||
|
|
||||||
Let's work together to keep our codebase clean, efficient, and maintainable! 💪🚀
|
### Recommended extensions
|
||||||
|
|
||||||
|
|
||||||
## 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)
|
- [Shell Syntax](https://marketplace.visualstudio.com/items?itemName=bmalehorn.shell-syntax)
|
||||||
- [ShellCheck](https://marketplace.visualstudio.com/items?itemName=timonwong.shellcheck)
|
- [ShellCheck](https://marketplace.visualstudio.com/items?itemName=timonwong.shellcheck)
|
||||||
- [Shell Format](https://marketplace.visualstudio.com/items?itemName=foxundermoon.shell-format)
|
- [Shell Format](https://marketplace.visualstudio.com/items?itemName=foxundermoon.shell-format)
|
||||||
|
|
||||||
### Important Notes
|
### Templates
|
||||||
- Use [AppName.sh](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh) and [AppName-install.sh](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh) as templates when creating new scripts.
|
|
||||||
|
|
||||||
---
|
Use these templates as your starting point:
|
||||||
|
|
||||||
# 🚀 The Application Script (ct/AppName.sh)
|
- [CT template: `AppName.sh`](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh)
|
||||||
|
- [Install template: `AppName-install.sh`](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh)
|
||||||
|
|
||||||
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md).
|
## Script types
|
||||||
- These scripts are responsible for container creation, setting the necessary variables and handling the update of the application once installed.
|
|
||||||
|
|
||||||
---
|
### Application script: `ct/AppName.sh`
|
||||||
|
|
||||||
# 🛠 The Installation Script (install/AppName-install.sh)
|
Reference guide:
|
||||||
|
|
||||||
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.md).
|
- [CT coding guide for `AppName.sh`](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md)
|
||||||
- These scripts are responsible for the installation of the application.
|
|
||||||
|
|
||||||
---
|
This script is responsible for:
|
||||||
|
|
||||||
## 🚀 Building Your Own Scripts
|
- host-side container orchestration
|
||||||
|
- app variables and defaults
|
||||||
|
- update wiring for the installed app
|
||||||
|
|
||||||
Start with the [template script](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh)
|
### Installation script: `install/AppName-install.sh`
|
||||||
|
|
||||||
---
|
Reference guide:
|
||||||
|
|
||||||
## 🤝 Contribution Process
|
- [Install coding guide for `AppName-install.sh`](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.md)
|
||||||
|
|
||||||
|
This script is responsible for:
|
||||||
|
|
||||||
|
- container-internal installation logic
|
||||||
|
- package/runtime setup
|
||||||
|
- final application configuration
|
||||||
|
|
||||||
|
## Contribution process
|
||||||
|
|
||||||
### 1. Fork the repository
|
### 1. Fork the repository
|
||||||
Fork to your GitHub account
|
|
||||||
|
|
||||||
### 2. Clone your fork on your local environment
|
Fork `community-scripts/ProxmoxVED` to your GitHub account.
|
||||||
|
|
||||||
|
### 2. Clone your fork
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/yourUserName/ForkName
|
git clone https://github.com/yourUserName/ForkName
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Create a new branch
|
### 3. Create a branch
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git switch -c your-feature-branch
|
git switch -c your-feature-branch
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Change paths in build.func install.func and AppName.sh
|
### 4. Configure your fork for testing
|
||||||
To be able to develop from your own branch you need to change `https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main` to `https://raw.githubusercontent.com/[USER]/[REPOSITORY]/refs/heads/[BRANCH]`. You need to make this change atleast in misc/build.func misc/install.func and in your ct/AppName.sh. This change is only for testing. Before opening a Pull Request you should change this line change all this back to point to `https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main`.
|
|
||||||
|
Use the helper script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash docs/contribution/setup-fork.sh --full
|
||||||
|
```
|
||||||
|
|
||||||
|
This prepares the raw GitHub URLs in your working copy so you can test against your own fork instead of the upstream repository.
|
||||||
|
|
||||||
|
### 5. Build and test from your fork
|
||||||
|
|
||||||
|
Use the curl/bash execution model that matches real user behavior, for example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash -c "$(curl -fsSL https://raw.githubusercontent.com/<USER>/<REPO>/refs/heads/<BRANCH>/ct/myapp.sh)"
|
||||||
|
```
|
||||||
|
|
||||||
|
Do **not** document or optimize only for local manual execution if the real path is curl-based execution.
|
||||||
|
|
||||||
|
### 6. Commit only your intended contribution
|
||||||
|
|
||||||
### 4. Commit changes (without build.func and install.func!)
|
|
||||||
```bash
|
```bash
|
||||||
git commit -m "Your commit message"
|
git commit -m "Your commit message"
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5. Push to your fork
|
### 7. Push your branch
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git push origin your-feature-branch
|
git push origin your-feature-branch
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6. Create a Pull Request
|
### 8. Open a pull request
|
||||||
Open a Pull Request from your feature branch to the main repository branch. You must only include your **$AppName.sh**, **$AppName-install.sh** and **$AppName.json** files in the pull request.
|
|
||||||
|
|
||||||
---
|
Open a PR from your branch to `community-scripts/ProxmoxVED/main`.
|
||||||
|
|
||||||
## 📚 Pages
|
Your PR should contain only the files that belong to the script contribution itself, typically:
|
||||||
|
|
||||||
|
- `ct/myapp.sh`
|
||||||
|
- `install/myapp-install.sh`
|
||||||
|
|
||||||
|
## Website metadata
|
||||||
|
|
||||||
|
Website metadata is maintained outside this repository's script contribution flow.
|
||||||
|
|
||||||
|
That means:
|
||||||
|
|
||||||
|
- do not add repo JSON metadata files as part of the normal contribution path
|
||||||
|
- do not assume a `frontend/public/json/...` workflow exists for the live site
|
||||||
|
- route metadata creation or metadata changes through the website / maintainer workflow
|
||||||
|
|
||||||
|
## Pages
|
||||||
|
|
||||||
- [CT Template: AppName.sh](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh)
|
- [CT Template: AppName.sh](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh)
|
||||||
- [Install Template: AppName-install.sh](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh)
|
- [Install Template: AppName-install.sh](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh)
|
||||||
- [JSON Template: AppName.json](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/json/AppName.json)
|
- [Fork setup guide](./FORK_SETUP.md)
|
||||||
|
- [Contribution README](./README.md)
|
||||||
|
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ var_unprivileged="1" # 1=unprivileged (secure), 0=privileged (rarely n
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Variable Naming Convention**:
|
**Variable Naming Convention**:
|
||||||
|
|
||||||
- Variables exposed to user: `var_*` (e.g., `var_cpu`, `var_hostname`, `var_ssh`)
|
- Variables exposed to user: `var_*` (e.g., `var_cpu`, `var_hostname`, `var_ssh`)
|
||||||
- Internal variables: lowercase (e.g., `container_id`, `app_version`)
|
- Internal variables: lowercase (e.g., `container_id`, `app_version`)
|
||||||
|
|
||||||
@@ -273,6 +274,7 @@ echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
|
|||||||
**Triggered by**: Called automatically at script start
|
**Triggered by**: Called automatically at script start
|
||||||
|
|
||||||
**Behavior**:
|
**Behavior**:
|
||||||
|
|
||||||
1. Parse command-line arguments (if any)
|
1. Parse command-line arguments (if any)
|
||||||
2. Generate random UUID for session tracking
|
2. Generate random UUID for session tracking
|
||||||
3. Load container storage from Proxmox
|
3. Load container storage from Proxmox
|
||||||
@@ -284,6 +286,7 @@ echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
|
|||||||
**Purpose**: Launch the container creation menu with 5 installation modes
|
**Purpose**: Launch the container creation menu with 5 installation modes
|
||||||
|
|
||||||
**Menu Options**:
|
**Menu Options**:
|
||||||
|
|
||||||
```
|
```
|
||||||
1. Default Installation (Quick setup, predefined settings)
|
1. Default Installation (Quick setup, predefined settings)
|
||||||
2. Advanced Installation (19-step wizard with full control)
|
2. Advanced Installation (19-step wizard with full control)
|
||||||
@@ -297,6 +300,7 @@ echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
|
|||||||
**Purpose**: Main orchestrator for LXC container creation
|
**Purpose**: Main orchestrator for LXC container creation
|
||||||
|
|
||||||
**Operations**:
|
**Operations**:
|
||||||
|
|
||||||
1. Validates all variables
|
1. Validates all variables
|
||||||
2. Creates LXC container via `pct create`
|
2. Creates LXC container via `pct create`
|
||||||
3. Executes `install/AppName-install.sh` inside container
|
3. Executes `install/AppName-install.sh` inside container
|
||||||
@@ -398,6 +402,7 @@ msg_ok "Completed successfully!\n"
|
|||||||
**Symptom**: `pct create` exits with error code 209
|
**Symptom**: `pct create` exits with error code 209
|
||||||
|
|
||||||
**Solution**:
|
**Solution**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Check existing containers
|
# Check existing containers
|
||||||
pct list | grep CTID
|
pct list | grep CTID
|
||||||
@@ -411,6 +416,7 @@ pct destroy CTID
|
|||||||
### Update Function Doesn't Detect New Version
|
### Update Function Doesn't Detect New Version
|
||||||
|
|
||||||
**Debug**:
|
**Debug**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Check version file
|
# Check version file
|
||||||
cat /opt/AppName_version.txt
|
cat /opt/AppName_version.txt
|
||||||
@@ -426,6 +432,7 @@ curl -fsSL https://api.github.com/repos/user/repo/releases/latest | grep tag_nam
|
|||||||
Before submitting a PR:
|
Before submitting a PR:
|
||||||
|
|
||||||
### Script Structure
|
### Script Structure
|
||||||
|
|
||||||
- [ ] Shebang is `#!/usr/bin/env bash`
|
- [ ] Shebang is `#!/usr/bin/env bash`
|
||||||
- [ ] Imports `build.func` from community-scripts repo
|
- [ ] Imports `build.func` from community-scripts repo
|
||||||
- [ ] Copyright header with author and source URL
|
- [ ] Copyright header with author and source URL
|
||||||
@@ -433,17 +440,20 @@ Before submitting a PR:
|
|||||||
- [ ] `var_tags` are semicolon-separated (no spaces)
|
- [ ] `var_tags` are semicolon-separated (no spaces)
|
||||||
|
|
||||||
### Default Values
|
### Default Values
|
||||||
|
|
||||||
- [ ] `var_cpu` set appropriately (2-4 for most apps)
|
- [ ] `var_cpu` set appropriately (2-4 for most apps)
|
||||||
- [ ] `var_ram` set appropriately (1024-4096 MB minimum)
|
- [ ] `var_ram` set appropriately (1024-4096 MB minimum)
|
||||||
- [ ] `var_disk` sufficient for app + data (5-20 GB)
|
- [ ] `var_disk` sufficient for app + data (5-20 GB)
|
||||||
- [ ] `var_os` is realistic
|
- [ ] `var_os` is realistic
|
||||||
|
|
||||||
### Functions
|
### Functions
|
||||||
|
|
||||||
- [ ] `update_script()` implemented
|
- [ ] `update_script()` implemented
|
||||||
- [ ] Update function checks if app installed
|
- [ ] Update function checks if app installed
|
||||||
- [ ] Proper error handling with `msg_error`
|
- [ ] Proper error handling with `msg_error`
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
|
||||||
- [ ] Script tested with default installation
|
- [ ] Script tested with default installation
|
||||||
- [ ] Script tested with advanced (19-step) installation
|
- [ ] Script tested with advanced (19-step) installation
|
||||||
- [ ] Update function tested on existing installation
|
- [ ] Update function tested on existing installation
|
||||||
|
|||||||
268
docs/guides/netboot-xyz.md
Normal file
268
docs/guides/netboot-xyz.md
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
# netboot.xyz — Self-Hosted PXE Boot Server on Proxmox
|
||||||
|
|
||||||
|
## What is netboot.xyz?
|
||||||
|
|
||||||
|
netboot.xyz is a **network boot (PXE) utility**. It lets any machine on your network boot from a menu of operating systems and tools — without a USB stick, CD/DVD, or pre-downloaded ISO.
|
||||||
|
|
||||||
|
Think of it like a universal boot menu that loads over the network.
|
||||||
|
|
||||||
|
### What your self-hosted container actually does
|
||||||
|
|
||||||
|
Your LXC container hosts only two things:
|
||||||
|
|
||||||
|
- **iPXE bootloader binaries** (`.efi`, `.kpxe` files — a few hundred KB each)
|
||||||
|
- **iPXE menu files** (plain text `.ipxe` scripts that define the menu structure)
|
||||||
|
|
||||||
|
That's it. The container serves ~80 MB of files total (bootloaders + menus).
|
||||||
|
|
||||||
|
When a machine PXE-boots, it:
|
||||||
|
|
||||||
|
1. Fetches the bootloader binary from your container (via TFTP or HTTP)
|
||||||
|
2. The bootloader loads the menu from your container
|
||||||
|
3. You pick an OS
|
||||||
|
4. The OS installer or live system loads **directly from upstream internet mirrors** at boot time
|
||||||
|
|
||||||
|
Your container is the **signpost**. The internet is the **library**.
|
||||||
|
|
||||||
|
> **Important:** Clients need internet access to actually install/boot an OS. Your container itself does not need to store or proxy OS images.
|
||||||
|
|
||||||
|
### What you can boot
|
||||||
|
|
||||||
|
| Category | Examples |
|
||||||
|
| ------------------ | ------------------------------------------------------------- |
|
||||||
|
| **OS Installers** | Debian, Ubuntu, Fedora, Rocky Linux, Alpine, Arch, NixOS, ... |
|
||||||
|
| **Live Systems** | Kali Live, Tails, Mint Live, Manjaro Live, ... |
|
||||||
|
| **Rescue Tools** | SystemRescue, Clonezilla, GParted, Rescuezilla, Memtest86 |
|
||||||
|
| **Virtualization** | Proxmox VE, Harvester, VMware ESXi |
|
||||||
|
| **BSD** | FreeBSD, OpenBSD |
|
||||||
|
| **Utilities** | ShredOS (disk wipe), DBAN, ZFSBootMenu, Super Grub2 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Run on your **Proxmox host**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/netboot-xyz.sh)"
|
||||||
|
```
|
||||||
|
|
||||||
|
Creates a minimal Debian 13 LXC container:
|
||||||
|
|
||||||
|
| Resource | Value |
|
||||||
|
| ----------- | ------ |
|
||||||
|
| CPU | 1 core |
|
||||||
|
| RAM | 512 MB |
|
||||||
|
| Disk | 8 GB |
|
||||||
|
| Port (HTTP) | 80/TCP |
|
||||||
|
| Port (TFTP) | 69/UDP |
|
||||||
|
|
||||||
|
After installation, the web interface is available at:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://<container-ip>/
|
||||||
|
```
|
||||||
|
|
||||||
|
It shows a directory listing of all available bootloaders and menu files.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to PXE Boot a Machine
|
||||||
|
|
||||||
|
### Step 1 — Configure your DHCP server
|
||||||
|
|
||||||
|
Your DHCP server needs to tell PXE clients where to find the bootloader.
|
||||||
|
|
||||||
|
**Required settings:**
|
||||||
|
|
||||||
|
| Setting | Value |
|
||||||
|
| --------------------------- | ------------------ |
|
||||||
|
| Next Server (TFTP) | `<container-ip>` |
|
||||||
|
| Boot filename (UEFI) | `netboot.xyz.efi` |
|
||||||
|
| Boot filename (BIOS/Legacy) | `netboot.xyz.kpxe` |
|
||||||
|
|
||||||
|
**OPNsense / pfSense:**
|
||||||
|
`Services → DHCP Server → [interface] → Network Booting`
|
||||||
|
|
||||||
|
- _Enable_: checked
|
||||||
|
- _Next server_: `<container-ip>`
|
||||||
|
- _Default BIOS filename_: `netboot.xyz.kpxe`
|
||||||
|
- _UEFI 64-bit filename_: `netboot.xyz.efi`
|
||||||
|
|
||||||
|
**dnsmasq (Pi-hole, AdGuard Home, OpenWrt):**
|
||||||
|
|
||||||
|
```
|
||||||
|
dhcp-boot=netboot.xyz.kpxe,<container-ip> # BIOS
|
||||||
|
# or:
|
||||||
|
dhcp-boot=netboot.xyz.efi,<container-ip> # UEFI
|
||||||
|
```
|
||||||
|
|
||||||
|
**ISC DHCP (`dhcpd.conf`):**
|
||||||
|
|
||||||
|
```
|
||||||
|
next-server <container-ip>;
|
||||||
|
filename "netboot.xyz.efi";
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2 — Enable PXE boot on your client
|
||||||
|
|
||||||
|
In the machine's BIOS/UEFI:
|
||||||
|
|
||||||
|
- Enable **Network Boot** / **PXE Boot**
|
||||||
|
- Set boot order: Network first (or select once via boot menu, usually F11/F12)
|
||||||
|
|
||||||
|
### Step 3 — Boot
|
||||||
|
|
||||||
|
Power on the machine. The iPXE bootloader loads from your container, shows the menu, and you navigate with arrow keys.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## UEFI HTTP Boot (no DHCP changes)
|
||||||
|
|
||||||
|
Modern UEFI firmware supports booting directly from an HTTP URL — no DHCP options needed.
|
||||||
|
|
||||||
|
Load the bootloader directly in the UEFI shell:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://<container-ip>/netboot.xyz.efi
|
||||||
|
```
|
||||||
|
|
||||||
|
**Proxmox VMs:** Set the VM network boot URL in the UEFI shell, or use iPXE chaining in the VM BIOS.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Available Bootloader Files
|
||||||
|
|
||||||
|
All files are served at `http://<container-ip>/` and `http://<container-ip>/ipxe/`:
|
||||||
|
|
||||||
|
### x86_64 UEFI
|
||||||
|
|
||||||
|
| File | Use case |
|
||||||
|
| ------------------------- | ----------------------------------------------- |
|
||||||
|
| `netboot.xyz.efi` | Standard UEFI — recommended starting point |
|
||||||
|
| `netboot.xyz.efi.dsk` | Virtual floppy/disk image of the EFI bootloader |
|
||||||
|
| `netboot.xyz-snp.efi` | UEFI SNP — tries all network devices |
|
||||||
|
| `netboot.xyz-snp.efi.dsk` | Disk image of SNP EFI bootloader |
|
||||||
|
| `netboot.xyz-snponly.efi` | UEFI SNP — only boots from chained device |
|
||||||
|
|
||||||
|
### x86_64 UEFI Metal (Secure Boot / code-signed)
|
||||||
|
|
||||||
|
| File | Use case |
|
||||||
|
| ------------------------------- | ------------------------------------------- |
|
||||||
|
| `netboot.xyz-metal.efi` | Secure Boot compatible UEFI bootloader |
|
||||||
|
| `netboot.xyz-metal.efi.dsk` | Disk image of metal EFI bootloader |
|
||||||
|
| `netboot.xyz-metal-snp.efi` | Secure Boot SNP — tries all network devices |
|
||||||
|
| `netboot.xyz-metal-snp.efi.dsk` | Disk image of metal SNP EFI bootloader |
|
||||||
|
| `netboot.xyz-metal-snponly.efi` | Secure Boot SNP — only chained device |
|
||||||
|
|
||||||
|
### x86_64 BIOS / Legacy
|
||||||
|
|
||||||
|
| File | Use case |
|
||||||
|
| --------------------------- | ------------------------------------------------- |
|
||||||
|
| `netboot.xyz.kpxe` | BIOS PXE — built-in iPXE NIC drivers |
|
||||||
|
| `netboot.xyz-undionly.kpxe` | BIOS PXE fallback — use if NIC has driver issues |
|
||||||
|
| `netboot.xyz-metal.kpxe` | BIOS PXE — Secure Boot / code-signed variant |
|
||||||
|
| `netboot.xyz.lkrn` | Kernel module — load from GRUB/EXTLINUX |
|
||||||
|
| `netboot.xyz-linux.bin` | Linux binary — chainload from existing Linux boot |
|
||||||
|
| `netboot.xyz.dsk` | Virtual floppy disk for DRAC/iLO, VMware, etc. |
|
||||||
|
| `netboot.xyz.pdsk` | Padded virtual floppy disk |
|
||||||
|
|
||||||
|
### ARM64
|
||||||
|
|
||||||
|
| File | Use case |
|
||||||
|
| ------------------------------------- | ------------------------------------------- |
|
||||||
|
| `netboot.xyz-arm64.efi` | ARM64 UEFI — standard |
|
||||||
|
| `netboot.xyz-arm64-snp.efi` | ARM64 UEFI SNP — tries all network devices |
|
||||||
|
| `netboot.xyz-arm64-snponly.efi` | ARM64 UEFI SNP — only chained device |
|
||||||
|
| `netboot.xyz-metal-arm64.efi` | ARM64 Secure Boot UEFI |
|
||||||
|
| `netboot.xyz-metal-arm64-snp.efi` | ARM64 Secure Boot SNP |
|
||||||
|
| `netboot.xyz-metal-arm64-snponly.efi` | ARM64 Secure Boot SNP — only chained device |
|
||||||
|
|
||||||
|
### ISO / IMG (for media creation or virtual boot)
|
||||||
|
|
||||||
|
| File | Use case |
|
||||||
|
| --------------------------- | ------------------------------------------------- |
|
||||||
|
| `netboot.xyz.iso` | x86_64 ISO — CD/DVD, virtual CD, DRAC/iLO, VMware |
|
||||||
|
| `netboot.xyz.img` | x86_64 IMG — USB key creation |
|
||||||
|
| `netboot.xyz-arm64.iso` | ARM64 ISO |
|
||||||
|
| `netboot.xyz-arm64.img` | ARM64 IMG — USB key creation |
|
||||||
|
| `netboot.xyz-multiarch.iso` | Combined x86_64 + ARM64 ISO |
|
||||||
|
| `netboot.xyz-multiarch.img` | Combined x86_64 + ARM64 IMG |
|
||||||
|
|
||||||
|
### Checksums
|
||||||
|
|
||||||
|
| File | Use case |
|
||||||
|
| ---------------------------------- | --------------------------- |
|
||||||
|
| `netboot.xyz-sha256-checksums.txt` | SHA256 hashes for all files |
|
||||||
|
|
||||||
|
> **BIOS vs UEFI:** Use `.efi` for UEFI systems, `.kpxe` for legacy BIOS. Mixing them causes silent failures.
|
||||||
|
>
|
||||||
|
> **Secure Boot:** Use the `-metal-` variants if your firmware enforces Secure Boot.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Customizing the Menu
|
||||||
|
|
||||||
|
Edit `/var/www/html/boot.cfg` inside the container:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SSH into the container, then:
|
||||||
|
nano /var/www/html/boot.cfg
|
||||||
|
```
|
||||||
|
|
||||||
|
Changes take effect immediately — no service restart needed.
|
||||||
|
|
||||||
|
Common customizations:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set a default boot entry with 10-second timeout:
|
||||||
|
set menu-timeout 10000
|
||||||
|
set menu-default linux
|
||||||
|
|
||||||
|
# Override the mirror used for Ubuntu:
|
||||||
|
set mirror http://de.archive.ubuntu.com/ubuntu
|
||||||
|
```
|
||||||
|
|
||||||
|
Full documentation: [netboot.xyz/docs](https://netboot.xyz/docs/)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Updating
|
||||||
|
|
||||||
|
The update script preserves your `boot.cfg` customizations, updates menus and bootloaders to the latest release:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/netboot-xyz.sh)"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Client can't reach the container / TFTP timeout
|
||||||
|
|
||||||
|
- Check that UDP/69 (TFTP) and TCP/80 (HTTP) are not blocked between client and container
|
||||||
|
- Proxmox firewall: add rules to allow these ports inbound on the container
|
||||||
|
- Check that the container is in the same VLAN/subnet as the client, or that inter-VLAN routing is configured
|
||||||
|
|
||||||
|
### Menu loads but OS download fails or is slow
|
||||||
|
|
||||||
|
- Expected — OS files come from the internet, not your container
|
||||||
|
- Client needs internet access (direct or via NAT through Proxmox)
|
||||||
|
- For air-gapped networks, you need to mirror OS images locally (advanced, see netboot.xyz docs)
|
||||||
|
|
||||||
|
### Machine boots to local disk instead of PXE
|
||||||
|
|
||||||
|
- Check boot order in BIOS/UEFI — network boot must come first, or select it manually via F11/F12
|
||||||
|
- Some UEFI systems require Secure Boot to be disabled for iPXE
|
||||||
|
|
||||||
|
### UEFI machine ignores the boot filename
|
||||||
|
|
||||||
|
- Some DHCP servers send the same `filename` option to both BIOS and UEFI clients
|
||||||
|
- Use vendor class matching in your DHCP config to send `.efi` only to UEFI clients
|
||||||
|
- OPNsense/pfSense handle this automatically when you set both BIOS and UEFI filenames separately
|
||||||
|
|
||||||
|
### `netboot.xyz.kpxe` works but `netboot.xyz.efi` doesn't (or vice versa)
|
||||||
|
|
||||||
|
- BIOS systems → use `netboot.xyz.kpxe` or `netboot.xyz-undionly.kpxe`
|
||||||
|
- UEFI systems → use `netboot.xyz.efi` or `netboot.xyz-snp.efi`
|
||||||
@@ -1,15 +1,25 @@
|
|||||||
# Misc Documentation
|
# 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.
|
This directory documents the shared Bash function libraries under `misc/`.
|
||||||
|
|
||||||
|
The important implementation detail is that these libraries are **not independent islands**:
|
||||||
|
|
||||||
|
- `build.func` orchestrates host-side CT creation.
|
||||||
|
- `api.func` is the canonical source of telemetry and exit-code explanations.
|
||||||
|
- `error_handler.func` wraps trap handling and falls back to `explain_exit_code()` if `api.func` was not loaded yet.
|
||||||
|
- `install.func` runs inside the container and bootstraps `core.func` + `error_handler.func` first, then downloads `tools.func` after the OS update stage.
|
||||||
|
- `tools.func` is the large Debian/Ubuntu helper toolbox for repository management, retries, releases, services, language runtimes, databases, GPU helpers, and update workflows.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🏗️ **Core Function Libraries**
|
## 🏗️ **Core Function Libraries**
|
||||||
|
|
||||||
### 📁 [build.func/](./build.func/)
|
### 📁 [build.func/](./build.func/)
|
||||||
|
|
||||||
**Core LXC Container Orchestration** - Main orchestrator for Proxmox LXC container creation
|
**Core LXC Container Orchestration** - Main orchestrator for Proxmox LXC container creation
|
||||||
|
|
||||||
**Contents:**
|
**Contents:**
|
||||||
|
|
||||||
- BUILD_FUNC_FLOWCHART.md - Visual execution flows and decision trees
|
- BUILD_FUNC_FLOWCHART.md - Visual execution flows and decision trees
|
||||||
- BUILD_FUNC_ARCHITECTURE.md - System architecture and design
|
- BUILD_FUNC_ARCHITECTURE.md - System architecture and design
|
||||||
- BUILD_FUNC_ENVIRONMENT_VARIABLES.md - Complete environment variable reference
|
- BUILD_FUNC_ENVIRONMENT_VARIABLES.md - Complete environment variable reference
|
||||||
@@ -23,9 +33,11 @@ This directory contains comprehensive documentation for all function libraries a
|
|||||||
---
|
---
|
||||||
|
|
||||||
### 📁 [core.func/](./core.func/)
|
### 📁 [core.func/](./core.func/)
|
||||||
**System Utilities & Foundation** - Essential utility functions and system checks
|
|
||||||
|
**System Utilities & Foundation** - Shared runtime foundation for logging, prompts, validation, and execution control
|
||||||
|
|
||||||
**Contents:**
|
**Contents:**
|
||||||
|
|
||||||
- CORE_FLOWCHART.md - Visual execution flows
|
- CORE_FLOWCHART.md - Visual execution flows
|
||||||
- CORE_FUNCTIONS_REFERENCE.md - Complete function reference
|
- CORE_FUNCTIONS_REFERENCE.md - Complete function reference
|
||||||
- CORE_INTEGRATION.md - Integration points
|
- CORE_INTEGRATION.md - Integration points
|
||||||
@@ -37,9 +49,11 @@ This directory contains comprehensive documentation for all function libraries a
|
|||||||
---
|
---
|
||||||
|
|
||||||
### 📁 [error_handler.func/](./error_handler.func/)
|
### 📁 [error_handler.func/](./error_handler.func/)
|
||||||
**Error Handling & Signal Management** - Comprehensive error handling and signal trapping
|
|
||||||
|
**Error Handling & Signal Management** - Trap orchestration, cleanup, and abort telemetry
|
||||||
|
|
||||||
**Contents:**
|
**Contents:**
|
||||||
|
|
||||||
- ERROR_HANDLER_FLOWCHART.md - Visual error handling flows
|
- ERROR_HANDLER_FLOWCHART.md - Visual error handling flows
|
||||||
- ERROR_HANDLER_FUNCTIONS_REFERENCE.md - Function reference
|
- ERROR_HANDLER_FUNCTIONS_REFERENCE.md - Function reference
|
||||||
- ERROR_HANDLER_INTEGRATION.md - Integration with other components
|
- ERROR_HANDLER_INTEGRATION.md - Integration with other components
|
||||||
@@ -51,39 +65,45 @@ This directory contains comprehensive documentation for all function libraries a
|
|||||||
---
|
---
|
||||||
|
|
||||||
### 📁 [api.func/](./api.func/)
|
### 📁 [api.func/](./api.func/)
|
||||||
**Proxmox API Integration** - API communication and diagnostic reporting
|
|
||||||
|
**Telemetry & Diagnostics Runtime** - Anonymous telemetry reporting, progress tracking, and canonical exit-code mapping
|
||||||
|
|
||||||
**Contents:**
|
**Contents:**
|
||||||
|
|
||||||
- API_FLOWCHART.md - API communication flows
|
- API_FLOWCHART.md - API communication flows
|
||||||
- API_FUNCTIONS_REFERENCE.md - Function reference
|
- API_FUNCTIONS_REFERENCE.md - Function reference
|
||||||
- API_INTEGRATION.md - Integration points
|
- API_INTEGRATION.md - Integration points
|
||||||
- API_USAGE_EXAMPLES.md - Practical examples
|
- API_USAGE_EXAMPLES.md - Practical examples
|
||||||
- README.md - Overview and quick reference
|
- README.md - Overview and quick reference
|
||||||
|
|
||||||
**Key Functions**: `post_to_api()`, `post_update_to_api()`, `get_error_description()`
|
**Key Functions**: `post_to_api()`, `post_to_api_vm()`, `post_progress_to_api()`, `post_update_to_api()`, `explain_exit_code()`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📦 **Installation & Setup Function Libraries**
|
## 📦 **Installation & Setup Function Libraries**
|
||||||
|
|
||||||
### 📁 [install.func/](./install.func/)
|
### 📁 [install.func/](./install.func/)
|
||||||
**Container Installation Workflow** - Installation orchestration for container-internal setup
|
|
||||||
|
**Container Installation Workflow** - Container bootstrap inside the LXC
|
||||||
|
|
||||||
**Contents:**
|
**Contents:**
|
||||||
|
|
||||||
- INSTALL_FUNC_FLOWCHART.md - Installation workflow diagrams
|
- INSTALL_FUNC_FLOWCHART.md - Installation workflow diagrams
|
||||||
- INSTALL_FUNC_FUNCTIONS_REFERENCE.md - Complete function reference
|
- INSTALL_FUNC_FUNCTIONS_REFERENCE.md - Complete function reference
|
||||||
- INSTALL_FUNC_INTEGRATION.md - Integration with build and tools
|
- INSTALL_FUNC_INTEGRATION.md - Integration with build and tools
|
||||||
- INSTALL_FUNC_USAGE_EXAMPLES.md - Practical examples
|
- INSTALL_FUNC_USAGE_EXAMPLES.md - Practical examples
|
||||||
- README.md - Overview and quick reference
|
- README.md - Overview and quick reference
|
||||||
|
|
||||||
**Key Functions**: `setting_up_container()`, `network_check()`, `update_os()`, `motd_ssh()`, `cleanup_lxc()`
|
**Key Functions**: `setting_up_container()`, `network_check()`, `update_os()`, `motd_ssh()`, `customize()`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 📁 [tools.func/](./tools.func/)
|
### 📁 [tools.func/](./tools.func/)
|
||||||
**Package & Tool Installation** - Robust package management and 30+ tool installation functions
|
|
||||||
|
**Package & Tool Installation** - Repository, package, release, runtime, and service toolbox
|
||||||
|
|
||||||
**Contents:**
|
**Contents:**
|
||||||
|
|
||||||
- TOOLS_FUNC_FLOWCHART.md - Package management flows
|
- TOOLS_FUNC_FLOWCHART.md - Package management flows
|
||||||
- TOOLS_FUNC_FUNCTIONS_REFERENCE.md - 30+ function reference
|
- TOOLS_FUNC_FUNCTIONS_REFERENCE.md - 30+ function reference
|
||||||
- TOOLS_FUNC_INTEGRATION.md - Integration with install workflows
|
- TOOLS_FUNC_INTEGRATION.md - Integration with install workflows
|
||||||
@@ -91,14 +111,16 @@ This directory contains comprehensive documentation for all function libraries a
|
|||||||
- TOOLS_FUNC_ENVIRONMENT_VARIABLES.md - Configuration reference
|
- TOOLS_FUNC_ENVIRONMENT_VARIABLES.md - Configuration reference
|
||||||
- README.md - Overview and quick reference
|
- README.md - Overview and quick reference
|
||||||
|
|
||||||
**Key Functions**: `setup_nodejs()`, `setup_php()`, `setup_mariadb()`, `setup_docker()`, `setup_deb822_repo()`, `pkg_install()`, `pkg_update()`
|
**Key Functions**: `curl_with_retry()`, `setup_deb822_repo()`, `install_packages_with_retry()`, `setup_mariadb()`, `setup_postgresql()`, `get_latest_github_release()`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 📁 [alpine-install.func/](./alpine-install.func/)
|
### 📁 [alpine-install.func/](./alpine-install.func/)
|
||||||
|
|
||||||
**Alpine Container Setup** - Alpine Linux-specific installation functions
|
**Alpine Container Setup** - Alpine Linux-specific installation functions
|
||||||
|
|
||||||
**Contents:**
|
**Contents:**
|
||||||
|
|
||||||
- ALPINE_INSTALL_FUNC_FLOWCHART.md - Alpine setup flows
|
- ALPINE_INSTALL_FUNC_FLOWCHART.md - Alpine setup flows
|
||||||
- ALPINE_INSTALL_FUNC_FUNCTIONS_REFERENCE.md - Function reference
|
- ALPINE_INSTALL_FUNC_FUNCTIONS_REFERENCE.md - Function reference
|
||||||
- ALPINE_INSTALL_FUNC_INTEGRATION.md - Integration points
|
- ALPINE_INSTALL_FUNC_INTEGRATION.md - Integration points
|
||||||
@@ -110,9 +132,11 @@ This directory contains comprehensive documentation for all function libraries a
|
|||||||
---
|
---
|
||||||
|
|
||||||
### 📁 [alpine-tools.func/](./alpine-tools.func/)
|
### 📁 [alpine-tools.func/](./alpine-tools.func/)
|
||||||
|
|
||||||
**Alpine Tool Installation** - Alpine-specific package and tool installation
|
**Alpine Tool Installation** - Alpine-specific package and tool installation
|
||||||
|
|
||||||
**Contents:**
|
**Contents:**
|
||||||
|
|
||||||
- ALPINE_TOOLS_FUNC_FLOWCHART.md - Alpine package flows
|
- ALPINE_TOOLS_FUNC_FLOWCHART.md - Alpine package flows
|
||||||
- ALPINE_TOOLS_FUNC_FUNCTIONS_REFERENCE.md - Function reference
|
- ALPINE_TOOLS_FUNC_FUNCTIONS_REFERENCE.md - Function reference
|
||||||
- ALPINE_TOOLS_FUNC_INTEGRATION.md - Integration with Alpine workflows
|
- ALPINE_TOOLS_FUNC_INTEGRATION.md - Integration with Alpine workflows
|
||||||
@@ -124,9 +148,11 @@ This directory contains comprehensive documentation for all function libraries a
|
|||||||
---
|
---
|
||||||
|
|
||||||
### 📁 [cloud-init.func/](./cloud-init.func/)
|
### 📁 [cloud-init.func/](./cloud-init.func/)
|
||||||
|
|
||||||
**VM Cloud-Init Configuration** - Cloud-init and VM provisioning functions
|
**VM Cloud-Init Configuration** - Cloud-init and VM provisioning functions
|
||||||
|
|
||||||
**Contents:**
|
**Contents:**
|
||||||
|
|
||||||
- CLOUD_INIT_FUNC_FLOWCHART.md - Cloud-init flows
|
- CLOUD_INIT_FUNC_FLOWCHART.md - Cloud-init flows
|
||||||
- CLOUD_INIT_FUNC_FUNCTIONS_REFERENCE.md - Function reference
|
- CLOUD_INIT_FUNC_FUNCTIONS_REFERENCE.md - Function reference
|
||||||
- CLOUD_INIT_FUNC_INTEGRATION.md - Integration points
|
- CLOUD_INIT_FUNC_INTEGRATION.md - Integration points
|
||||||
@@ -145,18 +171,24 @@ This directory contains comprehensive documentation for all function libraries a
|
|||||||
├─────────────────────────────────────────────┤
|
├─────────────────────────────────────────────┤
|
||||||
│ │
|
│ │
|
||||||
│ ct/AppName.sh │
|
│ ct/AppName.sh │
|
||||||
│ ↓ (sources) │
|
│ ↓ sources │
|
||||||
│ build.func │
|
│ build.func │
|
||||||
│ ├─ variables() │
|
│ ├─ sources api.func │
|
||||||
│ ├─ build_container() │
|
│ ├─ sources core.func │
|
||||||
│ └─ advanced_settings() │
|
│ ├─ sources error_handler.func │
|
||||||
│ ↓ (calls pct create with) │
|
│ ├─ loads variables/settings/prompts │
|
||||||
|
│ └─ creates container + launch phase │
|
||||||
|
│ ↓ pct exec / lxc-attach │
|
||||||
│ install/appname-install.sh │
|
│ install/appname-install.sh │
|
||||||
│ ↓ (sources) │
|
│ ↓ sources install.func │
|
||||||
│ ├─ core.func (colors, messaging) │
|
│ ├─ sources core.func │
|
||||||
│ ├─ error_handler.func (error trapping) │
|
│ ├─ sources error_handler.func │
|
||||||
│ ├─ install.func (setup/network) │
|
│ ├─ load_functions() │
|
||||||
│ └─ tools.func (packages/tools) │
|
│ ├─ catch_errors() │
|
||||||
|
│ ├─ network_check() │
|
||||||
|
│ ├─ update_os() │
|
||||||
|
│ │ └─ downloads + sources tools.func │
|
||||||
|
│ └─ app install uses tools.func │
|
||||||
│ │
|
│ │
|
||||||
└─────────────────────────────────────────────┘
|
└─────────────────────────────────────────────┘
|
||||||
|
|
||||||
@@ -192,7 +224,7 @@ This directory contains comprehensive documentation for all function libraries a
|
|||||||
## 📊 **Documentation Quick Stats**
|
## 📊 **Documentation Quick Stats**
|
||||||
|
|
||||||
| Library | Files | Functions | Status |
|
| Library | Files | Functions | Status |
|
||||||
|---------|:---:|:---:|:---:|
|
| ------------------- | :---: | :-------: | :---------: |
|
||||||
| build.func | 7 | 50+ | ✅ Complete |
|
| build.func | 7 | 50+ | ✅ Complete |
|
||||||
| core.func | 5 | 20+ | ✅ Complete |
|
| core.func | 5 | 20+ | ✅ Complete |
|
||||||
| error_handler.func | 5 | 10+ | ✅ Complete |
|
| error_handler.func | 5 | 10+ | ✅ Complete |
|
||||||
@@ -210,16 +242,20 @@ This directory contains comprehensive documentation for all function libraries a
|
|||||||
## 🚀 **Getting Started**
|
## 🚀 **Getting Started**
|
||||||
|
|
||||||
### For Container Creation Scripts
|
### For Container Creation Scripts
|
||||||
Start with: **[build.func/](./build.func/)** → **[tools.func/](./tools.func/)** → **[install.func/](./install.func/)**
|
|
||||||
|
Start with: **[build.func/](./build.func/)** → **[core.func/](./core.func/)** → **[error_handler.func/](./error_handler.func/)** → **[api.func/](./api.func/)** → **[install.func/](./install.func/)** → **[tools.func/](./tools.func/)**
|
||||||
|
|
||||||
### For Alpine Containers
|
### For Alpine Containers
|
||||||
|
|
||||||
Start with: **[alpine-install.func/](./alpine-install.func/)** → **[alpine-tools.func/](./alpine-tools.func/)**
|
Start with: **[alpine-install.func/](./alpine-install.func/)** → **[alpine-tools.func/](./alpine-tools.func/)**
|
||||||
|
|
||||||
### For VM Provisioning
|
### For VM Provisioning
|
||||||
|
|
||||||
Start with: **[cloud-init.func/](./cloud-init.func/)**
|
Start with: **[cloud-init.func/](./cloud-init.func/)**
|
||||||
|
|
||||||
### For Troubleshooting
|
### For Troubleshooting
|
||||||
Start with: **[error_handler.func/](./error_handler.func/)** → **[EXIT_CODES.md](../EXIT_CODES.md)**
|
|
||||||
|
Start with: **[error_handler.func/](./error_handler.func/)** → **[api.func/](./api.func/)**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -251,6 +287,7 @@ function-library/
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Advantages**:
|
**Advantages**:
|
||||||
|
|
||||||
- ✅ Consistent navigation across all libraries
|
- ✅ Consistent navigation across all libraries
|
||||||
- ✅ Quick reference sections in each README
|
- ✅ Quick reference sections in each README
|
||||||
- ✅ Visual flowcharts for understanding
|
- ✅ Visual flowcharts for understanding
|
||||||
@@ -273,11 +310,12 @@ All documentation follows these standards:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ✅ **Last Updated**: December 2025
|
## ✅ **Last Updated**: Based on live `misc/*` code verification
|
||||||
|
|
||||||
**Maintainers**: community-scripts team
|
**Maintainers**: community-scripts team
|
||||||
**License**: MIT
|
**License**: MIT
|
||||||
**Status**: All 9 libraries fully documented and standardized
|
**Status**: Canonical overviews aligned to live code; deeper generated subpages may still require occasional drift cleanup
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*This directory contains specialized documentation for specific components of the Proxmox Community Scripts project.*
|
_When documentation conflicts with the live shell implementation, prefer the files under `ProxmoxVE` / `ProxmoxVED` `misc/`._
|
||||||
|
|||||||
65
docs/pocketbase-bot.md
Normal file
65
docs/pocketbase-bot.md
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
## 🤖 PocketBase Bot — Command Reference
|
||||||
|
|
||||||
|
> Available to **org members only** (Contributors team).
|
||||||
|
> Trigger by posting a comment on any Issue or PR.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🔧 Field Updates
|
||||||
|
Simple key=value pairs. Multiple in one line.
|
||||||
|
```
|
||||||
|
/pocketbase <slug> field=value [field=value ...]
|
||||||
|
```
|
||||||
|
**Boolean fields** (`true`/`false`): `updateable` `privileged` `has_arm` `is_dev` `is_disabled` `is_deleted`
|
||||||
|
**Text fields**: `name` `description` `logo` `documentation` `website` `project_url` `github` `config_path` `disable_message` `deleted_message`
|
||||||
|
**Number**: `port`
|
||||||
|
**Nullable**: `default_user` `default_passwd` *(empty value = null: `default_passwd=`)*
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
```
|
||||||
|
/pocketbase homeassistant is_disabled=true disable_message="Broken upstream"
|
||||||
|
/pocketbase homeassistant documentation=https://www.home-assistant.io/docs
|
||||||
|
/pocketbase homeassistant is_dev=false
|
||||||
|
/pocketbase homeassistant default_passwd=
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 📝 set — HTML / Multiline / Special Characters
|
||||||
|
Use a code block for values that contain HTML, links, quotes or newlines.
|
||||||
|
````
|
||||||
|
/pocketbase <slug> set <field>
|
||||||
|
```
|
||||||
|
Your content here — HTML tags, links, quotes, all fine
|
||||||
|
```
|
||||||
|
````
|
||||||
|
**Allowed fields:** `name` `description` `logo` `documentation` `website` `project_url` `github` `config_path` `disable_message` `deleted_message`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🗒️ Notes
|
||||||
|
```
|
||||||
|
/pocketbase <slug> note list
|
||||||
|
/pocketbase <slug> note add <type> "<text>"
|
||||||
|
/pocketbase <slug> note edit <type> "<old text>" "<new text>"
|
||||||
|
/pocketbase <slug> note remove <type> "<text>"
|
||||||
|
```
|
||||||
|
Note types come from `z_ref_note_types` in PocketBase (e.g. `info`, `warning`).
|
||||||
|
If text doesn't match exactly, the bot lists all current notes automatically.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ⚙️ Install Method Resources
|
||||||
|
```
|
||||||
|
/pocketbase <slug> method list
|
||||||
|
/pocketbase <slug> method <type> hdd=10
|
||||||
|
/pocketbase <slug> method <type> cpu=4 ram=2048 hdd=20
|
||||||
|
```
|
||||||
|
`<type>` matches the install method type name (e.g. `default`, `alpine`). Use `method list` to see available types and current values. `ram` = MB, `hdd` = GB.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 💡 Tips
|
||||||
|
- The bot reacts with 👀 when it picks up the command, ✅ on success, 👎 on error
|
||||||
|
- On any error, a comment explains what went wrong
|
||||||
|
- `note edit` / `note remove` show the current note list if the text doesn't match
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: cobalt (cobaltgit)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
|
||||||
# Source: https://ntfy.sh/
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
msg_info "Installing ntfy"
|
|
||||||
$STD apk add --no-cache ntfy ntfy-openrc libcap
|
|
||||||
sed -i '/^listen-http/s/^\(.*\)$/#\1\n/' /etc/ntfy/server.yml
|
|
||||||
setcap 'cap_net_bind_service=+ep' /usr/bin/ntfy
|
|
||||||
$STD rc-update add ntfy default
|
|
||||||
$STD service ntfy start
|
|
||||||
msg_ok "Installed ntfy"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: Slaviša Arežina (tremor021)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
|
||||||
# Source: https://wakapi.dev/ | https://github.com/muety/wakapi
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
msg_info "Installing Dependencies"
|
|
||||||
$STD apk add --no-cache \
|
|
||||||
ca-certificates \
|
|
||||||
tzdata
|
|
||||||
$STD update-ca-certificates
|
|
||||||
$STD apk add --no-cache go --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community
|
|
||||||
msg_ok "Installed Dependencies"
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "wakapi" "muety/wakapi" "tarball"
|
|
||||||
|
|
||||||
msg_info "Configuring Wakapi"
|
|
||||||
LOCAL_IP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1)
|
|
||||||
cd /opt/wakapi
|
|
||||||
$STD go mod download
|
|
||||||
$STD go build -o wakapi
|
|
||||||
cp config.default.yml config.yml
|
|
||||||
sed -i 's/listen_ipv6: ::1/listen_ipv6: "-"/g' config.yml
|
|
||||||
sed -i 's/listen_ipv4: 127.0.0.1/listen_ipv4: "0.0.0.0"/g' config.yml
|
|
||||||
sed -i "s/public_url: http:\/\/localhost:3000/public_url: http:\/\/$LOCAL_IP:3000/g" config.yml
|
|
||||||
msg_ok "Configured Wakapi"
|
|
||||||
|
|
||||||
msg_info "Enabling Wakapi Service"
|
|
||||||
cat <<EOF >/etc/init.d/wakapi
|
|
||||||
#!/sbin/openrc-run
|
|
||||||
description="Wakapi Service"
|
|
||||||
directory="/opt/wakapi"
|
|
||||||
command="/opt/wakapi/wakapi"
|
|
||||||
command_args="-config config.yml"
|
|
||||||
command_background="true"
|
|
||||||
command_user="root"
|
|
||||||
pidfile="/var/run/wakapi.pid"
|
|
||||||
|
|
||||||
depend() {
|
|
||||||
use net
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
chmod +x /etc/init.d/wakapi
|
|
||||||
$STD rc-update add wakapi default
|
|
||||||
msg_ok "Enabled Wakapi Service"
|
|
||||||
|
|
||||||
msg_info "Starting Wakapi"
|
|
||||||
$STD rc-service wakapi start
|
|
||||||
msg_ok "Started Wakapi"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: Nícolas Pastorello (opastorello)
|
# Author: Nícolas Pastorello (opastorello)
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://github.com/jumpserver/jumpserver
|
# Source: https://github.com/jumpserver/jumpserver
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 tteck
|
# Copyright (c) 2021-2026 tteck
|
||||||
# Author: tteck (tteckster)
|
# Author: tteck (tteckster)
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://petio.tv/
|
# Source: https://petio.tv/
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 tteck
|
# Copyright (c) 2021-2026 tteck
|
||||||
# Author: tteck (tteckster)
|
# Author: tteck (tteckster)
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://nginxproxymanager.com/
|
# Source: https://nginxproxymanager.com/
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: CrazyWolf13
|
# Author: CrazyWolf13
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://github.com/arunavo4/gitea-mirror
|
# Source: https://github.com/arunavo4/gitea-mirror
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: MickLesk (Canbiz)
|
# Author: MickLesk (Canbiz)
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://github.com/agersant/polaris
|
# Source: https://github.com/agersant/polaris
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: MickLesk (CanbiZ)
|
# Author: MickLesk (CanbiZ)
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
color
|
color
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: SunFlowerOwl
|
# Author: SunFlowerOwl
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://github.com/haugene/docker-transmission-openvpn
|
# Source: https://github.com/haugene/docker-transmission-openvpn
|
||||||
|
|
||||||
# Import Functions und Setup
|
# Import Functions und Setup
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 tteck
|
# Copyright (c) 2021-2026 tteck
|
||||||
# Author: tteck (tteckster)
|
# Author: tteck (tteckster)
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://github.com/dani-garcia/vaultwarden
|
# Source: https://github.com/dani-garcia/vaultwarden
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: MickLesk (Canbiz)
|
# Author: MickLesk (Canbiz)
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://vikunja.io/
|
# Source: https://vikunja.io/
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
|||||||
88
install/degoog-install.sh
Normal file
88
install/degoog-install.sh
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
|
# Author: vhsdream
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
|
# Source: https://github.com/fccview/degoog
|
||||||
|
|
||||||
|
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 \
|
||||||
|
git \
|
||||||
|
unzip
|
||||||
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
|
msg_info "Installing Bun"
|
||||||
|
export BUN_INSTALL="/root/.bun"
|
||||||
|
curl -fsSL https://bun.sh/install | $STD bash
|
||||||
|
ln -sf /root/.bun/bin/bun /usr/local/bin/bun
|
||||||
|
ln -sf /root/.bun/bin/bunx /usr/local/bin/bunx
|
||||||
|
msg_ok "Installed Bun"
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_release "degoog" "fccview/degoog" "prebuild" "latest" "/opt/degoog" "degoog_*_prebuild.tar.gz"
|
||||||
|
|
||||||
|
msg_info "Setting up degoog"
|
||||||
|
mkdir -p /opt/degoog/data/{engines,plugins,themes,store}
|
||||||
|
|
||||||
|
cat <<EOF >/opt/degoog/.env
|
||||||
|
DEGOOG_PORT=4444
|
||||||
|
DEGOOG_ENGINES_DIR=/opt/degoog/data/engines
|
||||||
|
DEGOOG_PLUGINS_DIR=/opt/degoog/data/plugins
|
||||||
|
DEGOOG_THEMES_DIR=/opt/degoog/data/themes
|
||||||
|
DEGOOG_ALIASES_FILE=/opt/degoog/data/aliases.json
|
||||||
|
DEGOOG_PLUGIN_SETTINGS_FILE=/opt/degoog/data/plugin-settings.json
|
||||||
|
# DEGOOG_SETTINGS_PASSWORDS=changeme
|
||||||
|
# DEGOOG_PUBLIC_INSTANCE=false
|
||||||
|
# LOGGER=debug
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if [[ ! -f /opt/degoog/data/aliases.json ]]; then
|
||||||
|
cat <<EOF >/opt/degoog/data/aliases.json
|
||||||
|
{}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f /opt/degoog/data/plugin-settings.json ]]; then
|
||||||
|
cat <<EOF >/opt/degoog/data/plugin-settings.json
|
||||||
|
{}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f /opt/degoog/data/repos.json ]]; then
|
||||||
|
cat <<EOF >/opt/degoog/data/repos.json
|
||||||
|
[]
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
msg_ok "Set up degoog"
|
||||||
|
|
||||||
|
msg_info "Creating Service"
|
||||||
|
cat <<EOF >/etc/systemd/system/degoog.service
|
||||||
|
[Unit]
|
||||||
|
Description=degoog
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
WorkingDirectory=/opt/degoog
|
||||||
|
EnvironmentFile=/opt/degoog/.env
|
||||||
|
ExecStart=/usr/local/bin/bun run src/server/index.ts
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl enable -q --now degoog
|
||||||
|
msg_ok "Created Service"
|
||||||
|
|
||||||
|
motd_ssh
|
||||||
|
customize
|
||||||
|
cleanup_lxc
|
||||||
@@ -55,18 +55,17 @@ DISCOURSE_DB_NAME=discourse
|
|||||||
DISCOURSE_DB_USERNAME=discourse
|
DISCOURSE_DB_USERNAME=discourse
|
||||||
DISCOURSE_DB_PASSWORD=${DISCOURSE_DB_PASS}
|
DISCOURSE_DB_PASSWORD=${DISCOURSE_DB_PASS}
|
||||||
DISCOURSE_REDIS_URL=redis://localhost:6379
|
DISCOURSE_REDIS_URL=redis://localhost:6379
|
||||||
DISCOURSE_DEVELOPER_EMAILS=admin@local
|
DISCOURSE_DEVELOPER_EMAILS=admin@discourse.local
|
||||||
DISCOURSE_HOSTNAME=${LOCAL_IP}
|
DISCOURSE_HOSTNAME=${LOCAL_IP}
|
||||||
DISCOURSE_SMTP_ADDRESS=localhost
|
DISCOURSE_SMTP_ADDRESS=localhost
|
||||||
DISCOURSE_SMTP_PORT=25
|
DISCOURSE_SMTP_PORT=25
|
||||||
DISCOURSE_SMTP_AUTHENTICATION=none
|
DISCOURSE_SMTP_AUTHENTICATION=none
|
||||||
DISCOURSE_NOTIFICATION_EMAIL=noreply@${LOCAL_IP}
|
DISCOURSE_NOTIFICATION_EMAIL=noreply@${LOCAL_IP}
|
||||||
|
DISCOURSE_SKIP_NEW_ACCOUNT_EMAIL=true
|
||||||
APP_ROOT=/opt/discourse
|
APP_ROOT=/opt/discourse
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
mkdir -p /opt/discourse/tmp/sockets /opt/discourse/tmp/pids /opt/discourse/log
|
mkdir -p /opt/discourse/tmp/sockets /opt/discourse/tmp/pids /opt/discourse/log
|
||||||
sed -i 's|bind "unix://#{APP_ROOT}/tmp/sockets/puma.sock"|bind "tcp://127.0.0.1:3000"|' /opt/discourse/config/puma.rb
|
|
||||||
sed -i 's|stdout_redirect.*|# logging handled by systemd|' /opt/discourse/config/puma.rb
|
|
||||||
chown -R root:root /opt/discourse
|
chown -R root:root /opt/discourse
|
||||||
chmod 755 /opt/discourse
|
chmod 755 /opt/discourse
|
||||||
msg_ok "Configured Discourse"
|
msg_ok "Configured Discourse"
|
||||||
@@ -94,8 +93,32 @@ set -a
|
|||||||
source /opt/discourse/.env
|
source /opt/discourse/.env
|
||||||
set +a
|
set +a
|
||||||
$STD bundle exec rails db:migrate
|
$STD bundle exec rails db:migrate
|
||||||
|
$STD bundle exec rails db:seed
|
||||||
msg_ok "Set Up Database"
|
msg_ok "Set Up Database"
|
||||||
|
|
||||||
|
msg_info "Creating Admin Account"
|
||||||
|
ADMIN_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c16)
|
||||||
|
$STD bundle exec rails runner "
|
||||||
|
user = User.new(email: 'admin@discourse.local', username: 'admin', password: '${ADMIN_PASS}')
|
||||||
|
user.active = true
|
||||||
|
user.admin = true
|
||||||
|
user.approved = true
|
||||||
|
user.save!(validate: false)
|
||||||
|
user.activate
|
||||||
|
user.grant_admin!
|
||||||
|
user.change_trust_level!(TrustLevel[4])
|
||||||
|
SiteSetting.has_login_hint = false
|
||||||
|
SiteSetting.wizard_enabled = false
|
||||||
|
"
|
||||||
|
{
|
||||||
|
echo "Discourse Credentials"
|
||||||
|
echo "Admin Username: admin"
|
||||||
|
echo "Admin Email: admin@discourse.local"
|
||||||
|
echo "Admin Password: ${ADMIN_PASS}"
|
||||||
|
echo "Database Password: ${DISCOURSE_DB_PASS}"
|
||||||
|
} >~/discourse.creds
|
||||||
|
msg_ok "Created Admin Account"
|
||||||
|
|
||||||
msg_info "Building Discourse Assets"
|
msg_info "Building Discourse Assets"
|
||||||
cd /opt/discourse
|
cd /opt/discourse
|
||||||
export PATH="$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH"
|
export PATH="$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH"
|
||||||
@@ -119,7 +142,7 @@ User=root
|
|||||||
WorkingDirectory=/opt/discourse
|
WorkingDirectory=/opt/discourse
|
||||||
EnvironmentFile=/opt/discourse/.env
|
EnvironmentFile=/opt/discourse/.env
|
||||||
Environment=PATH=/root/.rbenv/shims:/root/.rbenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
Environment=PATH=/root/.rbenv/shims:/root/.rbenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
ExecStart=/root/.rbenv/shims/bundle exec puma -w 2
|
ExecStart=/root/.rbenv/shims/bundle exec pitchfork -c config/pitchfork.conf.rb
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|
||||||
@@ -138,7 +161,7 @@ User=root
|
|||||||
WorkingDirectory=/opt/discourse
|
WorkingDirectory=/opt/discourse
|
||||||
EnvironmentFile=/opt/discourse/.env
|
EnvironmentFile=/opt/discourse/.env
|
||||||
Environment=PATH=/root/.rbenv/shims:/root/.rbenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
Environment=PATH=/root/.rbenv/shims:/root/.rbenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
ExecStart=/root/.rbenv/shims/bundle exec sidekiq -q critical -q low -q default
|
ExecStart=/root/.rbenv/shims/bundle exec sidekiq -q critical -q default -q low -q ultra_low
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|
||||||
@@ -153,12 +176,27 @@ cat <<EOF >/etc/nginx/sites-available/discourse
|
|||||||
server {
|
server {
|
||||||
listen 80 default_server;
|
listen 80 default_server;
|
||||||
server_name _;
|
server_name _;
|
||||||
|
root /opt/discourse/public;
|
||||||
|
|
||||||
client_max_body_size 100M;
|
client_max_body_size 100M;
|
||||||
proxy_busy_buffers_size 512k;
|
proxy_busy_buffers_size 512k;
|
||||||
proxy_buffers 4 512k;
|
proxy_buffers 4 512k;
|
||||||
|
|
||||||
|
location /assets/ {
|
||||||
|
gzip_static on;
|
||||||
|
expires max;
|
||||||
|
add_header Cache-Control public,immutable;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /uploads/ {
|
||||||
|
expires 1h;
|
||||||
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
|
try_files \$uri @discourse;
|
||||||
|
}
|
||||||
|
|
||||||
|
location @discourse {
|
||||||
proxy_pass http://127.0.0.1:3000;
|
proxy_pass http://127.0.0.1:3000;
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Upgrade \$http_upgrade;
|
proxy_set_header Upgrade \$http_upgrade;
|
||||||
@@ -167,6 +205,7 @@ server {
|
|||||||
proxy_set_header X-Real-IP \$remote_addr;
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||||
|
proxy_set_header X-Accel-Mapping /opt/discourse/public/=/downloads/;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
@@ -175,6 +214,7 @@ ln -sf /etc/nginx/sites-available/discourse /etc/nginx/sites-enabled/discourse
|
|||||||
rm -f /etc/nginx/sites-enabled/default
|
rm -f /etc/nginx/sites-enabled/default
|
||||||
$STD nginx -t
|
$STD nginx -t
|
||||||
$STD systemctl enable --now nginx
|
$STD systemctl enable --now nginx
|
||||||
|
$STD systemctl reload nginx
|
||||||
msg_ok "Configured Nginx"
|
msg_ok "Configured Nginx"
|
||||||
|
|
||||||
motd_ssh
|
motd_ssh
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: MickLesk
|
# Author: MickLesk
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://github.com/ente-io/ente
|
# Source: https://github.com/ente-io/ente
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
@@ -29,7 +29,6 @@ NODE_VERSION="24" NODE_MODULE="yarn" setup_nodejs
|
|||||||
RUST_CRATES="wasm-pack" setup_rust
|
RUST_CRATES="wasm-pack" setup_rust
|
||||||
$STD rustup target add wasm32-unknown-unknown
|
$STD rustup target add wasm32-unknown-unknown
|
||||||
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "ente-server" "ente-io/ente" "tarball" "latest" "/opt/ente"
|
fetch_and_deploy_gh_release "ente-server" "ente-io/ente" "tarball" "latest" "/opt/ente"
|
||||||
|
|
||||||
msg_info "Building Ente CLI"
|
msg_info "Building Ente CLI"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: Simon Friedrich
|
# Author: Simon Friedrich
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://forgejo.org/
|
# Source: https://forgejo.org/
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: Matthew Stern (sternma) | MickLesk (CanbiZ)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/dmunozv04/iSponsorBlockTV
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "isponsorblocktv" "dmunozv04/iSponsorBlockTV" "singlefile" "latest" "/opt/isponsorblocktv" "iSponsorBlockTV-*-linux"
|
|
||||||
|
|
||||||
msg_info "Setting up iSponsorBlockTV"
|
|
||||||
install -d /var/lib/isponsorblocktv
|
|
||||||
msg_ok "Set up iSponsorBlockTV"
|
|
||||||
|
|
||||||
msg_info "Creating Service"
|
|
||||||
cat <<EOF >/etc/systemd/system/isponsorblocktv.service
|
|
||||||
[Unit]
|
|
||||||
Description=iSponsorBlockTV
|
|
||||||
After=network-online.target
|
|
||||||
Wants=network-online.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=root
|
|
||||||
Group=root
|
|
||||||
Environment=iSPBTV_data_dir=/var/lib/isponsorblocktv
|
|
||||||
ExecStart=/opt/isponsorblocktv/isponsorblocktv
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
systemctl enable -q isponsorblocktv
|
|
||||||
msg_ok "Created Service"
|
|
||||||
|
|
||||||
msg_info "Creating CLI wrapper"
|
|
||||||
cat <<EOF >/usr/local/bin/iSponsorBlockTV
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
export iSPBTV_data_dir="/var/lib/isponsorblocktv"
|
|
||||||
|
|
||||||
set +e
|
|
||||||
/opt/isponsorblocktv/isponsorblocktv "$@"
|
|
||||||
status=$?
|
|
||||||
set -e
|
|
||||||
|
|
||||||
case "${1:-}" in
|
|
||||||
setup|setup-cli)
|
|
||||||
systemctl restart isponsorblocktv >/dev/null 2>&1 || true
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
exit $status
|
|
||||||
EOF
|
|
||||||
chmod +x /usr/local/bin/iSponsorBlockTV
|
|
||||||
ln -sf /usr/local/bin/iSponsorBlockTV /usr/bin/iSponsorBlockTV
|
|
||||||
msg_ok "Created CLI wrapper"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
cleanup_lxc
|
|
||||||
139
install/librechat-install.sh
Normal file
139
install/librechat-install.sh
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
|
# Author: MickLesk (CanbiZ)
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
|
# Source: https://github.com/danny-avila/LibreChat
|
||||||
|
|
||||||
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
color
|
||||||
|
verb_ip6
|
||||||
|
catch_errors
|
||||||
|
setting_up_container
|
||||||
|
network_check
|
||||||
|
update_os
|
||||||
|
|
||||||
|
MONGO_VERSION="8.0" setup_mongodb
|
||||||
|
setup_meilisearch
|
||||||
|
PG_VERSION="17" PG_MODULES="pgvector" setup_postgresql
|
||||||
|
PG_DB_NAME="ragapi" PG_DB_USER="ragapi" PG_DB_EXTENSIONS="vector" setup_postgresql_db
|
||||||
|
NODE_VERSION="22" setup_nodejs
|
||||||
|
UV_PYTHON="3.12" setup_uv
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_tag "librechat" "danny-avila/LibreChat"
|
||||||
|
fetch_and_deploy_gh_release "rag-api" "danny-avila/rag_api" "tarball"
|
||||||
|
|
||||||
|
msg_info "Installing LibreChat Dependencies"
|
||||||
|
cd /opt/librechat
|
||||||
|
$STD npm ci
|
||||||
|
msg_ok "Installed LibreChat Dependencies"
|
||||||
|
|
||||||
|
msg_info "Building Frontend"
|
||||||
|
$STD npm run frontend
|
||||||
|
$STD npm prune --production
|
||||||
|
$STD npm cache clean --force
|
||||||
|
msg_ok "Built Frontend"
|
||||||
|
|
||||||
|
msg_info "Installing RAG API Dependencies"
|
||||||
|
cd /opt/rag-api
|
||||||
|
$STD uv venv --python 3.12 --seed .venv
|
||||||
|
$STD .venv/bin/pip install -r requirements.lite.txt
|
||||||
|
mkdir -p /opt/rag-api/uploads
|
||||||
|
msg_ok "Installed RAG API Dependencies"
|
||||||
|
|
||||||
|
msg_info "Configuring LibreChat"
|
||||||
|
JWT_SECRET=$(openssl rand -hex 32)
|
||||||
|
JWT_REFRESH_SECRET=$(openssl rand -hex 32)
|
||||||
|
CREDS_KEY=$(openssl rand -hex 32)
|
||||||
|
CREDS_IV=$(openssl rand -hex 16)
|
||||||
|
cat <<EOF >/opt/librechat/.env
|
||||||
|
HOST=0.0.0.0
|
||||||
|
PORT=3080
|
||||||
|
MONGO_URI=mongodb://127.0.0.1:27017/LibreChat
|
||||||
|
DOMAIN_CLIENT=http://${LOCAL_IP}:3080
|
||||||
|
DOMAIN_SERVER=http://${LOCAL_IP}:3080
|
||||||
|
NO_INDEX=true
|
||||||
|
TRUST_PROXY=1
|
||||||
|
JWT_SECRET=${JWT_SECRET}
|
||||||
|
JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET}
|
||||||
|
SESSION_EXPIRY=1000 * 60 * 15
|
||||||
|
REFRESH_TOKEN_EXPIRY=(1000 * 60 * 60 * 24) * 7
|
||||||
|
CREDS_KEY=${CREDS_KEY}
|
||||||
|
CREDS_IV=${CREDS_IV}
|
||||||
|
ALLOW_EMAIL_LOGIN=true
|
||||||
|
ALLOW_REGISTRATION=true
|
||||||
|
ALLOW_SOCIAL_LOGIN=false
|
||||||
|
ALLOW_SOCIAL_REGISTRATION=false
|
||||||
|
ALLOW_PASSWORD_RESET=false
|
||||||
|
ALLOW_UNVERIFIED_EMAIL_LOGIN=true
|
||||||
|
SEARCH=true
|
||||||
|
MEILI_NO_ANALYTICS=true
|
||||||
|
MEILI_HOST=http://127.0.0.1:7700
|
||||||
|
MEILI_MASTER_KEY=${MEILISEARCH_MASTER_KEY}
|
||||||
|
RAG_PORT=8000
|
||||||
|
RAG_API_URL=http://127.0.0.1:8000
|
||||||
|
APP_TITLE=LibreChat
|
||||||
|
ENDPOINTS=openAI,agents,assistants,anthropic,google
|
||||||
|
# OPENAI_API_KEY=your-key-here
|
||||||
|
# OPENAI_MODELS=
|
||||||
|
# ANTHROPIC_API_KEY=your-key-here
|
||||||
|
# GOOGLE_KEY=your-key-here
|
||||||
|
EOF
|
||||||
|
msg_ok "Configured LibreChat"
|
||||||
|
|
||||||
|
msg_info "Configuring RAG API"
|
||||||
|
cat <<EOF >/opt/rag-api/.env
|
||||||
|
VECTOR_DB_TYPE=pgvector
|
||||||
|
DB_HOST=127.0.0.1
|
||||||
|
DB_PORT=5432
|
||||||
|
POSTGRES_DB=${PG_DB_NAME}
|
||||||
|
POSTGRES_USER=${PG_DB_USER}
|
||||||
|
POSTGRES_PASSWORD=${PG_DB_PASS}
|
||||||
|
RAG_HOST=0.0.0.0
|
||||||
|
RAG_PORT=8000
|
||||||
|
JWT_SECRET=${JWT_SECRET}
|
||||||
|
RAG_UPLOAD_DIR=/opt/rag-api/uploads/
|
||||||
|
EOF
|
||||||
|
msg_ok "Configured RAG API"
|
||||||
|
|
||||||
|
msg_info "Creating Services"
|
||||||
|
cat <<EOF >/etc/systemd/system/librechat.service
|
||||||
|
[Unit]
|
||||||
|
Description=LibreChat
|
||||||
|
After=network.target mongod.service meilisearch.service rag-api.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
WorkingDirectory=/opt/librechat
|
||||||
|
EnvironmentFile=/opt/librechat/.env
|
||||||
|
ExecStart=/usr/bin/npm run backend
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
cat <<EOF >/etc/systemd/system/rag-api.service
|
||||||
|
[Unit]
|
||||||
|
Description=LibreChat RAG API
|
||||||
|
After=network.target postgresql.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
WorkingDirectory=/opt/rag-api
|
||||||
|
EnvironmentFile=/opt/rag-api/.env
|
||||||
|
ExecStart=/opt/rag-api/.venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl enable -q --now rag-api librechat
|
||||||
|
msg_ok "Created Services"
|
||||||
|
|
||||||
|
motd_ssh
|
||||||
|
customize
|
||||||
|
cleanup_lxc
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Copyright (c) 2021-2025 minthcm
|
# Copyright (c) 2021-2025 minthcm
|
||||||
# Author: MintHCM
|
# Author: MintHCM
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://github.com/minthcm/minthcm
|
# Source: https://github.com/minthcm/minthcm
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ PHP_VERSION="8.2"
|
|||||||
PHP_APACHE="YES" PHP_MODULE="mysql,redis" PHP_FPM="YES" setup_php
|
PHP_APACHE="YES" PHP_MODULE="mysql,redis" PHP_FPM="YES" setup_php
|
||||||
setup_composer
|
setup_composer
|
||||||
setup_mariadb
|
setup_mariadb
|
||||||
$STD mariadb -u root -e "SET GLOBAL sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'";
|
$STD mariadb -u root -e "SET GLOBAL sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'"
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "MintHCM" "minthcm/minthcm" "tarball" "latest" "/var/www/MintHCM"
|
fetch_and_deploy_gh_release "MintHCM" "minthcm/minthcm" "tarball" "latest" "/var/www/MintHCM"
|
||||||
|
|
||||||
|
|||||||
102
install/netboot.xyz-install.sh
Normal file
102
install/netboot.xyz-install.sh
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
|
# Author: Michel Roegl-Brunner (michelroegl-brunner)
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
|
# Source: https://netboot.xyz
|
||||||
|
|
||||||
|
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 \
|
||||||
|
tftpd-hpa
|
||||||
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_release "netboot-xyz" "netbootxyz/netboot.xyz" "prebuild" "latest" "/var/www/html" "menus.tar.gz"
|
||||||
|
|
||||||
|
# x86_64 UEFI bootloaders
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-efi" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-efi-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.efi.dsk"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-snp" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-snp.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-snp-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-snp.efi.dsk"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-snponly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-snponly.efi"
|
||||||
|
# x86_64 metal (code-signed) UEFI bootloaders
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal.efi.dsk"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-snp" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-snp.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-snp-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-snp.efi.dsk"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-snponly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-snponly.efi"
|
||||||
|
# x86_64 BIOS/Legacy bootloaders
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-kpxe" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.kpxe"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-undionly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-undionly.kpxe"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-kpxe" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal.kpxe"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-lkrn" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.lkrn"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-linux-bin" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-linux.bin"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.dsk"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-pdsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.pdsk"
|
||||||
|
# ARM64 bootloaders
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64-snp" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64-snp.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64-snponly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64-snponly.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-arm64" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-arm64.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-arm64-snp" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-arm64-snp.efi"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-arm64-snponly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-arm64-snponly.efi"
|
||||||
|
# ISO and IMG images (for virtual/physical media creation)
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-iso" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.iso"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-img" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.img"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64-iso" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64.iso"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64-img" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64.img"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-multiarch-iso" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-multiarch.iso"
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-multiarch-img" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-multiarch.img"
|
||||||
|
# SHA256 checksums
|
||||||
|
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-checksums" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-sha256-checksums.txt"
|
||||||
|
|
||||||
|
msg_info "Configuring Webserver"
|
||||||
|
rm -f /etc/nginx/sites-enabled/default
|
||||||
|
cat <<'EOF' >/etc/nginx/sites-available/netboot-xyz
|
||||||
|
server {
|
||||||
|
listen 80 default_server;
|
||||||
|
listen [::]:80 default_server;
|
||||||
|
|
||||||
|
root /var/www/html;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
autoindex on;
|
||||||
|
add_header Access-Control-Allow-Origin "*";
|
||||||
|
add_header Access-Control-Allow-Headers "Content-Type";
|
||||||
|
}
|
||||||
|
|
||||||
|
# The index.html from menus.tar.gz links bootloaders under /ipxe/ —
|
||||||
|
# serve them from the same root directory via alias
|
||||||
|
location /ipxe/ {
|
||||||
|
alias /var/www/html/;
|
||||||
|
autoindex on;
|
||||||
|
add_header Access-Control-Allow-Origin "*";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
ln -sf /etc/nginx/sites-available/netboot-xyz /etc/nginx/sites-enabled/netboot-xyz
|
||||||
|
$STD systemctl reload nginx
|
||||||
|
msg_ok "Configured Webserver"
|
||||||
|
|
||||||
|
msg_info "Configuring TFTP Server"
|
||||||
|
cat <<EOF >/etc/default/tftpd-hpa
|
||||||
|
TFTP_USERNAME="tftp"
|
||||||
|
TFTP_DIRECTORY="/var/www/html"
|
||||||
|
TFTP_ADDRESS="0.0.0.0:69"
|
||||||
|
TFTP_OPTIONS="--secure"
|
||||||
|
EOF
|
||||||
|
systemctl enable -q --now tftpd-hpa
|
||||||
|
msg_ok "Configured TFTP Server"
|
||||||
|
|
||||||
|
motd_ssh
|
||||||
|
customize
|
||||||
|
cleanup_lxc
|
||||||
190
install/nginxproxymanager-install.sh
Normal file
190
install/nginxproxymanager-install.sh
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
|
# Author: tteck (tteckster) | Co-Author: CrazyWolf13
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://nginxproxymanager.com/ | Github: https://github.com/NginxProxyManager/nginx-proxy-manager
|
||||||
|
|
||||||
|
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 \
|
||||||
|
apache2-utils \
|
||||||
|
logrotate \
|
||||||
|
build-essential \
|
||||||
|
libpcre3-dev \
|
||||||
|
libssl-dev \
|
||||||
|
zlib1g-dev \
|
||||||
|
git \
|
||||||
|
python3 \
|
||||||
|
python3-dev \
|
||||||
|
python3-pip \
|
||||||
|
python3-venv \
|
||||||
|
python3-cffi
|
||||||
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
|
msg_info "Setting up Certbot"
|
||||||
|
$STD python3 -m venv /opt/certbot
|
||||||
|
$STD /opt/certbot/bin/pip install --upgrade pip setuptools wheel
|
||||||
|
$STD /opt/certbot/bin/pip install certbot certbot-dns-cloudflare
|
||||||
|
ln -sf /opt/certbot/bin/certbot /usr/local/bin/certbot
|
||||||
|
msg_ok "Set up Certbot"
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_release "openresty" "openresty/openresty" "prebuild" "latest" "/opt/openresty" "openresty-*.tar.gz"
|
||||||
|
|
||||||
|
msg_info "Building OpenResty"
|
||||||
|
cd /opt/openresty
|
||||||
|
$STD ./configure \
|
||||||
|
--with-http_v2_module \
|
||||||
|
--with-http_realip_module \
|
||||||
|
--with-http_stub_status_module \
|
||||||
|
--with-http_ssl_module \
|
||||||
|
--with-http_sub_module \
|
||||||
|
--with-http_auth_request_module \
|
||||||
|
--with-pcre-jit \
|
||||||
|
--with-stream \
|
||||||
|
--with-stream_ssl_module
|
||||||
|
$STD make -j"$(nproc)"
|
||||||
|
$STD make install
|
||||||
|
rm -rf /opt/openresty
|
||||||
|
|
||||||
|
cat <<'EOF' >/lib/systemd/system/openresty.service
|
||||||
|
[Unit]
|
||||||
|
Description=The OpenResty Application Platform
|
||||||
|
After=syslog.target network-online.target remote-fs.target nss-lookup.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStartPre=/usr/local/openresty/nginx/sbin/nginx -t
|
||||||
|
ExecStart=/usr/local/openresty/nginx/sbin/nginx -g 'daemon off;'
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
msg_ok "Built OpenResty"
|
||||||
|
|
||||||
|
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
|
||||||
|
RELEASE=$(get_latest_github_release "NginxProxyManager/nginx-proxy-manager")
|
||||||
|
fetch_and_deploy_gh_release "nginxproxymanager" "NginxProxyManager/nginx-proxy-manager" "tarball" "v${RELEASE}"
|
||||||
|
|
||||||
|
msg_info "Setting up Environment"
|
||||||
|
ln -sf /usr/bin/python3 /usr/bin/python
|
||||||
|
ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx
|
||||||
|
ln -sf /usr/local/openresty/nginx/ /etc/nginx
|
||||||
|
sed -i "0,/\"version\": \"[^\"]*\"/s|\"version\": \"[^\"]*\"|\"version\": \"$RELEASE\"|" /opt/nginxproxymanager/backend/package.json
|
||||||
|
sed -i "0,/\"version\": \"[^\"]*\"/s|\"version\": \"[^\"]*\"|\"version\": \"$RELEASE\"|" /opt/nginxproxymanager/frontend/package.json
|
||||||
|
sed -i 's+^daemon+#daemon+g' /opt/nginxproxymanager/docker/rootfs/etc/nginx/nginx.conf
|
||||||
|
NGINX_CONFS=$(find /opt/nginxproxymanager -type f -name "*.conf")
|
||||||
|
for NGINX_CONF in $NGINX_CONFS; do
|
||||||
|
sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF"
|
||||||
|
done
|
||||||
|
|
||||||
|
mkdir -p /var/www/html /etc/nginx/logs
|
||||||
|
cp -r /opt/nginxproxymanager/docker/rootfs/var/www/html/* /var/www/html/
|
||||||
|
cp -r /opt/nginxproxymanager/docker/rootfs/etc/nginx/* /etc/nginx/
|
||||||
|
cp /opt/nginxproxymanager/docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini
|
||||||
|
cp /opt/nginxproxymanager/docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager
|
||||||
|
ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf
|
||||||
|
rm -f /etc/nginx/conf.d/dev.conf
|
||||||
|
|
||||||
|
mkdir -p /tmp/nginx/body \
|
||||||
|
/run/nginx \
|
||||||
|
/data/nginx \
|
||||||
|
/data/custom_ssl \
|
||||||
|
/data/logs \
|
||||||
|
/data/access \
|
||||||
|
/data/nginx/default_host \
|
||||||
|
/data/nginx/default_www \
|
||||||
|
/data/nginx/proxy_host \
|
||||||
|
/data/nginx/redirection_host \
|
||||||
|
/data/nginx/stream \
|
||||||
|
/data/nginx/dead_host \
|
||||||
|
/data/nginx/temp \
|
||||||
|
/var/lib/nginx/cache/public \
|
||||||
|
/var/lib/nginx/cache/private \
|
||||||
|
/var/cache/nginx/proxy_temp
|
||||||
|
|
||||||
|
chmod -R 777 /var/cache/nginx
|
||||||
|
chown root /tmp/nginx
|
||||||
|
|
||||||
|
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf
|
||||||
|
|
||||||
|
if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then
|
||||||
|
$STD openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p /app/frontend/images
|
||||||
|
cp -r /opt/nginxproxymanager/backend/* /app
|
||||||
|
msg_ok "Set up Environment"
|
||||||
|
|
||||||
|
msg_info "Building Frontend"
|
||||||
|
export NODE_OPTIONS="--max_old_space_size=2048 --openssl-legacy-provider"
|
||||||
|
cd /opt/nginxproxymanager/frontend
|
||||||
|
# Replace node-sass with sass in package.json before installation
|
||||||
|
sed -E -i 's/"node-sass" *: *"([^"]*)"/"sass": "\1"/g' package.json
|
||||||
|
$STD yarn install --network-timeout 600000
|
||||||
|
$STD yarn locale-compile
|
||||||
|
$STD yarn build
|
||||||
|
cp -r /opt/nginxproxymanager/frontend/dist/* /app/frontend
|
||||||
|
cp -r /opt/nginxproxymanager/frontend/public/images/* /app/frontend/images
|
||||||
|
msg_ok "Built Frontend"
|
||||||
|
|
||||||
|
msg_info "Initializing Backend"
|
||||||
|
rm -rf /app/config/default.json
|
||||||
|
if [ ! -f /app/config/production.json ]; then
|
||||||
|
cat <<'EOF' >/app/config/production.json
|
||||||
|
{
|
||||||
|
"database": {
|
||||||
|
"engine": "knex-native",
|
||||||
|
"knex": {
|
||||||
|
"client": "better-sqlite3",
|
||||||
|
"connection": {
|
||||||
|
"filename": "/data/database.sqlite"
|
||||||
|
},
|
||||||
|
"useNullAsDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
cd /app
|
||||||
|
$STD yarn install --network-timeout 600000
|
||||||
|
msg_ok "Initialized Backend"
|
||||||
|
|
||||||
|
msg_info "Creating Service"
|
||||||
|
cat <<'EOF' >/lib/systemd/system/npm.service
|
||||||
|
[Unit]
|
||||||
|
Description=Nginx Proxy Manager
|
||||||
|
After=network.target
|
||||||
|
Wants=openresty.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
Environment=NODE_ENV=production
|
||||||
|
ExecStartPre=-mkdir -p /tmp/nginx/body /data/letsencrypt-acme-challenge
|
||||||
|
ExecStart=/usr/bin/node index.js --abort_on_uncaught_exception --max_old_space_size=250
|
||||||
|
WorkingDirectory=/app
|
||||||
|
Restart=on-failure
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
msg_ok "Created Service"
|
||||||
|
|
||||||
|
msg_info "Starting Services"
|
||||||
|
sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf
|
||||||
|
sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/g;' /etc/logrotate.d/nginx-proxy-manager
|
||||||
|
systemctl enable -q --now openresty
|
||||||
|
systemctl enable -q --now npm
|
||||||
|
msg_ok "Started Services"
|
||||||
|
|
||||||
|
motd_ssh
|
||||||
|
customize
|
||||||
|
cleanup_lxc
|
||||||
@@ -110,7 +110,7 @@ export NAMESERVERS="1.1.1.1"
|
|||||||
export MEM_STORE_URI="redis://localhost:6379/1"
|
export MEM_STORE_URI="redis://localhost:6379/1"
|
||||||
export OPENID_PRIVATE_KEY_PATH="/opt/simplelogin/openid-rsa.key"
|
export OPENID_PRIVATE_KEY_PATH="/opt/simplelogin/openid-rsa.key"
|
||||||
export OPENID_PUBLIC_KEY_PATH="/opt/simplelogin/openid-rsa.pub"
|
export OPENID_PUBLIC_KEY_PATH="/opt/simplelogin/openid-rsa.pub"
|
||||||
$STD .venv/bin/flask db upgrade
|
$STD .venv/bin/alembic upgrade head
|
||||||
$STD .venv/bin/python init_app.py
|
$STD .venv/bin/python init_app.py
|
||||||
msg_ok "Configured SimpleLogin"
|
msg_ok "Configured SimpleLogin"
|
||||||
|
|
||||||
@@ -224,6 +224,7 @@ ln -sf /etc/nginx/sites-available/simplelogin.conf /etc/nginx/sites-enabled/
|
|||||||
rm -f /etc/nginx/sites-enabled/default
|
rm -f /etc/nginx/sites-enabled/default
|
||||||
$STD nginx -t
|
$STD nginx -t
|
||||||
$STD systemctl enable --now nginx
|
$STD systemctl enable --now nginx
|
||||||
|
$STD systemctl reload nginx
|
||||||
msg_ok "Configured Nginx"
|
msg_ok "Configured Nginx"
|
||||||
|
|
||||||
motd_ssh
|
motd_ssh
|
||||||
|
|||||||
@@ -22,27 +22,20 @@ setup_deb822_repo \
|
|||||||
|
|
||||||
msg_info "Installing step-ca and step-cli"
|
msg_info "Installing step-ca and step-cli"
|
||||||
$STD apt install -y step-ca step-cli
|
$STD apt install -y step-ca step-cli
|
||||||
msg_ok "Installed step-ca and step-cli"
|
|
||||||
|
|
||||||
msg_info "Define smallstep environment variables"
|
|
||||||
STEPHOME="/root/.step"
|
STEPHOME="/root/.step"
|
||||||
$STD export STEPPATH=/etc/step-ca
|
$STD export STEPPATH=/etc/step-ca
|
||||||
$STD export STEPHOME=$STEPHOME
|
$STD export STEPHOME=$STEPHOME
|
||||||
msg_ok "Defined smallstep environment variables"
|
|
||||||
|
|
||||||
msg_info "Add smallstep environment variables to /etc/profile"
|
|
||||||
$STD sed -i '1i export STEPPATH=/etc/step-ca' /etc/profile
|
$STD sed -i '1i export STEPPATH=/etc/step-ca' /etc/profile
|
||||||
$STD sed -i '1i export STEPHOME=/root/.step' /etc/profile
|
$STD sed -i '1i export STEPHOME=/root/.step' /etc/profile
|
||||||
msg_ok "Added smallstep environment variables to /etc/profile"
|
|
||||||
|
|
||||||
msg_info "Authorize step-ca binary with low port-binding capabilities"
|
|
||||||
$STD setcap CAP_NET_BIND_SERVICE=+eip $(which step-ca)
|
$STD setcap CAP_NET_BIND_SERVICE=+eip $(which step-ca)
|
||||||
msg_ok "Authorized low port-binding capabilities"
|
|
||||||
|
|
||||||
msg_info "Add a smallstep CA service user - Will only be used by systemd to manage the CA"
|
|
||||||
$STD useradd --user-group --system --home $(step path) --shell /bin/false step
|
$STD useradd --user-group --system --home $(step path) --shell /bin/false step
|
||||||
msg_ok "Created smallstep CA service user"
|
msg_ok "Installed step-ca and step-cli"
|
||||||
|
|
||||||
|
msg_info "Initializing step-ca"
|
||||||
DeploymentType="standalone"
|
DeploymentType="standalone"
|
||||||
FQDN=$(hostname -f)
|
FQDN=$(hostname -f)
|
||||||
DomainName=$(hostname -d)
|
DomainName=$(hostname -d)
|
||||||
@@ -77,7 +70,6 @@ X509DefaultDur=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "step
|
|||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
msg_info "Initializing step-ca"
|
|
||||||
EncryptionPwdDir="$(step path)/encryption"
|
EncryptionPwdDir="$(step path)/encryption"
|
||||||
PwdFile="$EncryptionPwdDir/ca.pwd"
|
PwdFile="$EncryptionPwdDir/ca.pwd"
|
||||||
ProvisionerPwdFile="$EncryptionPwdDir/provisioner.pwd"
|
ProvisionerPwdFile="$EncryptionPwdDir/provisioner.pwd"
|
||||||
@@ -100,25 +92,19 @@ $STD step ca init \
|
|||||||
ln -s "$PwdFile" "$(step path)/password.txt"
|
ln -s "$PwdFile" "$(step path)/password.txt"
|
||||||
chown -R step:step $(step path)
|
chown -R step:step $(step path)
|
||||||
chmod -R 700 $(step path)
|
chmod -R 700 $(step path)
|
||||||
msg_ok "Initialized step-ca"
|
|
||||||
|
|
||||||
msg_info "Add ACME provisioner"
|
|
||||||
$STD step ca provisioner add "$AcmeProvisioner" --type ACME --admin-name "$AcmeProvisioner"
|
$STD step ca provisioner add "$AcmeProvisioner" --type ACME --admin-name "$AcmeProvisioner"
|
||||||
msg_ok "Added ACME provisioner"
|
|
||||||
|
|
||||||
msg_info "Update provisioner configurations"
|
|
||||||
$STD step ca provisioner update "$PKIProvisioner" \
|
$STD step ca provisioner update "$PKIProvisioner" \
|
||||||
--x509-min-dur=$X509MinDur \
|
--x509-min-dur=$X509MinDur \
|
||||||
--x509-max-dur=$X509MaxDur \
|
--x509-max-dur=$X509MaxDur \
|
||||||
--x509-default-dur=$X509DefaultDur \
|
--x509-default-dur=$X509DefaultDur \
|
||||||
--allow-renewal-after-expiry
|
--allow-renewal-after-expiry
|
||||||
|
|
||||||
$STD step ca provisioner update "$AcmeProvisioner" \
|
$STD step ca provisioner update "$AcmeProvisioner" \
|
||||||
--x509-min-dur=$X509MinDur \
|
--x509-min-dur=$X509MinDur \
|
||||||
--x509-max-dur=$X509MaxDur \
|
--x509-max-dur=$X509MaxDur \
|
||||||
--x509-default-dur=$X509DefaultDur \
|
--x509-default-dur=$X509DefaultDur \
|
||||||
--allow-renewal-after-expiry
|
--allow-renewal-after-expiry
|
||||||
msg_ok "Updated provisioner configurations"
|
msg_ok "Initialized step-ca"
|
||||||
|
|
||||||
msg_info "Start step-ca as a Daemon"
|
msg_info "Start step-ca as a Daemon"
|
||||||
cat <<'EOF' >/etc/systemd/system/step-ca.service
|
cat <<'EOF' >/etc/systemd/system/step-ca.service
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
# Author: KernelSailor
|
# Author: KernelSailor
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://snowflake.torproject.org/
|
# Source: https://snowflake.torproject.org/
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
|
|||||||
$STD corepack enable
|
$STD corepack enable
|
||||||
$STD corepack prepare yarn@4.9.2 --activate
|
$STD corepack prepare yarn@4.9.2 --activate
|
||||||
$STD yarn install --immutable || $STD yarn install
|
$STD yarn install --immutable || $STD yarn install
|
||||||
export NODE_OPTIONS="--max-old-space-size=3072"
|
export NODE_OPTIONS="--max-old-space-size=4096"
|
||||||
$STD npx nx run twenty-server:build
|
$STD npx nx run twenty-server:build
|
||||||
$STD npx nx build twenty-front
|
$STD npx nx build twenty-front
|
||||||
cp -r /opt/twenty/packages/twenty-front/build /opt/twenty/packages/twenty-server/dist/front
|
cp -r /opt/twenty/packages/twenty-front/build /opt/twenty/packages/twenty-server/dist/front
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: MickLesk (CanbiZ)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/versity/versitygw
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "versitygw" "versity/versitygw" "binary"
|
|
||||||
|
|
||||||
msg_info "Configuring VersityGW"
|
|
||||||
mkdir -p /opt/versitygw-data
|
|
||||||
ACCESS_KEY=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-20)
|
|
||||||
SECRET_KEY=$(openssl rand -base64 36 | tr -dc 'a-zA-Z0-9' | cut -c1-40)
|
|
||||||
cat <<EOF >/etc/versitygw.d/gateway.conf
|
|
||||||
VGW_BACKEND=posix
|
|
||||||
VGW_BACKEND_ARG=/opt/versitygw-data
|
|
||||||
VGW_PORT=7070
|
|
||||||
ROOT_ACCESS_KEY_ID=${ACCESS_KEY}
|
|
||||||
ROOT_SECRET_ACCESS_KEY=${SECRET_KEY}
|
|
||||||
EOF
|
|
||||||
msg_ok "Configured VersityGW"
|
|
||||||
|
|
||||||
msg_info "Enabling Service"
|
|
||||||
systemctl enable -q --now versitygw@gateway
|
|
||||||
msg_ok "Enabled Service"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
cleanup_lxc
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: dave-yap (dave-yap) | Co-Author: remz1337
|
# Author: dave-yap (dave-yap) | Co-Author: remz1337
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# Source: https://zitadel.com/
|
# Source: https://zitadel.com/
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Alpine-Wakapi",
|
|
||||||
"slug": "alpine-wakapi",
|
|
||||||
"categories": [
|
|
||||||
9
|
|
||||||
],
|
|
||||||
"date_created": "2026-02-16",
|
|
||||||
"type": "ct",
|
|
||||||
"updateable": true,
|
|
||||||
"privileged": false,
|
|
||||||
"interface_port": 3000,
|
|
||||||
"documentation": "https://github.com/muety/wakapi/wiki",
|
|
||||||
"website": "https://wakapi.dev/",
|
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/wakapi.webp",
|
|
||||||
"config_path": "/opt/wakapi/config.yml",
|
|
||||||
"description": "Wakapi is an open-source tool that helps you keep track of the time you have spent coding on different projects in different programming languages and more. Ideal for statistics freaks and anyone else.",
|
|
||||||
"install_methods": [
|
|
||||||
{
|
|
||||||
"type": "default",
|
|
||||||
"script": "ct/alpine-wakapi.sh",
|
|
||||||
"resources": {
|
|
||||||
"cpu": 1,
|
|
||||||
"ram": 512,
|
|
||||||
"hdd": 4,
|
|
||||||
"os": "alpine",
|
|
||||||
"version": "3.23"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default_credentials": {
|
|
||||||
"username": null,
|
|
||||||
"password": null
|
|
||||||
},
|
|
||||||
"notes": [
|
|
||||||
{
|
|
||||||
"text": "The first user created will be an admin.",
|
|
||||||
"type": "warning"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
44
json/degoog.json
Normal file
44
json/degoog.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"name": "degoog",
|
||||||
|
"slug": "degoog",
|
||||||
|
"categories": [
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"date_created": "2026-03-20",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"interface_port": 4444,
|
||||||
|
"documentation": "https://fccview.github.io/degoog/",
|
||||||
|
"website": "https://github.com/fccview/degoog",
|
||||||
|
"logo": "https://raw.githubusercontent.com/fccview/degoog/main/src/public/images/degoog-logo.png",
|
||||||
|
"config_path": "/opt/degoog/.env",
|
||||||
|
"description": "Search aggregator that queries multiple engines and supports plugins, themes, and extension repositories.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/degoog.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 2,
|
||||||
|
"ram": 2048,
|
||||||
|
"hdd": 6,
|
||||||
|
"os": "Debian",
|
||||||
|
"version": "13"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": [
|
||||||
|
{
|
||||||
|
"text": "Project is currently marked beta upstream and not intended for production use yet.",
|
||||||
|
"type": "warning"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Add extension store repositories in Settings after first start (official repo: https://github.com/fccview/fccview-degoog-extensions).",
|
||||||
|
"type": "info"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -37,11 +37,11 @@
|
|||||||
"type": "warning"
|
"type": "warning"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "Admin user is created with username 'admin'. Set password in first login.",
|
"text": "Admin credentials are saved in `/root/discourse.creds` inside the container.",
|
||||||
"type": "info"
|
"type": "info"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "Configure SMTP settings in admin panel for email notifications.",
|
"text": "Configure SMTP settings in the admin panel (Admin > Settings > Email) for email notifications.",
|
||||||
"type": "info"
|
"type": "info"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "iSponsorBlockTV",
|
|
||||||
"slug": "isponsorblocktv",
|
|
||||||
"categories": [
|
|
||||||
13
|
|
||||||
],
|
|
||||||
"date_created": "2026-01-25",
|
|
||||||
"type": "ct",
|
|
||||||
"updateable": true,
|
|
||||||
"privileged": false,
|
|
||||||
"interface_port": null,
|
|
||||||
"documentation": "https://github.com/dmunozv04/iSponsorBlockTV/wiki",
|
|
||||||
"website": "https://github.com/dmunozv04/iSponsorBlockTV",
|
|
||||||
"logo": "https://raw.githubusercontent.com/ajayyy/SponsorBlock/master/public/icons/IconSponsorBlocker512px.png",
|
|
||||||
"config_path": "/var/lib/isponsorblocktv/config.json",
|
|
||||||
"description": "iSponsorBlockTV connects to YouTube TV clients and automatically skips SponsorBlock segments, mutes ads, and presses the Skip Ad button when available.",
|
|
||||||
"install_methods": [
|
|
||||||
{
|
|
||||||
"type": "default",
|
|
||||||
"script": "ct/isponsorblocktv.sh",
|
|
||||||
"resources": {
|
|
||||||
"cpu": 1,
|
|
||||||
"ram": 1024,
|
|
||||||
"hdd": 4,
|
|
||||||
"os": "debian",
|
|
||||||
"version": "13"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default_credentials": {
|
|
||||||
"username": null,
|
|
||||||
"password": null
|
|
||||||
},
|
|
||||||
"notes": [
|
|
||||||
{
|
|
||||||
"text": "No web UI; run `iSponsorBlockTV setup` inside the container to configure.",
|
|
||||||
"type": "info"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"text": "SSDP auto-discovery requires multicast on your bridge; manual pairing works without it.",
|
|
||||||
"type": "info"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
52
json/librechat.json
Normal file
52
json/librechat.json
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"name": "LibreChat",
|
||||||
|
"slug": "librechat",
|
||||||
|
"categories": [
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"date_created": "2026-03-18",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"interface_port": 3080,
|
||||||
|
"documentation": "https://www.librechat.ai/docs",
|
||||||
|
"website": "https://www.librechat.ai/",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/librechat.webp",
|
||||||
|
"config_path": "/opt/librechat/.env",
|
||||||
|
"description": "LibreChat is an open-source AI chat platform that supports multiple AI providers including OpenAI, Anthropic, Google, and more. It features conversation history, multi-modal support, custom endpoints, and a plugin system.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/librechat.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 4,
|
||||||
|
"ram": 6144,
|
||||||
|
"hdd": 20,
|
||||||
|
"os": "Debian",
|
||||||
|
"version": "13"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": [
|
||||||
|
{
|
||||||
|
"text": "Register the first account via the web interface — it becomes the admin account.",
|
||||||
|
"type": "info"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Add your AI provider API keys to /opt/librechat/.env (OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.) and restart librechat. OpenAI, Anthropic, Google and Agents endpoints are pre-enabled via ENDPOINTS.",
|
||||||
|
"type": "info"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "RAG API is included and running on port 8000. Set RAG_OPENAI_API_KEY in /opt/rag-api/.env to enable document Q&A.",
|
||||||
|
"type": "info"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "For local embeddings without an API key, set EMBEDDINGS_PROVIDER=ollama and OLLAMA_BASE_URL=http://<ollama-host>:11434 in /opt/rag-api/.env and restart rag-api.",
|
||||||
|
"type": "info"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
52
json/netboot-xyz.json
Normal file
52
json/netboot-xyz.json
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"name": "netboot.xyz",
|
||||||
|
"slug": "netboot-xyz",
|
||||||
|
"categories": [
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"date_created": "2026-03-20",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"interface_port": 80,
|
||||||
|
"documentation": "https://netboot.xyz/docs/",
|
||||||
|
"website": "https://netboot.xyz/",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/netboot-xyz.webp",
|
||||||
|
"config_path": "/var/www/html/boot.cfg",
|
||||||
|
"description": "netboot.xyz is a network boot utility that lets you boot into any type of operating system or utility disk directly from a BIOS/UEFI, without needing a physical boot media. It uses iPXE to present a user-friendly menu of operating systems and tools.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/netboot-xyz.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 1,
|
||||||
|
"ram": 512,
|
||||||
|
"hdd": 8,
|
||||||
|
"os": "Debian",
|
||||||
|
"version": "13"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": [
|
||||||
|
{
|
||||||
|
"text": "Configure your DHCP server: set `next-server` to the container IP, and `boot-filename` to `netboot.xyz.efi` (UEFI) or `netboot.xyz.kpxe` (BIOS/legacy).",
|
||||||
|
"type": "info"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "For UEFI HTTP boot (no DHCP changes required), load the bootloader directly from your firmware: `http://IP/netboot.xyz.efi`.",
|
||||||
|
"type": "info"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Customize menus by editing `/var/www/html/boot.cfg`. Changes are picked up immediately — no service restart needed.",
|
||||||
|
"type": "info"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "TFTP is available on port 69/UDP and HTTP on port 80, both serving from `/var/www/html`.",
|
||||||
|
"type": "info"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -33,7 +33,11 @@
|
|||||||
},
|
},
|
||||||
"notes": [
|
"notes": [
|
||||||
{
|
{
|
||||||
"text": "After installation, update EMAIL_DOMAIN in /opt/simplelogin/.env with your actual domain and configure DNS (MX, SPF, DKIM) accordingly.",
|
"text": "After installation, update EMAIL_DOMAIN and URL in /opt/simplelogin/.env with your actual domain and configure DNS (MX, SPF, DKIM) accordingly.",
|
||||||
|
"type": "warning"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "A working SMTP setup (Postfix + valid domain/DNS) is required. Registration sends an activation email that must be delivered.",
|
||||||
"type": "warning"
|
"type": "warning"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
"script": "ct/twenty.sh",
|
"script": "ct/twenty.sh",
|
||||||
"resources": {
|
"resources": {
|
||||||
"cpu": 4,
|
"cpu": 4,
|
||||||
"ram": 8192,
|
"ram": 10240,
|
||||||
"hdd": 20,
|
"hdd": 20,
|
||||||
"os": "Debian",
|
"os": "Debian",
|
||||||
"version": "13"
|
"version": "13"
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "VersityGW",
|
|
||||||
"slug": "versitygw",
|
|
||||||
"categories": [
|
|
||||||
11
|
|
||||||
],
|
|
||||||
"date_created": "2026-03-10",
|
|
||||||
"type": "ct",
|
|
||||||
"updateable": true,
|
|
||||||
"privileged": false,
|
|
||||||
"interface_port": 7070,
|
|
||||||
"documentation": "https://github.com/versity/versitygw/wiki",
|
|
||||||
"config_path": "/etc/versitygw.d/gateway.conf",
|
|
||||||
"website": "https://www.versity.com/",
|
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/versitygw.webp",
|
|
||||||
"description": "VersityGW is a high-performance, cloud-native S3-compatible gateway that provides S3 API access to various storage backends including POSIX filesystems.",
|
|
||||||
"install_methods": [
|
|
||||||
{
|
|
||||||
"type": "default",
|
|
||||||
"script": "ct/versitygw.sh",
|
|
||||||
"resources": {
|
|
||||||
"cpu": 2,
|
|
||||||
"ram": 2048,
|
|
||||||
"hdd": 8,
|
|
||||||
"os": "Debian",
|
|
||||||
"version": "13"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default_credentials": {
|
|
||||||
"username": null,
|
|
||||||
"password": null
|
|
||||||
},
|
|
||||||
"notes": [
|
|
||||||
{
|
|
||||||
"text": "S3 access credentials are generated during installation and stored in /etc/versitygw.d/gateway.conf",
|
|
||||||
"type": "info"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"text": "Data is stored in /opt/versitygw-data (POSIX backend)",
|
|
||||||
"type": "info"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"text": "Use any S3-compatible client to connect to the gateway endpoint",
|
|
||||||
"type": "info"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: tteck (tteckster)
|
# Author: tteck (tteckster)
|
||||||
# Co-Author: MickLesk
|
# Co-Author: MickLesk
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
|
|
||||||
if ! command -v curl >/dev/null 2>&1; then
|
if ! command -v curl >/dev/null 2>&1; then
|
||||||
apk update && apk add curl >/dev/null 2>&1
|
apk update && apk add curl >/dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main}"
|
COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main}"
|
||||||
source <(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/core.func")
|
source <(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/core.func")
|
||||||
source <(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/error_handler.func")
|
source <(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/error_handler.func")
|
||||||
load_functions
|
load_functions
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: michelroegl-brunner | MickLesk
|
# Author: michelroegl-brunner | MickLesk
|
||||||
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/LICENSE
|
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/LICENSE
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# API.FUNC - TELEMETRY & DIAGNOSTICS API
|
# API.FUNC - TELEMETRY & DIAGNOSTICS API
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
|
# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
|
||||||
# License: MIT | https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
|
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/LICENSE
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# BUILD.FUNC - LXC CONTAINER BUILD & CONFIGURATION
|
# BUILD.FUNC - LXC CONTAINER BUILD & CONFIGURATION
|
||||||
@@ -85,7 +85,7 @@ variables() {
|
|||||||
|
|
||||||
# Configurable base URL for development — override with COMMUNITY_SCRIPTS_URL
|
# Configurable base URL for development — override with COMMUNITY_SCRIPTS_URL
|
||||||
# See docs/DEV_MODE.md for details
|
# See docs/DEV_MODE.md for details
|
||||||
COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main}"
|
COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main}"
|
||||||
|
|
||||||
source <(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
source <(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
||||||
|
|
||||||
@@ -631,7 +631,7 @@ run_preflight() {
|
|||||||
done
|
done
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${INFO} Please resolve the above issues before creating a container."
|
echo -e "${INFO} Please resolve the above issues before creating a container."
|
||||||
echo -e "${INFO} Documentation: ${BL}https://community-scripts.github.io/ProxmoxVE/${CL}"
|
echo -e "${INFO} Documentation: ${BL}https://community-scripts.github.io/ProxmoxVED/${CL}"
|
||||||
|
|
||||||
# Report to telemetry (if consent was given)
|
# Report to telemetry (if consent was given)
|
||||||
post_preflight_to_api
|
post_preflight_to_api
|
||||||
@@ -3294,7 +3294,7 @@ DIAGNOSTICS=yes
|
|||||||
#This file is used to store the diagnostics settings for the Community-Scripts API.
|
#This file is used to store the diagnostics settings for the Community-Scripts API.
|
||||||
#https://git.community-scripts.org/community-scripts/ProxmoxVED/discussions/1836
|
#https://git.community-scripts.org/community-scripts/ProxmoxVED/discussions/1836
|
||||||
#Your diagnostics will be sent to the Community-Scripts API for troubleshooting/statistical purposes.
|
#Your diagnostics will be sent to the Community-Scripts API for troubleshooting/statistical purposes.
|
||||||
#You can review the data at https://community-scripts.github.io/ProxmoxVE/data
|
#You can review the data at https://community-scripts.github.io/ProxmoxVED/data
|
||||||
#If you do not wish to send diagnostics, please set the variable 'DIAGNOSTICS' to "no" in /usr/local/community-scripts/diagnostics, or use the menue.
|
#If you do not wish to send diagnostics, please set the variable 'DIAGNOSTICS' to "no" in /usr/local/community-scripts/diagnostics, or use the menue.
|
||||||
#This will disable the diagnostics feature.
|
#This will disable the diagnostics feature.
|
||||||
#To send diagnostics, set the variable 'DIAGNOSTICS' to "yes" in /usr/local/community-scripts/diagnostics, or use the menue.
|
#To send diagnostics, set the variable 'DIAGNOSTICS' to "yes" in /usr/local/community-scripts/diagnostics, or use the menue.
|
||||||
@@ -3319,7 +3319,7 @@ DIAGNOSTICS=no
|
|||||||
#This file is used to store the diagnostics settings for the Community-Scripts API.
|
#This file is used to store the diagnostics settings for the Community-Scripts API.
|
||||||
#https://git.community-scripts.org/community-scripts/ProxmoxVED/discussions/1836
|
#https://git.community-scripts.org/community-scripts/ProxmoxVED/discussions/1836
|
||||||
#Your diagnostics will be sent to the Community-Scripts API for troubleshooting/statistical purposes.
|
#Your diagnostics will be sent to the Community-Scripts API for troubleshooting/statistical purposes.
|
||||||
#You can review the data at https://community-scripts.github.io/ProxmoxVE/data
|
#You can review the data at https://community-scripts.github.io/ProxmoxVED/data
|
||||||
#If you do not wish to send diagnostics, please set the variable 'DIAGNOSTICS' to "no" in /usr/local/community-scripts/diagnostics, or use the menue.
|
#If you do not wish to send diagnostics, please set the variable 'DIAGNOSTICS' to "no" in /usr/local/community-scripts/diagnostics, or use the menue.
|
||||||
#This will disable the diagnostics feature.
|
#This will disable the diagnostics feature.
|
||||||
#To send diagnostics, set the variable 'DIAGNOSTICS' to "yes" in /usr/local/community-scripts/diagnostics, or use the menue.
|
#To send diagnostics, set the variable 'DIAGNOSTICS' to "yes" in /usr/local/community-scripts/diagnostics, or use the menue.
|
||||||
@@ -4796,7 +4796,7 @@ EOF'
|
|||||||
if [[ "$is_cmd_not_found" == true ]]; then
|
if [[ "$is_cmd_not_found" == true ]]; then
|
||||||
local missing_cmd=""
|
local missing_cmd=""
|
||||||
if [[ -f "$combined_log" ]]; then
|
if [[ -f "$combined_log" ]]; then
|
||||||
missing_cmd=$(grep -oiE '[a-zA-Z0-9_.-]+: command not found' "$combined_log" | tail -1 | sed 's/: command not found//')
|
missing_cmd=$(grep -oiE '[a-zA-Z0-9_.-]+: command not found' "$combined_log" | tail -1 | sed 's/: command not found//' || true)
|
||||||
fi
|
fi
|
||||||
if [[ -n "$missing_cmd" ]]; then
|
if [[ -n "$missing_cmd" ]]; then
|
||||||
echo -e "${TAB}${INFO} Missing command: ${GN}${missing_cmd}${CL}"
|
echo -e "${TAB}${INFO} Missing command: ${GN}${missing_cmd}${CL}"
|
||||||
@@ -4935,7 +4935,7 @@ EOF'
|
|||||||
set +Eeuo pipefail
|
set +Eeuo pipefail
|
||||||
trap - ERR
|
trap - ERR
|
||||||
local _LXC_CAPTURE_LOG="/tmp/.install-capture-${SESSION_ID}.log"
|
local _LXC_CAPTURE_LOG="/tmp/.install-capture-${SESSION_ID}.log"
|
||||||
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh)" 2>&1 | tee "$_LXC_CAPTURE_LOG"
|
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/install/${var_install}.sh)" 2>&1 | tee "$_LXC_CAPTURE_LOG"
|
||||||
local apt_retry_exit=${PIPESTATUS[0]}
|
local apt_retry_exit=${PIPESTATUS[0]}
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
trap 'error_handler' ERR
|
trap 'error_handler' ERR
|
||||||
@@ -6006,7 +6006,7 @@ description() {
|
|||||||
cat <<EOF
|
cat <<EOF
|
||||||
<div align='center'>
|
<div align='center'>
|
||||||
<a href='https://Helper-Scripts.com' target='_blank' rel='noopener noreferrer'>
|
<a href='https://Helper-Scripts.com' target='_blank' rel='noopener noreferrer'>
|
||||||
<img src='https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
<img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<h2 style='font-size: 24px; margin: 20px 0;'>${APP} LXC</h2>
|
<h2 style='font-size: 24px; margin: 20px 0;'>${APP} LXC</h2>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: community-scripts ORG
|
# Author: community-scripts ORG
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/branch/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
|
||||||
# Revision: 1
|
# Revision: 1
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
# - Cloud-Init status monitoring and waiting
|
# - Cloud-Init status monitoring and waiting
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/cloud-init.func)
|
# source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/cloud-init.func)
|
||||||
# setup_cloud_init "$VMID" "$STORAGE" "$HN" "yes"
|
# setup_cloud_init "$VMID" "$STORAGE" "$HN" "yes"
|
||||||
#
|
#
|
||||||
# Compatible with: Debian, Ubuntu, and all Cloud-Init enabled distributions
|
# Compatible with: Debian, Ubuntu, and all Cloud-Init enabled distributions
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# License: MIT | https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
|
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/LICENSE
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# CORE FUNCTIONS - LXC CONTAINER UTILITIES
|
# CORE FUNCTIONS - LXC CONTAINER UTILITIES
|
||||||
@@ -491,7 +491,6 @@ log_section() {
|
|||||||
# - Executes command with output redirected to active log file
|
# - Executes command with output redirected to active log file
|
||||||
# - On error: displays last 20 lines of log and exits with original exit code
|
# - On error: displays last 20 lines of log and exits with original exit code
|
||||||
|
|
||||||
|
|
||||||
# - Temporarily disables error trap to capture exit code correctly
|
# - Temporarily disables error trap to capture exit code correctly
|
||||||
# - Sources explain_exit_code() for detailed error messages
|
# - Sources explain_exit_code() for detailed error messages
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -522,7 +521,7 @@ silent() {
|
|||||||
if [[ $rc -ne 0 ]]; then
|
if [[ $rc -ne 0 ]]; then
|
||||||
# Source explain_exit_code if needed
|
# Source explain_exit_code if needed
|
||||||
if ! declare -f explain_exit_code >/dev/null 2>&1; then
|
if ! declare -f explain_exit_code >/dev/null 2>&1; then
|
||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/error_handler.func)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local explanation
|
local explanation
|
||||||
@@ -791,7 +790,7 @@ exit_script() {
|
|||||||
get_header() {
|
get_header() {
|
||||||
local app_name=$(echo "${APP,,}" | tr -d ' ')
|
local app_name=$(echo "${APP,,}" | tr -d ' ')
|
||||||
local app_type=${APP_TYPE:-ct} # Default to 'ct' if not set
|
local app_type=${APP_TYPE:-ct} # Default to 'ct' if not set
|
||||||
local header_url="https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/${app_type}/headers/${app_name}"
|
local header_url="https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/${app_type}/headers/${app_name}"
|
||||||
local local_header_path="/usr/local/community-scripts/headers/${app_type}/${app_name}"
|
local local_header_path="/usr/local/community-scripts/headers/${app_type}/${app_name}"
|
||||||
|
|
||||||
mkdir -p "$(dirname "$local_header_path")"
|
mkdir -p "$(dirname "$local_header_path")"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: MickLesk (CanbiZ)
|
# Author: MickLesk (CanbiZ)
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Provides comprehensive error handling and signal management for all scripts.
|
# Provides comprehensive error handling and signal management for all scripts.
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ _bootstrap() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Configurable base URL for development — override with COMMUNITY_SCRIPTS_URL
|
# Configurable base URL for development — override with COMMUNITY_SCRIPTS_URL
|
||||||
COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main}"
|
COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main}"
|
||||||
|
|
||||||
# Source core functions
|
# Source core functions
|
||||||
source <(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/core.func")
|
source <(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/core.func")
|
||||||
@@ -944,7 +944,7 @@ EOF
|
|||||||
# Create update script
|
# Create update script
|
||||||
# Use var_os for OS-based containers, otherwise use app name
|
# Use var_os for OS-based containers, otherwise use app name
|
||||||
local update_script_name="${var_os:-$app}"
|
local update_script_name="${var_os:-$app}"
|
||||||
echo "bash -c \"\$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/ct/${update_script_name}.sh)\"" >/usr/bin/update
|
echo "bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/${update_script_name}.sh)\"" >/usr/bin/update
|
||||||
chmod +x /usr/bin/update
|
chmod +x /usr/bin/update
|
||||||
|
|
||||||
# Inject SSH authorized keys if provided
|
# Inject SSH authorized keys if provided
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: MickLesk (CanbiZ)
|
# Author: MickLesk (CanbiZ)
|
||||||
# License: MIT | https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
|
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/LICENSE
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# VM-APP.FUNC - DEPLOY LXC APPLICATIONS INSIDE VIRTUAL MACHINES
|
# VM-APP.FUNC - DEPLOY LXC APPLICATIONS INSIDE VIRTUAL MACHINES
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# License: MIT | https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
|
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/LICENSE
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
SPINNER_PID=""
|
SPINNER_PID=""
|
||||||
@@ -35,7 +35,7 @@ load_functions() {
|
|||||||
get_header() {
|
get_header() {
|
||||||
local app_name=$(echo "${APP,,}" | tr ' ' '-')
|
local app_name=$(echo "${APP,,}" | tr ' ' '-')
|
||||||
local app_type=${APP_TYPE:-vm}
|
local app_type=${APP_TYPE:-vm}
|
||||||
local header_url="https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/${app_type}/headers/${app_name}"
|
local header_url="https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/${app_type}/headers/${app_name}"
|
||||||
local local_header_path="/usr/local/community-scripts/headers/${app_type}/${app_name}"
|
local local_header_path="/usr/local/community-scripts/headers/${app_type}/${app_name}"
|
||||||
|
|
||||||
mkdir -p "$(dirname "$local_header_path")"
|
mkdir -p "$(dirname "$local_header_path")"
|
||||||
|
|||||||
Reference in New Issue
Block a user