Compare commits
1 Commits
main
...
delete_fil
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
930d28909a |
19
.github/workflows/move-to-main-repo.yaml
generated
vendored
19
.github/workflows/move-to-main-repo.yaml
generated
vendored
@@ -39,22 +39,11 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
echo "Resolving issue with label Migration To ProxmoxVE"
|
echo "Filtering Issues 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 [[ "${{ github.event_name }}" == "issues" ]]; then
|
if [ "$filtered_issue" == "null" ] || [ -z "$filtered_issue" ]; 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
676
.github/workflows/pocketbase-bot.yml
generated
vendored
@@ -1,676 +0,0 @@
|
|||||||
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
|
|
||||||
106
.github/workflows/push_json_to_pocketbase.yml
generated
vendored
106
.github/workflows/push_json_to_pocketbase.yml
generated
vendored
@@ -1,15 +1,10 @@
|
|||||||
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
|
||||||
|
|
||||||
@@ -25,52 +20,20 @@ jobs:
|
|||||||
- name: Get JSON file for script
|
- name: Get JSON file for script
|
||||||
id: changed
|
id: changed
|
||||||
run: |
|
run: |
|
||||||
: > changed_app_jsons.txt
|
script_slug="${{ github.event.inputs.script_slug }}"
|
||||||
|
file="json/${script_slug}.json"
|
||||||
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
if [[ ! -f "$file" ]]; then
|
||||||
script_slug="${{ github.event.inputs.script_slug }}"
|
echo "No JSON file at $file."
|
||||||
file="json/${script_slug}.json"
|
|
||||||
if [[ ! -f "$file" ]]; then
|
|
||||||
echo "No JSON file at $file."
|
|
||||||
echo "count=0" >> "$GITHUB_OUTPUT"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
if ! jq -e '.slug' "$file" >/dev/null 2>&1; then
|
|
||||||
echo "File $file has no .slug."
|
|
||||||
echo "count=0" >> "$GITHUB_OUTPUT"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
echo "$file" > changed_app_jsons.txt
|
|
||||||
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"
|
echo "count=0" >> "$GITHUB_OUTPUT"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
if ! jq -e '.slug' "$file" >/dev/null 2>&1; then
|
||||||
count=0
|
echo "File $file has no .slug."
|
||||||
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"
|
echo "count=0" >> "$GITHUB_OUTPUT"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
echo "$file" > changed_app_jsons.txt
|
||||||
echo "count=$count" >> "$GITHUB_OUTPUT"
|
echo "count=1" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Push to PocketBase
|
- name: Push to PocketBase
|
||||||
if: steps.changed.outputs.count != '0'
|
if: steps.changed.outputs.count != '0'
|
||||||
@@ -86,8 +49,7 @@ 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, redirectCount) {
|
function request(fullUrl, opts) {
|
||||||
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:';
|
||||||
@@ -102,13 +64,6 @@ 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() {
|
||||||
@@ -206,40 +161,11 @@ 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: new Date().toISOString().split('T')[0],
|
script_updated: data.date_created || data.script_updated,
|
||||||
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,
|
||||||
@@ -248,16 +174,10 @@ 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 || null,
|
default_user: (data.default_credentials && data.default_credentials.username) || data.default_user,
|
||||||
default_passwd: (data.default_credentials && data.default_credentials.password) || data.default_passwd || null,
|
default_passwd: (data.default_credentials && data.default_credentials.password) || data.default_passwd,
|
||||||
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;
|
||||||
|
|||||||
81
.github/workflows/stale_pr_close.yml
generated
vendored
81
.github/workflows/stale_pr_close.yml
generated
vendored
@@ -22,7 +22,7 @@ jobs:
|
|||||||
const now = new Date();
|
const now = new Date();
|
||||||
const owner = context.repo.owner;
|
const owner = context.repo.owner;
|
||||||
const repo = context.repo.repo;
|
const repo = context.repo.repo;
|
||||||
|
|
||||||
// --- When stale label is added, comment immediately ---
|
// --- When stale label is added, comment immediately ---
|
||||||
if (context.eventName === "pull_request_target" && context.payload.action === "labeled") {
|
if (context.eventName === "pull_request_target" && context.payload.action === "labeled") {
|
||||||
const label = context.payload.label?.name;
|
const label = context.payload.label?.name;
|
||||||
@@ -37,74 +37,19 @@ jobs:
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Scheduled run: fetch all open PRs ---
|
// --- Scheduled run: check all stale PRs ---
|
||||||
const { data: prs } = await github.rest.pulls.list({
|
const { data: prs } = await github.rest.pulls.list({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
state: "open",
|
state: "open",
|
||||||
per_page: 100
|
per_page: 100
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const pr of prs) {
|
for (const pr of prs) {
|
||||||
const labels = pr.labels.map(l => l.name);
|
const hasStale = pr.labels.some(l => l.name === "stale");
|
||||||
const hasStale = labels.includes("stale");
|
if (!hasStale) continue;
|
||||||
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({
|
||||||
owner,
|
owner,
|
||||||
@@ -112,27 +57,27 @@ jobs:
|
|||||||
issue_number: pr.number,
|
issue_number: pr.number,
|
||||||
per_page: 100
|
per_page: 100
|
||||||
});
|
});
|
||||||
|
|
||||||
// Find the most recent time the stale label was added
|
// Find the most recent time the stale label was added
|
||||||
const staleLabelEvents = events
|
const staleLabelEvents = events
|
||||||
.filter(e => e.event === "labeled" && e.label?.name === "stale")
|
.filter(e => e.event === "labeled" && e.label?.name === "stale")
|
||||||
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
|
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
|
||||||
|
|
||||||
if (staleLabelEvents.length === 0) continue;
|
if (staleLabelEvents.length === 0) continue;
|
||||||
|
|
||||||
const staleLabelDate = new Date(staleLabelEvents[0].created_at);
|
const staleLabelDate = new Date(staleLabelEvents[0].created_at);
|
||||||
const daysSinceStale = (now - staleLabelDate) / (1000 * 60 * 60 * 24);
|
const daysSinceStale = (now - staleLabelDate) / (1000 * 60 * 60 * 24);
|
||||||
|
|
||||||
// Check for new commits since stale label was added
|
// Check for new commits since stale label was added
|
||||||
const { data: commits } = await github.rest.pulls.listCommits({
|
const { data: commits } = await github.rest.pulls.listCommits({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
pull_number: pr.number
|
pull_number: pr.number
|
||||||
});
|
});
|
||||||
|
|
||||||
const lastCommitDate = new Date(commits[commits.length - 1].commit.author.date);
|
const lastCommitDate = new Date(commits[commits.length - 1].commit.author.date);
|
||||||
const author = pr.user.login;
|
const author = pr.user.login;
|
||||||
|
|
||||||
// If there are new commits after the stale label, remove it
|
// If there are new commits after the stale label, remove it
|
||||||
if (lastCommitDate > staleLabelDate) {
|
if (lastCommitDate > staleLabelDate) {
|
||||||
await github.rest.issues.removeLabel({
|
await github.rest.issues.removeLabel({
|
||||||
|
|||||||
10
.github/workflows/update-timestamp-on-db.yml
generated
vendored
10
.github/workflows/update-timestamp-on-db.yml
generated
vendored
@@ -83,8 +83,7 @@ jobs:
|
|||||||
const http = require('http');
|
const http = require('http');
|
||||||
const url = require('url');
|
const url = require('url');
|
||||||
|
|
||||||
function request(fullUrl, opts, redirectCount) {
|
function request(fullUrl, opts) {
|
||||||
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:';
|
||||||
@@ -99,13 +98,6 @@ 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() {
|
||||||
|
|||||||
50
ct/alpine-ntfy.sh
Normal file
50
ct/alpine-ntfy.sh
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#!/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}"
|
||||||
75
ct/alpine-wakapi.sh
Normal file
75
ct/alpine-wakapi.sh
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#!/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# Source: https://nginxproxymanager.com/
|
# Source: https://nginxproxymanager.com/
|
||||||
|
|
||||||
APP="Nginx Proxy Manager"
|
APP="Nginx Proxy Manager"
|
||||||
|
|||||||
4
ct/deferred/opencloud.json
generated
4
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/ProxmoxVED/scripts?id=apache-tika`",
|
"text": "**Optional Full-text Search with Apache Tika**: requires your own Tika LXC. See `https://community-scripts.github.io/ProxmoxVE/scripts?id=apache-tika`",
|
||||||
"type": "info"
|
"type": "info"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -61,4 +61,4 @@
|
|||||||
"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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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
73
ct/degoog.sh
@@ -1,73 +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: 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} Credentials saved in:${CL}"
|
echo -e "${INFO}${YW} Admin Setup:${CL}"
|
||||||
echo -e "${TAB}/root/discourse.creds"
|
echo -e "${TAB}${GATEWAY}${BGN}Create the first account in the web UI (use admin@local to match developer emails)${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: Simon Friedrich
|
# Author: Simon Friedrich
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# Source: https://forgejo.org/
|
# Source: https://forgejo.org/
|
||||||
|
|
||||||
APP="Forgejo-Runner"
|
APP="Forgejo-Runner"
|
||||||
|
|||||||
55
ct/isponsorblocktv.sh
Normal file
55
ct/isponsorblocktv.sh
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#!/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
101
ct/librechat.sh
@@ -1,101 +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/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# Source: https://github.com/minthcm/minthcm
|
# Source: https://github.com/minthcm/minthcm
|
||||||
|
|
||||||
APP="MintHCM"
|
APP="MintHCM"
|
||||||
|
|||||||
@@ -1,87 +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: 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}"
|
|
||||||
@@ -1,225 +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: 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/alembic upgrade head
|
$STD .venv/bin/flask db upgrade
|
||||||
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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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:-10240}"
|
var_ram="${var_ram:-8192}"
|
||||||
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}"
|
||||||
|
|||||||
54
ct/versitygw.sh
Normal file
54
ct/versitygw.sh
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#!/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# Source: https://zitadel.com/
|
# Source: https://zitadel.com/
|
||||||
|
|
||||||
APP="Zitadel"
|
APP="Zitadel"
|
||||||
|
|||||||
@@ -1,142 +1,106 @@
|
|||||||
|
|
||||||
# Community Scripts Contribution Guide
|
# Community Scripts Contribution Guide
|
||||||
|
|
||||||
## Welcome to the community-scripts repository
|
## **Welcome to the communty-scripts Repository!**
|
||||||
|
|
||||||
These documents outline the coding standards and contribution flow for the ProxmoxVED 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.
|
||||||
|
|
||||||
The important reality check is simple:
|
### Why Coding Standards Matter
|
||||||
|
|
||||||
- contributors primarily submit shell scripts
|
Coding standards are crucial for several reasons:
|
||||||
- website metadata is **not** contributed as repo JSON files
|
|
||||||
- metadata changes belong to the website / maintainer workflow
|
|
||||||
|
|
||||||
## Scope of these documents
|
1. **Consistency**: Consistent code is easier to read, understand, and maintain. It helps new team members quickly get up to speed and reduces the learning curve.
|
||||||
|
2. **Readability**: Clear and well-structured code is easier to debug and extend. It allows developers to quickly identify and fix issues.
|
||||||
|
3. **Maintainability**: Code that follows a standard structure is easier to refactor and update. It ensures that changes can be made with minimal risk of introducing new bugs.
|
||||||
|
4. **Collaboration**: When everyone follows the same standards, it becomes easier to collaborate on code. It reduces friction and misunderstandings during code reviews and merges.
|
||||||
|
|
||||||
This contribution guide covers:
|
### Scope of These Documents
|
||||||
|
|
||||||
- `ct/$AppName.sh` scripts for container creation and update entrypoints
|
These documents cover the coding standards for the following types of files in our project:
|
||||||
- `install/$AppName-install.sh` scripts for in-container installation logic
|
|
||||||
- the supporting workflow for testing from your fork before opening a PR
|
|
||||||
|
|
||||||
## Getting started
|
- **`install/$AppName-install.sh` Scripts**: These scripts are responsible for the installation of applications.
|
||||||
|
- **`ct/$AppName.sh` Scripts**: These scripts handle the creation and updating of containers.
|
||||||
|
- **`json/$AppName.json`**: These files store structured data and are used for the website.
|
||||||
|
|
||||||
Before contributing, set up:
|
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.
|
||||||
|
|
||||||
1. Visual Studio Code or another editor with ShellCheck support
|
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. 📚🔍
|
||||||
2. a fork of `community-scripts/ProxmoxVED`
|
|
||||||
3. a local clone of your fork
|
|
||||||
|
|
||||||
### Recommended extensions
|
Let's work together to keep our codebase clean, efficient, and maintainable! 💪🚀
|
||||||
|
|
||||||
- [Shell Syntax](https://marketplace.visualstudio.com/items?itemName=bmalehorn.shell-syntax)
|
|
||||||
- [ShellCheck](https://marketplace.visualstudio.com/items?itemName=timonwong.shellcheck)
|
|
||||||
- [Shell Format](https://marketplace.visualstudio.com/items?itemName=foxundermoon.shell-format)
|
|
||||||
|
|
||||||
### Templates
|
## Getting Started
|
||||||
|
|
||||||
Use these templates as your starting point:
|
Before contributing, please ensure that you have the following setup:
|
||||||
|
|
||||||
- [CT template: `AppName.sh`](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh)
|
1. **Visual Studio Code** (recommended for script development)
|
||||||
- [Install template: `AppName-install.sh`](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh)
|
2. **Recommended VS Code Extensions:**
|
||||||
|
- [Shell Syntax](https://marketplace.visualstudio.com/items?itemName=bmalehorn.shell-syntax)
|
||||||
|
- [ShellCheck](https://marketplace.visualstudio.com/items?itemName=timonwong.shellcheck)
|
||||||
|
- [Shell Format](https://marketplace.visualstudio.com/items?itemName=foxundermoon.shell-format)
|
||||||
|
|
||||||
## Script types
|
### Important Notes
|
||||||
|
- 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.
|
||||||
|
|
||||||
### Application script: `ct/AppName.sh`
|
---
|
||||||
|
|
||||||
Reference guide:
|
# 🚀 The Application Script (ct/AppName.sh)
|
||||||
|
|
||||||
- [CT coding guide for `AppName.sh`](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md)
|
- 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).
|
||||||
|
- These scripts are responsible for container creation, setting the necessary variables and handling the update of the application once installed.
|
||||||
|
|
||||||
This script is responsible for:
|
---
|
||||||
|
|
||||||
- host-side container orchestration
|
# 🛠 The Installation Script (install/AppName-install.sh)
|
||||||
- app variables and defaults
|
|
||||||
- update wiring for the installed app
|
|
||||||
|
|
||||||
### Installation script: `install/AppName-install.sh`
|
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.md).
|
||||||
|
- These scripts are responsible for the installation of the application.
|
||||||
|
|
||||||
Reference guide:
|
---
|
||||||
|
|
||||||
- [Install coding guide for `AppName-install.sh`](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.md)
|
## 🚀 Building Your Own Scripts
|
||||||
|
|
||||||
This script is responsible for:
|
Start with the [template script](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh)
|
||||||
|
|
||||||
- container-internal installation logic
|
---
|
||||||
- package/runtime setup
|
|
||||||
- final application configuration
|
|
||||||
|
|
||||||
## Contribution process
|
## 🤝 Contribution Process
|
||||||
|
|
||||||
### 1. Fork the repository
|
### 1. Fork the repository
|
||||||
|
Fork to your GitHub account
|
||||||
|
|
||||||
Fork `community-scripts/ProxmoxVED` to your GitHub account.
|
### 2. Clone your fork on your local environment
|
||||||
|
|
||||||
### 2. Clone your fork
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/yourUserName/ForkName
|
git clone https://github.com/yourUserName/ForkName
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Create a branch
|
### 3. Create a new branch
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git switch -c your-feature-branch
|
git switch -c your-feature-branch
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Configure your fork for testing
|
### 4. Change paths in build.func install.func and AppName.sh
|
||||||
|
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"
|
||||||
```
|
```
|
||||||
|
|
||||||
### 7. Push your branch
|
### 5. Push to your fork
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git push origin your-feature-branch
|
git push origin your-feature-branch
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8. Open a pull request
|
### 6. Create 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`.
|
---
|
||||||
|
|
||||||
Your PR should contain only the files that belong to the script contribution itself, typically:
|
## 📚 Pages
|
||||||
|
|
||||||
- `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)
|
||||||
- [Fork setup guide](./FORK_SETUP.md)
|
- [JSON Template: AppName.json](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/json/AppName.json)
|
||||||
- [Contribution README](./README.md)
|
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,6 @@ 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`)
|
||||||
|
|
||||||
@@ -274,7 +273,6 @@ 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
|
||||||
@@ -286,7 +284,6 @@ 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)
|
||||||
@@ -300,7 +297,6 @@ 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
|
||||||
@@ -402,7 +398,6 @@ 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
|
||||||
@@ -416,7 +411,6 @@ 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
|
||||||
@@ -432,7 +426,6 @@ 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
|
||||||
@@ -440,20 +433,17 @@ 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
|
||||||
|
|||||||
@@ -1,268 +0,0 @@
|
|||||||
# 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,25 +1,15 @@
|
|||||||
# Misc Documentation
|
# Misc Documentation
|
||||||
|
|
||||||
This directory documents the shared Bash function libraries under `misc/`.
|
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.
|
||||||
|
|
||||||
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
|
||||||
@@ -33,11 +23,9 @@ The important implementation detail is that these libraries are **not independen
|
|||||||
---
|
---
|
||||||
|
|
||||||
### 📁 [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
|
||||||
@@ -49,11 +37,9 @@ The important implementation detail is that these libraries are **not independen
|
|||||||
---
|
---
|
||||||
|
|
||||||
### 📁 [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
|
||||||
@@ -65,45 +51,39 @@ The important implementation detail is that these libraries are **not independen
|
|||||||
---
|
---
|
||||||
|
|
||||||
### 📁 [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_to_api_vm()`, `post_progress_to_api()`, `post_update_to_api()`, `explain_exit_code()`
|
**Key Functions**: `post_to_api()`, `post_update_to_api()`, `get_error_description()`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📦 **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()`, `customize()`
|
**Key Functions**: `setting_up_container()`, `network_check()`, `update_os()`, `motd_ssh()`, `cleanup_lxc()`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 📁 [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
|
||||||
@@ -111,16 +91,14 @@ The important implementation detail is that these libraries are **not independen
|
|||||||
- 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**: `curl_with_retry()`, `setup_deb822_repo()`, `install_packages_with_retry()`, `setup_mariadb()`, `setup_postgresql()`, `get_latest_github_release()`
|
**Key Functions**: `setup_nodejs()`, `setup_php()`, `setup_mariadb()`, `setup_docker()`, `setup_deb822_repo()`, `pkg_install()`, `pkg_update()`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 📁 [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
|
||||||
@@ -132,11 +110,9 @@ The important implementation detail is that these libraries are **not independen
|
|||||||
---
|
---
|
||||||
|
|
||||||
### 📁 [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
|
||||||
@@ -148,11 +124,9 @@ The important implementation detail is that these libraries are **not independen
|
|||||||
---
|
---
|
||||||
|
|
||||||
### 📁 [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
|
||||||
@@ -171,24 +145,18 @@ The important implementation detail is that these libraries are **not independen
|
|||||||
├─────────────────────────────────────────────┤
|
├─────────────────────────────────────────────┤
|
||||||
│ │
|
│ │
|
||||||
│ ct/AppName.sh │
|
│ ct/AppName.sh │
|
||||||
│ ↓ sources │
|
│ ↓ (sources) │
|
||||||
│ build.func │
|
│ build.func │
|
||||||
│ ├─ sources api.func │
|
│ ├─ variables() │
|
||||||
│ ├─ sources core.func │
|
│ ├─ build_container() │
|
||||||
│ ├─ sources error_handler.func │
|
│ └─ advanced_settings() │
|
||||||
│ ├─ loads variables/settings/prompts │
|
│ ↓ (calls pct create with) │
|
||||||
│ └─ creates container + launch phase │
|
|
||||||
│ ↓ pct exec / lxc-attach │
|
|
||||||
│ install/appname-install.sh │
|
│ install/appname-install.sh │
|
||||||
│ ↓ sources install.func │
|
│ ↓ (sources) │
|
||||||
│ ├─ sources core.func │
|
│ ├─ core.func (colors, messaging) │
|
||||||
│ ├─ sources error_handler.func │
|
│ ├─ error_handler.func (error trapping) │
|
||||||
│ ├─ load_functions() │
|
│ ├─ install.func (setup/network) │
|
||||||
│ ├─ catch_errors() │
|
│ └─ tools.func (packages/tools) │
|
||||||
│ ├─ network_check() │
|
|
||||||
│ ├─ update_os() │
|
|
||||||
│ │ └─ downloads + sources tools.func │
|
|
||||||
│ └─ app install uses tools.func │
|
|
||||||
│ │
|
│ │
|
||||||
└─────────────────────────────────────────────┘
|
└─────────────────────────────────────────────┘
|
||||||
|
|
||||||
@@ -223,17 +191,17 @@ The important implementation detail is that these libraries are **not independen
|
|||||||
|
|
||||||
## 📊 **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 |
|
||||||
| api.func | 5 | 5+ | ✅ Complete |
|
| api.func | 5 | 5+ | ✅ Complete |
|
||||||
| install.func | 5 | 8+ | ✅ Complete |
|
| install.func | 5 | 8+ | ✅ Complete |
|
||||||
| tools.func | 6 | 30+ | ✅ Complete |
|
| tools.func | 6 | 30+ | ✅ Complete |
|
||||||
| alpine-install.func | 5 | 6+ | ✅ Complete |
|
| alpine-install.func | 5 | 6+ | ✅ Complete |
|
||||||
| alpine-tools.func | 5 | 15+ | ✅ Complete |
|
| alpine-tools.func | 5 | 15+ | ✅ Complete |
|
||||||
| cloud-init.func | 5 | 12+ | ✅ Complete |
|
| cloud-init.func | 5 | 12+ | ✅ Complete |
|
||||||
|
|
||||||
**Total**: 9 function libraries, 48 documentation files, 150+ functions
|
**Total**: 9 function libraries, 48 documentation files, 150+ functions
|
||||||
|
|
||||||
@@ -242,20 +210,16 @@ The important implementation detail is that these libraries are **not independen
|
|||||||
## 🚀 **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/)**
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -287,7 +251,6 @@ 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
|
||||||
@@ -310,12 +273,11 @@ All documentation follows these standards:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ✅ **Last Updated**: Based on live `misc/*` code verification
|
## ✅ **Last Updated**: December 2025
|
||||||
|
|
||||||
**Maintainers**: community-scripts team
|
**Maintainers**: community-scripts team
|
||||||
**License**: MIT
|
**License**: MIT
|
||||||
**Status**: Canonical overviews aligned to live code; deeper generated subpages may still require occasional drift cleanup
|
**Status**: All 9 libraries fully documented and standardized
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
_When documentation conflicts with the live shell implementation, prefer the files under `ProxmoxVE` / `ProxmoxVED` `misc/`._
|
*This directory contains specialized documentation for specific components of the Proxmox Community Scripts project.*
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
## 🤖 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
|
|
||||||
26
install/alpine-ntfy-install.sh
Normal file
26
install/alpine-ntfy-install.sh
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/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
|
||||||
|
|
||||||
61
install/alpine-wakapi-install.sh
Normal file
61
install/alpine-wakapi-install.sh
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#!/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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"
|
||||||
@@ -15,7 +15,7 @@ update_os
|
|||||||
|
|
||||||
msg_info "Installing Dependencies"
|
msg_info "Installing Dependencies"
|
||||||
$STD apt-get install -y \
|
$STD apt-get install -y \
|
||||||
iptables
|
iptables
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
msg_info "Installing JumpServer"
|
msg_info "Installing JumpServer"
|
||||||
|
|||||||
@@ -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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# Source: https://nginxproxymanager.com/
|
# Source: https://nginxproxymanager.com/
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
@@ -16,29 +16,29 @@ update_os
|
|||||||
msg_info "Installing Dependencies"
|
msg_info "Installing Dependencies"
|
||||||
$STD apt-get update
|
$STD apt-get update
|
||||||
$STD apt-get -y install \
|
$STD apt-get -y install \
|
||||||
sudo \
|
sudo \
|
||||||
mc \
|
mc \
|
||||||
curl \
|
curl \
|
||||||
gnupg \
|
gnupg \
|
||||||
make \
|
make \
|
||||||
gcc \
|
gcc \
|
||||||
g++ \
|
g++ \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
apache2-utils \
|
apache2-utils \
|
||||||
logrotate \
|
logrotate \
|
||||||
build-essential \
|
build-essential \
|
||||||
git
|
git
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
msg_info "Installing Python3"
|
msg_info "Installing Python3"
|
||||||
$STD apt-get install -y \
|
$STD apt-get install -y \
|
||||||
python3 \
|
python3 \
|
||||||
python3-dev \
|
python3-dev \
|
||||||
python3-pip \
|
python3-pip \
|
||||||
python3-venv \
|
python3-venv \
|
||||||
python3-cffi \
|
python3-cffi \
|
||||||
python3-certbot \
|
python3-certbot \
|
||||||
python3-certbot-dns-cloudflare
|
python3-certbot-dns-cloudflare
|
||||||
$STD pip3 install certbot-dns-multi
|
$STD pip3 install certbot-dns-multi
|
||||||
$STD python3 -m venv /opt/certbot/
|
$STD python3 -m venv /opt/certbot/
|
||||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
||||||
@@ -76,7 +76,7 @@ sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" frontend/package.js
|
|||||||
sed -i 's+^daemon+#daemon+g' docker/rootfs/etc/nginx/nginx.conf
|
sed -i 's+^daemon+#daemon+g' docker/rootfs/etc/nginx/nginx.conf
|
||||||
NGINX_CONFS=$(find "$(pwd)" -type f -name "*.conf")
|
NGINX_CONFS=$(find "$(pwd)" -type f -name "*.conf")
|
||||||
for NGINX_CONF in $NGINX_CONFS; do
|
for NGINX_CONF in $NGINX_CONFS; do
|
||||||
sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF"
|
sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF"
|
||||||
done
|
done
|
||||||
|
|
||||||
mkdir -p /var/www/html /etc/nginx/logs
|
mkdir -p /var/www/html /etc/nginx/logs
|
||||||
@@ -88,21 +88,21 @@ ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf
|
|||||||
rm -f /etc/nginx/conf.d/dev.conf
|
rm -f /etc/nginx/conf.d/dev.conf
|
||||||
|
|
||||||
mkdir -p /tmp/nginx/body \
|
mkdir -p /tmp/nginx/body \
|
||||||
/run/nginx \
|
/run/nginx \
|
||||||
/data/nginx \
|
/data/nginx \
|
||||||
/data/custom_ssl \
|
/data/custom_ssl \
|
||||||
/data/logs \
|
/data/logs \
|
||||||
/data/access \
|
/data/access \
|
||||||
/data/nginx/default_host \
|
/data/nginx/default_host \
|
||||||
/data/nginx/default_www \
|
/data/nginx/default_www \
|
||||||
/data/nginx/proxy_host \
|
/data/nginx/proxy_host \
|
||||||
/data/nginx/redirection_host \
|
/data/nginx/redirection_host \
|
||||||
/data/nginx/stream \
|
/data/nginx/stream \
|
||||||
/data/nginx/dead_host \
|
/data/nginx/dead_host \
|
||||||
/data/nginx/temp \
|
/data/nginx/temp \
|
||||||
/var/lib/nginx/cache/public \
|
/var/lib/nginx/cache/public \
|
||||||
/var/lib/nginx/cache/private \
|
/var/lib/nginx/cache/private \
|
||||||
/var/cache/nginx/proxy_temp
|
/var/cache/nginx/proxy_temp
|
||||||
|
|
||||||
chmod -R 777 /var/cache/nginx
|
chmod -R 777 /var/cache/nginx
|
||||||
chown root /tmp/nginx
|
chown root /tmp/nginx
|
||||||
@@ -110,7 +110,7 @@ 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
|
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
|
if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then
|
||||||
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 &>/dev/null
|
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 &>/dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p /app/global /app/frontend/images
|
mkdir -p /app/global /app/frontend/images
|
||||||
@@ -130,7 +130,7 @@ msg_ok "Built Frontend"
|
|||||||
msg_info "Initializing Backend"
|
msg_info "Initializing Backend"
|
||||||
rm -rf /app/config/default.json
|
rm -rf /app/config/default.json
|
||||||
if [ ! -f /app/config/production.json ]; then
|
if [ ! -f /app/config/production.json ]; then
|
||||||
cat <<'EOF' >/app/config/production.json
|
cat <<'EOF' >/app/config/production.json
|
||||||
{
|
{
|
||||||
"database": {
|
"database": {
|
||||||
"engine": "knex-native",
|
"engine": "knex-native",
|
||||||
|
|||||||
@@ -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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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"
|
||||||
@@ -15,9 +15,9 @@ update_os
|
|||||||
|
|
||||||
msg_info "Installing dependencies"
|
msg_info "Installing dependencies"
|
||||||
$STD apt-get install -y \
|
$STD apt-get install -y \
|
||||||
build-essential \
|
build-essential \
|
||||||
openssl \
|
openssl \
|
||||||
git
|
git
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
msg_info "Installing Bun"
|
msg_info "Installing Bun"
|
||||||
@@ -38,10 +38,10 @@ $STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET client_encoding TO 'utf8'
|
|||||||
$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET default_transaction_isolation TO 'read committed';"
|
$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET default_transaction_isolation TO 'read committed';"
|
||||||
$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET timezone TO 'UTC'"
|
$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET timezone TO 'UTC'"
|
||||||
{
|
{
|
||||||
echo "Nimbus-Credentials"
|
echo "Nimbus-Credentials"
|
||||||
echo "Nimbus Database User: $DB_USER"
|
echo "Nimbus Database User: $DB_USER"
|
||||||
echo "Nimbus Database Password: $DB_PASS"
|
echo "Nimbus Database Password: $DB_PASS"
|
||||||
echo "Nimbus Database Name: $DB_NAME"
|
echo "Nimbus Database Name: $DB_NAME"
|
||||||
} >>~/nimbus.creds
|
} >>~/nimbus.creds
|
||||||
msg_ok "Set up PostgreSQL Database"
|
msg_ok "Set up PostgreSQL Database"
|
||||||
|
|
||||||
|
|||||||
@@ -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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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"
|
||||||
@@ -15,13 +15,13 @@ update_os
|
|||||||
|
|
||||||
msg_info "Installing Dependencies"
|
msg_info "Installing Dependencies"
|
||||||
$STD apt-get install -y \
|
$STD apt-get install -y \
|
||||||
make \
|
make \
|
||||||
git \
|
git \
|
||||||
build-essential \
|
build-essential \
|
||||||
binutils \
|
binutils \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
libsqlite3-dev \
|
libsqlite3-dev \
|
||||||
libssl-dev
|
libssl-dev
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
msg_info "Installing Rust"
|
msg_info "Installing Rust"
|
||||||
|
|||||||
@@ -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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
color
|
color
|
||||||
@@ -14,12 +14,12 @@ update_os
|
|||||||
|
|
||||||
msg_info "Installing Dependencies"
|
msg_info "Installing Dependencies"
|
||||||
$STD apt-get install -y \
|
$STD apt-get install -y \
|
||||||
curl \
|
curl \
|
||||||
sudo \
|
sudo \
|
||||||
mc \
|
mc \
|
||||||
gnupg \
|
gnupg \
|
||||||
apt-transport-https \
|
apt-transport-https \
|
||||||
lsb-release
|
lsb-release
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
msg_info "Setting up PostgreSQL Repository"
|
msg_info "Setting up PostgreSQL Repository"
|
||||||
@@ -146,11 +146,11 @@ msg_ok "Setup TimescaleDB"
|
|||||||
|
|
||||||
read -r -p "Would you like to add Adminer? <y/N> " prompt
|
read -r -p "Would you like to add Adminer? <y/N> " prompt
|
||||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||||
msg_info "Installing Adminer"
|
msg_info "Installing Adminer"
|
||||||
$STD apt install -y adminer
|
$STD apt install -y adminer
|
||||||
$STD a2enconf adminer
|
$STD a2enconf adminer
|
||||||
systemctl reload apache2
|
systemctl reload apache2
|
||||||
msg_ok "Installed Adminer"
|
msg_ok "Installed Adminer"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
motd_ssh
|
motd_ssh
|
||||||
|
|||||||
@@ -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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# Source: https://vikunja.io/
|
# Source: https://vikunja.io/
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
|||||||
@@ -1,88 +0,0 @@
|
|||||||
#!/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,17 +55,18 @@ 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@discourse.local
|
DISCOURSE_DEVELOPER_EMAILS=admin@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"
|
||||||
@@ -93,32 +94,8 @@ 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"
|
||||||
@@ -142,7 +119,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 pitchfork -c config/pitchfork.conf.rb
|
ExecStart=/root/.rbenv/shims/bundle exec puma -w 2
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|
||||||
@@ -161,7 +138,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 default -q low -q ultra_low
|
ExecStart=/root/.rbenv/shims/bundle exec sidekiq -q critical -q low -q default
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|
||||||
@@ -176,27 +153,12 @@ 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;
|
||||||
@@ -205,7 +167,6 @@ 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
|
||||||
@@ -214,7 +175,6 @@ 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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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,6 +29,7 @@ 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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# Source: https://forgejo.org/
|
# Source: https://forgejo.org/
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
|||||||
68
install/isponsorblocktv-install.sh
Normal file
68
install/isponsorblocktv-install.sh
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#!/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
|
||||||
@@ -1,139 +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/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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"
|
||||||
|
|
||||||
@@ -72,8 +72,8 @@ msg_ok "Generated configuration file"
|
|||||||
|
|
||||||
msg_info "Installing MintHCM"
|
msg_info "Installing MintHCM"
|
||||||
cd /var/www/MintHCM
|
cd /var/www/MintHCM
|
||||||
$STD sudo -u www-data php MintCLI install </var/www/MintHCM/configMint4
|
$STD sudo -u www-data php MintCLI install < /var/www/MintHCM/configMint4
|
||||||
printf "* * * * * cd /var/www/MintHCM/legacy; php -f cron.php > /dev/null 2>&1\n" >/var/spool/cron/crontabs/www-data
|
printf "* * * * * cd /var/www/MintHCM/legacy; php -f cron.php > /dev/null 2>&1\n" > /var/spool/cron/crontabs/www-data
|
||||||
service cron start
|
service cron start
|
||||||
rm -f /var/www/MintHCM/configMint4
|
rm -f /var/www/MintHCM/configMint4
|
||||||
msg_ok "Installed MintHCM"
|
msg_ok "Installed MintHCM"
|
||||||
|
|||||||
@@ -1,102 +0,0 @@
|
|||||||
#!/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
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
#!/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/alembic upgrade head
|
$STD .venv/bin/flask db upgrade
|
||||||
$STD .venv/bin/python init_app.py
|
$STD .venv/bin/python init_app.py
|
||||||
msg_ok "Configured SimpleLogin"
|
msg_ok "Configured SimpleLogin"
|
||||||
|
|
||||||
@@ -224,7 +224,6 @@ 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,20 +22,27 @@ 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 "Installed step-ca and step-cli"
|
msg_ok "Created smallstep CA service user"
|
||||||
|
|
||||||
msg_info "Initializing step-ca"
|
|
||||||
DeploymentType="standalone"
|
DeploymentType="standalone"
|
||||||
FQDN=$(hostname -f)
|
FQDN=$(hostname -f)
|
||||||
DomainName=$(hostname -d)
|
DomainName=$(hostname -d)
|
||||||
@@ -70,6 +77,7 @@ 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"
|
||||||
@@ -92,19 +100,25 @@ $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 "Initialized step-ca"
|
msg_ok "Updated provisioner configurations"
|
||||||
|
|
||||||
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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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=4096"
|
export NODE_OPTIONS="--max-old-space-size=3072"
|
||||||
$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
|
||||||
|
|||||||
37
install/versitygw-install.sh
Normal file
37
install/versitygw-install.sh
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#!/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# Source: https://zitadel.com/
|
# Source: https://zitadel.com/
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
@@ -55,12 +55,12 @@ msg_ok "Configured PostgreSQL"
|
|||||||
msg_info "Installing Zitadel"
|
msg_info "Installing Zitadel"
|
||||||
cd "${ZITADEL_DIR}"
|
cd "${ZITADEL_DIR}"
|
||||||
mkdir -p ${CONFIG_DIR}
|
mkdir -p ${CONFIG_DIR}
|
||||||
echo -n "${MASTERKEY}" >${CONFIG_DIR}/.masterkey
|
echo -n "${MASTERKEY}" > ${CONFIG_DIR}/.masterkey
|
||||||
chmod 600 "${CONFIG_DIR}/.masterkey"
|
chmod 600 "${CONFIG_DIR}/.masterkey"
|
||||||
chown "${ZITADEL_USER}:${ZITADEL_GROUP}" "${CONFIG_DIR}/.masterkey"
|
chown "${ZITADEL_USER}:${ZITADEL_GROUP}" "${CONFIG_DIR}/.masterkey"
|
||||||
|
|
||||||
# Update config.yaml for network access
|
# Update config.yaml for network access
|
||||||
cat >"${CONFIG_DIR}/config.yaml" <<EOF
|
cat > "${CONFIG_DIR}/config.yaml" <<EOF
|
||||||
ExternalSecure: false
|
ExternalSecure: false
|
||||||
ExternalDomain: ${SERVER_IP}
|
ExternalDomain: ${SERVER_IP}
|
||||||
ExternalPort: ${API_PORT}
|
ExternalPort: ${API_PORT}
|
||||||
@@ -134,7 +134,7 @@ $STD sudo -u ${ZITADEL_USER} ./zitadel setup --config ${CONFIG_DIR}/config.yaml
|
|||||||
CLIENT_PAT=$(cat ${ZITADEL_DIR}/login-client.pat)
|
CLIENT_PAT=$(cat ${ZITADEL_DIR}/login-client.pat)
|
||||||
|
|
||||||
# Update Login V2 login.env file
|
# Update Login V2 login.env file
|
||||||
cat >"${CONFIG_DIR}/login.env" <<EOF
|
cat > "${CONFIG_DIR}/login.env" <<EOF
|
||||||
NEXT_PUBLIC_BASE_PATH=/ui/v2/login
|
NEXT_PUBLIC_BASE_PATH=/ui/v2/login
|
||||||
EMAIL_VERIFICATION=false
|
EMAIL_VERIFICATION=false
|
||||||
ZITADEL_API_URL=http://${SERVER_IP}:${API_PORT}
|
ZITADEL_API_URL=http://${SERVER_IP}:${API_PORT}
|
||||||
@@ -144,7 +144,7 @@ EOF
|
|||||||
chown "${ZITADEL_USER}:${ZITADEL_GROUP}" "${CONFIG_DIR}/login.env"
|
chown "${ZITADEL_USER}:${ZITADEL_GROUP}" "${CONFIG_DIR}/login.env"
|
||||||
|
|
||||||
# Create api.env file
|
# Create api.env file
|
||||||
cat >"${CONFIG_DIR}/api.env" <<EOF
|
cat > "${CONFIG_DIR}/api.env" <<EOF
|
||||||
ZITADEL_MASTERKEY=${MASTERKEY}
|
ZITADEL_MASTERKEY=${MASTERKEY}
|
||||||
ZITADEL_DATABASE_POSTGRES_HOST=localhost
|
ZITADEL_DATABASE_POSTGRES_HOST=localhost
|
||||||
ZITADEL_DATABASE_POSTGRES_PORT=5432
|
ZITADEL_DATABASE_POSTGRES_PORT=5432
|
||||||
@@ -165,7 +165,7 @@ msg_ok "Installed Zitadel"
|
|||||||
|
|
||||||
msg_info "Creating Services"
|
msg_info "Creating Services"
|
||||||
# Create API service
|
# Create API service
|
||||||
cat >/etc/systemd/system/zitadel-api.service <<EOF
|
cat > /etc/systemd/system/zitadel-api.service <<EOF
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=ZITADEL API Server
|
Description=ZITADEL API Server
|
||||||
After=network.target postgresql.service
|
After=network.target postgresql.service
|
||||||
@@ -187,7 +187,7 @@ WantedBy=multi-user.target
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Create Login V2 service
|
# Create Login V2 service
|
||||||
cat >/etc/systemd/system/zitadel-login.service <<EOF
|
cat > /etc/systemd/system/zitadel-login.service <<EOF
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=ZITADEL Login V2 Service
|
Description=ZITADEL Login V2 Service
|
||||||
After=network.target zitadel-api.service
|
After=network.target zitadel-api.service
|
||||||
@@ -221,7 +221,7 @@ msg_ok "Created Services"
|
|||||||
|
|
||||||
msg_info "Saving Credentials"
|
msg_info "Saving Credentials"
|
||||||
# Create credentials file
|
# Create credentials file
|
||||||
cat >"${CONFIG_DIR}/INSTALLATION_INFO.txt" <<EOF
|
cat > "${CONFIG_DIR}/INSTALLATION_INFO.txt" <<EOF
|
||||||
################################################################################
|
################################################################################
|
||||||
# ZITADEL Installation Information
|
# ZITADEL Installation Information
|
||||||
# Generated: $(date)
|
# Generated: $(date)
|
||||||
|
|||||||
40
json/alpine-wakapi.json
Normal file
40
json/alpine-wakapi.json
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"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 credentials are saved in `/root/discourse.creds` inside the container.",
|
"text": "Admin user is created with username 'admin'. Set password in first login.",
|
||||||
"type": "info"
|
"type": "info"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "Configure SMTP settings in the admin panel (Admin > Settings > Email) for email notifications.",
|
"text": "Configure SMTP settings in admin panel for email notifications.",
|
||||||
"type": "info"
|
"type": "info"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
44
json/isponsorblocktv.json
Normal file
44
json/isponsorblocktv.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
{
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
{
|
|
||||||
"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,11 +33,7 @@
|
|||||||
},
|
},
|
||||||
"notes": [
|
"notes": [
|
||||||
{
|
{
|
||||||
"text": "After installation, update EMAIL_DOMAIN and URL in /opt/simplelogin/.env with your actual domain and configure DNS (MX, SPF, DKIM) accordingly.",
|
"text": "After installation, update EMAIL_DOMAIN 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": 10240,
|
"ram": 8192,
|
||||||
"hdd": 20,
|
"hdd": 20,
|
||||||
"os": "Debian",
|
"os": "Debian",
|
||||||
"version": "13"
|
"version": "13"
|
||||||
|
|||||||
48
json/versitygw.json
Normal file
48
json/versitygw.json
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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://raw.githubusercontent.com/community-scripts/ProxmoxVED/main}"
|
COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/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/ProxmoxVED/main/LICENSE
|
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVE/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://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/LICENSE
|
# License: MIT | https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/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://raw.githubusercontent.com/community-scripts/ProxmoxVED/main}"
|
COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/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/ProxmoxVED/${CL}"
|
echo -e "${INFO} Documentation: ${BL}https://community-scripts.github.io/ProxmoxVE/${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/ProxmoxVED/data
|
#You can review the data at https://community-scripts.github.io/ProxmoxVE/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/ProxmoxVED/data
|
#You can review the data at https://community-scripts.github.io/ProxmoxVE/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//' || true)
|
missing_cmd=$(grep -oiE '[a-zA-Z0-9_.-]+: command not found' "$combined_log" | tail -1 | sed 's/: command not found//')
|
||||||
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/ProxmoxVED/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/ProxmoxVE/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://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
<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;'/>
|
||||||
</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/ProxmoxVED/raw/branch/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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/ProxmoxVED/main/misc/cloud-init.func)
|
# source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/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://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/LICENSE
|
# License: MIT | https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# CORE FUNCTIONS - LXC CONTAINER UTILITIES
|
# CORE FUNCTIONS - LXC CONTAINER UTILITIES
|
||||||
@@ -399,7 +399,7 @@ ssh_check() {
|
|||||||
# even after INSTALL_LOG is exported for the container)
|
# even after INSTALL_LOG is exported for the container)
|
||||||
# - INSTALL_LOG: Container operations (application installation)
|
# - INSTALL_LOG: Container operations (application installation)
|
||||||
# - BUILD_LOG: Host operations (container creation)
|
# - BUILD_LOG: Host operations (container creation)
|
||||||
|
|
||||||
# - Fallback to BUILD_LOG if neither is set
|
# - Fallback to BUILD_LOG if neither is set
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
get_active_logfile() {
|
get_active_logfile() {
|
||||||
@@ -490,7 +490,8 @@ 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
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -517,11 +518,11 @@ silent() {
|
|||||||
|
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
trap 'error_handler' ERR
|
trap 'error_handler' ERR
|
||||||
|
|
||||||
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/ProxmoxVED/main/misc/error_handler.func)
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local explanation
|
local explanation
|
||||||
@@ -790,7 +791,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://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/${app_type}/headers/${app_name}"
|
local header_url="https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/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/ProxmoxVED/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/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://raw.githubusercontent.com/community-scripts/ProxmoxVED/main}"
|
COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/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://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/${update_script_name}.sh)\"" >/usr/bin/update
|
echo "bash -c \"\$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/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
|
||||||
|
|||||||
601
misc/tools.func
601
misc/tools.func
@@ -105,13 +105,11 @@ curl_with_retry() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
debug_log "curl attempt $attempt failed (timeout=${timeout}s), waiting ${backoff}s before retry..."
|
debug_log "curl attempt $attempt failed, waiting ${backoff}s before retry..."
|
||||||
sleep "$backoff"
|
sleep "$backoff"
|
||||||
# Exponential backoff: 1, 2, 4, 8... capped at 30s
|
# Exponential backoff: 1, 2, 4, 8... capped at 30s
|
||||||
backoff=$((backoff * 2))
|
backoff=$((backoff * 2))
|
||||||
((backoff > 30)) && backoff=30
|
((backoff > 30)) && backoff=30
|
||||||
# Double --max-time on each retry so slow connections can finish
|
|
||||||
timeout=$((timeout * 2))
|
|
||||||
((attempt++))
|
((attempt++))
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -174,10 +172,8 @@ curl_api_with_retry() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
debug_log "curl API attempt $attempt failed (HTTP $http_code, timeout=${timeout}s), waiting ${attempt}s..."
|
debug_log "curl API attempt $attempt failed (HTTP $http_code), waiting ${attempt}s..."
|
||||||
sleep "$attempt"
|
sleep "$attempt"
|
||||||
# Double --max-time on each retry so slow connections can finish
|
|
||||||
timeout=$((timeout * 2))
|
|
||||||
((attempt++))
|
((attempt++))
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -938,11 +934,7 @@ upgrade_package() {
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Repository availability check with caching
|
# Repository availability check with caching
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Note: Must use -gA (global) because tools.func is sourced inside update_os()
|
declare -A _REPO_CACHE 2>/dev/null || true
|
||||||
# function scope. Plain 'declare -A' would create a local variable that gets
|
|
||||||
# destroyed when update_os() returns, causing "unbound variable" errors later
|
|
||||||
# when setup_postgresql/verify_repo_available tries to access the cache key.
|
|
||||||
declare -gA _REPO_CACHE 2>/dev/null || declare -A _REPO_CACHE 2>/dev/null || true
|
|
||||||
|
|
||||||
verify_repo_available() {
|
verify_repo_available() {
|
||||||
local repo_url="$1"
|
local repo_url="$1"
|
||||||
@@ -973,43 +965,13 @@ verify_repo_available() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Ensure dependencies are installed (with apt/apk update caching)
|
# Ensure dependencies are installed (with apt update caching)
|
||||||
# Supports both Debian (apt/dpkg) and Alpine (apk) systems
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
ensure_dependencies() {
|
ensure_dependencies() {
|
||||||
local deps=("$@")
|
local deps=("$@")
|
||||||
local missing=()
|
local missing=()
|
||||||
|
|
||||||
# Detect Alpine Linux
|
# Fast batch check using dpkg-query (much faster than individual checks)
|
||||||
if [[ -f /etc/alpine-release ]]; then
|
|
||||||
for dep in "${deps[@]}"; do
|
|
||||||
if command -v "$dep" &>/dev/null; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if apk info -e "$dep" &>/dev/null; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
missing+=("$dep")
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
||||||
$STD apk add --no-cache "${missing[@]}" || {
|
|
||||||
local failed=()
|
|
||||||
for pkg in "${missing[@]}"; do
|
|
||||||
if ! $STD apk add --no-cache "$pkg" 2>/dev/null; then
|
|
||||||
failed+=("$pkg")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [[ ${#failed[@]} -gt 0 ]]; then
|
|
||||||
msg_error "Failed to install dependencies: ${failed[*]}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Debian/Ubuntu: Fast batch check using dpkg-query
|
|
||||||
local installed_pkgs
|
local installed_pkgs
|
||||||
installed_pkgs=$(dpkg-query -W -f='${Package}\n' 2>/dev/null | sort -u)
|
installed_pkgs=$(dpkg-query -W -f='${Package}\n' 2>/dev/null | sort -u)
|
||||||
|
|
||||||
@@ -1106,53 +1068,11 @@ create_temp_dir() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Check if package is installed (supports both Debian and Alpine)
|
# Check if package is installed (faster than dpkg -l | grep)
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
is_package_installed() {
|
is_package_installed() {
|
||||||
local package="$1"
|
local package="$1"
|
||||||
if [[ -f /etc/alpine-release ]]; then
|
dpkg-query -W -f='${Status}' "$package" 2>/dev/null | grep -q "^install ok installed$"
|
||||||
apk info -e "$package" &>/dev/null
|
|
||||||
else
|
|
||||||
dpkg-query -W -f='${Status}' "$package" 2>/dev/null | grep -q "^install ok installed$"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Prompt user to enter a GitHub Personal Access Token (PAT) interactively
|
|
||||||
# Returns 0 if a valid token was provided, 1 otherwise
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
prompt_for_github_token() {
|
|
||||||
if [[ ! -t 0 ]]; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local reply
|
|
||||||
read -rp "${TAB}Would you like to enter a GitHub Personal Access Token (PAT)? [y/N]: " reply
|
|
||||||
reply="${reply:-n}"
|
|
||||||
|
|
||||||
if [[ ! "${reply,,}" =~ ^(y|yes)$ ]]; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local token
|
|
||||||
while true; do
|
|
||||||
read -rp "${TAB}Enter your GitHub PAT: " token
|
|
||||||
# Trim leading/trailing whitespace
|
|
||||||
token="$(echo "$token" | xargs)"
|
|
||||||
if [[ -z "$token" ]]; then
|
|
||||||
msg_warn "Token cannot be empty. Please try again."
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if [[ "$token" =~ [[:space:]] ]]; then
|
|
||||||
msg_warn "Token must not contain spaces. Please try again."
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
break
|
|
||||||
done
|
|
||||||
|
|
||||||
export GITHUB_TOKEN="$token"
|
|
||||||
msg_ok "GitHub token has been set."
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -1167,8 +1087,7 @@ github_api_call() {
|
|||||||
local header_args=()
|
local header_args=()
|
||||||
[[ -n "${GITHUB_TOKEN:-}" ]] && header_args=(-H "Authorization: Bearer $GITHUB_TOKEN")
|
[[ -n "${GITHUB_TOKEN:-}" ]] && header_args=(-H "Authorization: Bearer $GITHUB_TOKEN")
|
||||||
|
|
||||||
local attempt=1
|
for attempt in $(seq 1 $max_retries); do
|
||||||
while ((attempt <= max_retries)); do
|
|
||||||
local http_code
|
local http_code
|
||||||
http_code=$(curl -sSL -w "%{http_code}" -o "$output_file" \
|
http_code=$(curl -sSL -w "%{http_code}" -o "$output_file" \
|
||||||
-H "Accept: application/vnd.github+json" \
|
-H "Accept: application/vnd.github+json" \
|
||||||
@@ -1185,11 +1104,7 @@ github_api_call() {
|
|||||||
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
|
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
|
||||||
msg_error "Your GITHUB_TOKEN appears to be invalid or expired."
|
msg_error "Your GITHUB_TOKEN appears to be invalid or expired."
|
||||||
else
|
else
|
||||||
msg_error "The repository may require authentication."
|
msg_error "The repository may require authentication. Try: export GITHUB_TOKEN=\"ghp_your_token\""
|
||||||
fi
|
|
||||||
if prompt_for_github_token; then
|
|
||||||
header_args=(-H "Authorization: Bearer $GITHUB_TOKEN")
|
|
||||||
continue
|
|
||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
;;
|
;;
|
||||||
@@ -1199,16 +1114,9 @@ github_api_call() {
|
|||||||
msg_warn "GitHub API rate limit, waiting ${retry_delay}s... (attempt $attempt/$max_retries)"
|
msg_warn "GitHub API rate limit, waiting ${retry_delay}s... (attempt $attempt/$max_retries)"
|
||||||
sleep "$retry_delay"
|
sleep "$retry_delay"
|
||||||
retry_delay=$((retry_delay * 2))
|
retry_delay=$((retry_delay * 2))
|
||||||
((attempt++))
|
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
msg_error "GitHub API rate limit exceeded (HTTP 403)."
|
msg_error "GitHub API rate limit exceeded (HTTP 403)."
|
||||||
if prompt_for_github_token; then
|
|
||||||
header_args=(-H "Authorization: Bearer $GITHUB_TOKEN")
|
|
||||||
retry_delay=2
|
|
||||||
attempt=1
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
msg_error "To increase the limit, export a GitHub token before running the script:"
|
msg_error "To increase the limit, export a GitHub token before running the script:"
|
||||||
msg_error " export GITHUB_TOKEN=\"ghp_your_token_here\""
|
msg_error " export GITHUB_TOKEN=\"ghp_your_token_here\""
|
||||||
return 1
|
return 1
|
||||||
@@ -1220,7 +1128,6 @@ github_api_call() {
|
|||||||
000 | "")
|
000 | "")
|
||||||
if [[ $attempt -lt $max_retries ]]; then
|
if [[ $attempt -lt $max_retries ]]; then
|
||||||
sleep "$retry_delay"
|
sleep "$retry_delay"
|
||||||
((attempt++))
|
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
msg_error "GitHub API connection failed (no response)."
|
msg_error "GitHub API connection failed (no response)."
|
||||||
@@ -1230,14 +1137,12 @@ github_api_call() {
|
|||||||
*)
|
*)
|
||||||
if [[ $attempt -lt $max_retries ]]; then
|
if [[ $attempt -lt $max_retries ]]; then
|
||||||
sleep "$retry_delay"
|
sleep "$retry_delay"
|
||||||
((attempt++))
|
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
msg_error "GitHub API call failed (HTTP $http_code)."
|
msg_error "GitHub API call failed (HTTP $http_code)."
|
||||||
return 1
|
return 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
((attempt++))
|
|
||||||
done
|
done
|
||||||
|
|
||||||
msg_error "GitHub API call failed after ${max_retries} attempts: ${url}"
|
msg_error "GitHub API call failed after ${max_retries} attempts: ${url}"
|
||||||
@@ -1827,13 +1732,6 @@ setup_deb822_repo() {
|
|||||||
rm -f "$tmp_gpg"
|
rm -f "$tmp_gpg"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
else
|
|
||||||
# Already binary — copy directly
|
|
||||||
cp -f "$tmp_gpg" "/etc/apt/keyrings/${name}.gpg" || {
|
|
||||||
msg_error "Failed to install GPG key for ${name}"
|
|
||||||
rm -f "$tmp_gpg"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
fi
|
fi
|
||||||
rm -f "$tmp_gpg"
|
rm -f "$tmp_gpg"
|
||||||
chmod 644 "/etc/apt/keyrings/${name}.gpg"
|
chmod 644 "/etc/apt/keyrings/${name}.gpg"
|
||||||
@@ -1979,47 +1877,6 @@ extract_version_from_json() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Get latest GitHub tag (for repos that only publish tags, not releases).
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
# get_latest_gh_tag "owner/repo" [prefix]
|
|
||||||
#
|
|
||||||
# Arguments:
|
|
||||||
# $1 - GitHub repo (owner/repo)
|
|
||||||
# $2 - Optional prefix filter (e.g., "v" to only match tags starting with "v")
|
|
||||||
#
|
|
||||||
# Returns:
|
|
||||||
# Latest tag name (stdout), or returns 1 on failure
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
get_latest_gh_tag() {
|
|
||||||
local repo="$1"
|
|
||||||
local prefix="${2:-}"
|
|
||||||
local temp_file
|
|
||||||
temp_file=$(mktemp)
|
|
||||||
|
|
||||||
if ! github_api_call "https://api.github.com/repos/${repo}/tags?per_page=50" "$temp_file"; then
|
|
||||||
rm -f "$temp_file"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local tag=""
|
|
||||||
if [[ -n "$prefix" ]]; then
|
|
||||||
tag=$(jq -r --arg p "$prefix" '[.[] | select(.name | startswith($p))][0].name // empty' "$temp_file")
|
|
||||||
else
|
|
||||||
tag=$(jq -r '.[0].name // empty' "$temp_file")
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f "$temp_file"
|
|
||||||
|
|
||||||
if [[ -z "$tag" ]]; then
|
|
||||||
msg_error "No tags found for ${repo}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$tag"
|
|
||||||
}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Get latest GitHub release version with fallback to tags
|
# Get latest GitHub release version with fallback to tags
|
||||||
# Usage: get_latest_github_release "owner/repo" [strip_v] [include_prerelease]
|
# Usage: get_latest_github_release "owner/repo" [strip_v] [include_prerelease]
|
||||||
@@ -2118,129 +1975,101 @@ verify_gpg_fingerprint() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Fetches and deploys a GitHub tag-based source tarball.
|
# Get latest GitHub tag for a repository.
|
||||||
#
|
#
|
||||||
# Description:
|
# Description:
|
||||||
# - Downloads the source tarball for a given tag from GitHub
|
# - Queries the GitHub API for tags (not releases)
|
||||||
# - Extracts to the target directory
|
# - Useful for repos that only create tags, not full releases
|
||||||
# - Writes the version to ~/.<app>
|
# - Supports optional prefix filter and version-only extraction
|
||||||
|
# - Returns the latest tag name (printed to stdout)
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# fetch_and_deploy_gh_tag "guacd" "apache/guacamole-server"
|
# MONGO_VERSION=$(get_latest_gh_tag "mongodb/mongo-tools")
|
||||||
# fetch_and_deploy_gh_tag "guacd" "apache/guacamole-server" "latest" "/opt/guacamole-server"
|
# LATEST=$(get_latest_gh_tag "owner/repo" "v") # only tags starting with "v"
|
||||||
|
# LATEST=$(get_latest_gh_tag "owner/repo" "" "true") # strip leading "v"
|
||||||
#
|
#
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# $1 - App name (used for version file ~/.<app>)
|
# $1 - GitHub repo (owner/repo)
|
||||||
# $2 - GitHub repo (owner/repo)
|
# $2 - Tag prefix filter (optional, e.g. "v" or "100.")
|
||||||
# $3 - Tag version (default: "latest" → auto-detect via get_latest_gh_tag)
|
# $3 - Strip prefix from result (optional, "true" to strip $2 prefix)
|
||||||
# $4 - Target directory (default: /opt/$app)
|
#
|
||||||
|
# Returns:
|
||||||
|
# 0 on success (tag printed to stdout), 1 on failure
|
||||||
#
|
#
|
||||||
# Notes:
|
# Notes:
|
||||||
# - Supports CLEAN_INSTALL=1 to wipe target before extracting
|
# - Skips tags containing "rc", "alpha", "beta", "dev", "test"
|
||||||
# - For repos that only publish tags, not GitHub Releases
|
# - Sorts by version number (sort -V) to find the latest
|
||||||
|
# - Respects GITHUB_TOKEN for rate limiting
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
fetch_and_deploy_gh_tag() {
|
get_latest_gh_tag() {
|
||||||
local app="$1"
|
local repo="$1"
|
||||||
local repo="$2"
|
local prefix="${2:-}"
|
||||||
local version="${3:-latest}"
|
local strip_prefix="${3:-false}"
|
||||||
local target="${4:-/opt/$app}"
|
|
||||||
local app_lc=""
|
|
||||||
app_lc="$(echo "${app,,}" | tr -d ' ')"
|
|
||||||
local version_file="$HOME/.${app_lc}"
|
|
||||||
|
|
||||||
if [[ "$version" == "latest" ]]; then
|
local header_args=()
|
||||||
version=$(get_latest_gh_tag "$repo") || {
|
[[ -n "${GITHUB_TOKEN:-}" ]] && header_args=(-H "Authorization: Bearer $GITHUB_TOKEN")
|
||||||
msg_error "Failed to determine latest tag for ${repo}"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
local current_version=""
|
local http_code=""
|
||||||
[[ -f "$version_file" ]] && current_version=$(<"$version_file")
|
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o /tmp/gh_tags.json \
|
||||||
|
-H 'Accept: application/vnd.github+json' \
|
||||||
|
-H 'X-GitHub-Api-Version: 2022-11-28' \
|
||||||
|
"${header_args[@]}" \
|
||||||
|
"https://api.github.com/repos/${repo}/tags?per_page=100" 2>/dev/null) || true
|
||||||
|
|
||||||
if [[ "$current_version" == "$version" ]]; then
|
if [[ "$http_code" == "401" ]]; then
|
||||||
msg_ok "$app is already up-to-date ($version)"
|
msg_error "GitHub API authentication failed (HTTP 401)."
|
||||||
return 0
|
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
|
||||||
fi
|
msg_error "Your GITHUB_TOKEN appears to be invalid or expired."
|
||||||
|
else
|
||||||
local tmpdir
|
msg_error "The repository may require authentication. Try: export GITHUB_TOKEN=\"ghp_your_token\""
|
||||||
tmpdir=$(mktemp -d) || return 1
|
fi
|
||||||
local tarball_url="https://github.com/${repo}/archive/refs/tags/${version}.tar.gz"
|
rm -f /tmp/gh_tags.json
|
||||||
local filename="${app_lc}-${version}.tar.gz"
|
|
||||||
|
|
||||||
msg_info "Fetching GitHub tag: ${app} (${version})"
|
|
||||||
|
|
||||||
download_file "$tarball_url" "$tmpdir/$filename" || {
|
|
||||||
msg_error "Download failed: $tarball_url"
|
|
||||||
rm -rf "$tmpdir"
|
|
||||||
return 1
|
return 1
|
||||||
}
|
|
||||||
|
|
||||||
mkdir -p "$target"
|
|
||||||
if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
|
|
||||||
rm -rf "${target:?}/"*
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
tar --no-same-owner -xzf "$tmpdir/$filename" -C "$tmpdir" || {
|
if [[ "$http_code" == "403" ]]; then
|
||||||
msg_error "Failed to extract tarball"
|
msg_error "GitHub API rate limit exceeded (HTTP 403)."
|
||||||
rm -rf "$tmpdir"
|
msg_error "To increase the limit, export a GitHub token before running the script:"
|
||||||
|
msg_error " export GITHUB_TOKEN=\"ghp_your_token_here\""
|
||||||
|
rm -f /tmp/gh_tags.json
|
||||||
return 1
|
return 1
|
||||||
}
|
fi
|
||||||
|
|
||||||
local unpack_dir
|
if [[ "$http_code" == "000" || -z "$http_code" ]]; then
|
||||||
unpack_dir=$(find "$tmpdir" -mindepth 1 -maxdepth 1 -type d | head -n1)
|
msg_error "GitHub API connection failed (no response)."
|
||||||
|
msg_error "Check your network/DNS: curl -sSL https://api.github.com/rate_limit"
|
||||||
|
rm -f /tmp/gh_tags.json
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
shopt -s dotglob nullglob
|
if [[ "$http_code" != "200" ]] || [[ ! -s /tmp/gh_tags.json ]]; then
|
||||||
cp -r "$unpack_dir"/* "$target/"
|
msg_error "Unable to fetch tags for ${repo} (HTTP ${http_code})"
|
||||||
shopt -u dotglob nullglob
|
rm -f /tmp/gh_tags.json
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
rm -rf "$tmpdir"
|
local tags_json
|
||||||
echo "$version" >"$version_file"
|
tags_json=$(</tmp/gh_tags.json)
|
||||||
msg_ok "Deployed ${app} ${version} to ${target}"
|
rm -f /tmp/gh_tags.json
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Checks for new GitHub tag (for repos without releases).
|
|
||||||
#
|
|
||||||
# Description:
|
|
||||||
# - Uses get_latest_gh_tag to fetch the latest tag
|
|
||||||
# - Compares it to a local cached version (~/.<app>)
|
|
||||||
# - If newer, sets global CHECK_UPDATE_RELEASE and returns 0
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
# if check_for_gh_tag "guacd" "apache/guacamole-server"; then
|
|
||||||
# fetch_and_deploy_gh_tag "guacd" "apache/guacamole-server" "/opt/guacamole-server"
|
|
||||||
# fi
|
|
||||||
#
|
|
||||||
# Notes:
|
|
||||||
# - For repos that only publish tags, not GitHub Releases
|
|
||||||
# - Same interface as check_for_gh_release
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
check_for_gh_tag() {
|
|
||||||
local app="$1"
|
|
||||||
local repo="$2"
|
|
||||||
local prefix="${3:-}"
|
|
||||||
local app_lc=""
|
|
||||||
app_lc="$(echo "${app,,}" | tr -d ' ')"
|
|
||||||
local current_file="$HOME/.${app_lc}"
|
|
||||||
|
|
||||||
msg_info "Checking for update: ${app}"
|
|
||||||
|
|
||||||
|
# Extract tag names, filter by prefix, exclude pre-release patterns, sort by version
|
||||||
local latest=""
|
local latest=""
|
||||||
latest=$(get_latest_gh_tag "$repo" "$prefix") || return 1
|
latest=$(echo "$tags_json" | grep -oP '"name":\s*"\K[^"]+' |
|
||||||
|
{ [[ -n "$prefix" ]] && grep "^${prefix}" || cat; } |
|
||||||
|
grep -viE '(rc|alpha|beta|dev|test|preview|snapshot)' |
|
||||||
|
sort -V | tail -n1)
|
||||||
|
|
||||||
local current=""
|
if [[ -z "$latest" ]]; then
|
||||||
[[ -f "$current_file" ]] && current="$(<"$current_file")"
|
msg_warn "No matching tags found for ${repo}${prefix:+ (prefix: $prefix)}"
|
||||||
|
return 1
|
||||||
if [[ -z "$current" || "$current" != "$latest" ]]; then
|
|
||||||
CHECK_UPDATE_RELEASE="$latest"
|
|
||||||
msg_ok "Update available: ${app} ${current:-not installed} → ${latest}"
|
|
||||||
return 0
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_ok "No update available: ${app} (${latest})"
|
if [[ "$strip_prefix" == "true" && -n "$prefix" ]]; then
|
||||||
return 1
|
latest="${latest#"$prefix"}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$latest"
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
@@ -2292,35 +2121,6 @@ check_for_gh_release() {
|
|||||||
# Try /latest endpoint for non-pinned versions (most efficient)
|
# Try /latest endpoint for non-pinned versions (most efficient)
|
||||||
local releases_json="" http_code=""
|
local releases_json="" http_code=""
|
||||||
|
|
||||||
# For pinned versions, query the specific release tag directly
|
|
||||||
if [[ -n "$pinned_version_in" ]]; then
|
|
||||||
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o /tmp/gh_check.json \
|
|
||||||
-H 'Accept: application/vnd.github+json' \
|
|
||||||
-H 'X-GitHub-Api-Version: 2022-11-28' \
|
|
||||||
"${header_args[@]}" \
|
|
||||||
"https://api.github.com/repos/${source}/releases/tags/${pinned_version_in}" 2>/dev/null) || true
|
|
||||||
|
|
||||||
if [[ "$http_code" == "200" ]] && [[ -s /tmp/gh_check.json ]]; then
|
|
||||||
releases_json="[$(</tmp/gh_check.json)]"
|
|
||||||
elif [[ "$http_code" == "401" ]]; then
|
|
||||||
msg_error "GitHub API authentication failed (HTTP 401)."
|
|
||||||
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
|
|
||||||
msg_error "Your GITHUB_TOKEN appears to be invalid or expired."
|
|
||||||
else
|
|
||||||
msg_error "The repository may require authentication. Try: export GITHUB_TOKEN=\"ghp_your_token\""
|
|
||||||
fi
|
|
||||||
rm -f /tmp/gh_check.json
|
|
||||||
return 1
|
|
||||||
elif [[ "$http_code" == "403" ]]; then
|
|
||||||
msg_error "GitHub API rate limit exceeded (HTTP 403)."
|
|
||||||
msg_error "To increase the limit, export a GitHub token before running the script:"
|
|
||||||
msg_error " export GITHUB_TOKEN=\"ghp_your_token_here\""
|
|
||||||
rm -f /tmp/gh_check.json
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
rm -f /tmp/gh_check.json
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$pinned_version_in" ]]; then
|
if [[ -z "$pinned_version_in" ]]; then
|
||||||
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o /tmp/gh_check.json \
|
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o /tmp/gh_check.json \
|
||||||
-H 'Accept: application/vnd.github+json' \
|
-H 'Accept: application/vnd.github+json' \
|
||||||
@@ -2588,8 +2388,6 @@ check_for_codeberg_release() {
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
create_self_signed_cert() {
|
create_self_signed_cert() {
|
||||||
local APP_NAME="${1:-${APPLICATION}}"
|
local APP_NAME="${1:-${APPLICATION}}"
|
||||||
local HOSTNAME="$(hostname -f)"
|
|
||||||
local IP="$(hostname -I | awk '{print $1}')"
|
|
||||||
local APP_NAME_LC=$(echo "${APP_NAME,,}" | tr -d ' ')
|
local APP_NAME_LC=$(echo "${APP_NAME,,}" | tr -d ' ')
|
||||||
local CERT_DIR="/etc/ssl/${APP_NAME_LC}"
|
local CERT_DIR="/etc/ssl/${APP_NAME_LC}"
|
||||||
local CERT_KEY="${CERT_DIR}/${APP_NAME_LC}.key"
|
local CERT_KEY="${CERT_DIR}/${APP_NAME_LC}.key"
|
||||||
@@ -2607,8 +2405,8 @@ create_self_signed_cert() {
|
|||||||
|
|
||||||
mkdir -p "$CERT_DIR"
|
mkdir -p "$CERT_DIR"
|
||||||
$STD openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 \
|
$STD openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 \
|
||||||
-subj "/CN=${HOSTNAME}" \
|
-subj "/CN=${APP_NAME}" \
|
||||||
-addext "subjectAltName=DNS:${HOSTNAME},DNS:localhost,IP:${IP},IP:127.0.0.1" \
|
-addext "subjectAltName=DNS:${APP_NAME}" \
|
||||||
-keyout "$CERT_KEY" \
|
-keyout "$CERT_KEY" \
|
||||||
-out "$CERT_CRT" || {
|
-out "$CERT_CRT" || {
|
||||||
msg_error "Failed to create self-signed certificate"
|
msg_error "Failed to create self-signed certificate"
|
||||||
@@ -2678,30 +2476,6 @@ function ensure_usr_local_bin_persist() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# curl_download - Downloads a file with automatic retry and exponential backoff.
|
|
||||||
#
|
|
||||||
# Usage: curl_download <output_file> <url>
|
|
||||||
#
|
|
||||||
# Retries up to 5 times with increasing --max-time (60/120/240/480/960s).
|
|
||||||
# Returns 0 on success, 1 if all attempts fail.
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
function curl_download() {
|
|
||||||
local output="$1"
|
|
||||||
local url="$2"
|
|
||||||
local timeouts=(60 120 240 480 960)
|
|
||||||
|
|
||||||
for i in "${!timeouts[@]}"; do
|
|
||||||
if curl --connect-timeout 15 --max-time "${timeouts[$i]}" -fsSL -o "$output" "$url"; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
if ((i < ${#timeouts[@]} - 1)); then
|
|
||||||
msg_warn "Download timed out after ${timeouts[$i]}s, retrying... (attempt $((i + 2))/${#timeouts[@]})"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Downloads and deploys latest Codeberg release (source, binary, tarball, asset).
|
# Downloads and deploys latest Codeberg release (source, binary, tarball, asset).
|
||||||
#
|
#
|
||||||
@@ -2759,7 +2533,8 @@ function fetch_and_deploy_codeberg_release() {
|
|||||||
local app_lc=$(echo "${app,,}" | tr -d ' ')
|
local app_lc=$(echo "${app,,}" | tr -d ' ')
|
||||||
local version_file="$HOME/.${app_lc}"
|
local version_file="$HOME/.${app_lc}"
|
||||||
|
|
||||||
local api_timeouts=(60 120 240)
|
local api_timeout="--connect-timeout 10 --max-time 60"
|
||||||
|
local download_timeout="--connect-timeout 15 --max-time 900"
|
||||||
|
|
||||||
local current_version=""
|
local current_version=""
|
||||||
[[ -f "$version_file" ]] && current_version=$(<"$version_file")
|
[[ -f "$version_file" ]] && current_version=$(<"$version_file")
|
||||||
@@ -2799,7 +2574,7 @@ function fetch_and_deploy_codeberg_release() {
|
|||||||
|
|
||||||
# Codeberg archive URL format: https://codeberg.org/{owner}/{repo}/archive/{tag}.tar.gz
|
# Codeberg archive URL format: https://codeberg.org/{owner}/{repo}/archive/{tag}.tar.gz
|
||||||
local archive_url="https://codeberg.org/$repo/archive/${tag_name}.tar.gz"
|
local archive_url="https://codeberg.org/$repo/archive/${tag_name}.tar.gz"
|
||||||
if curl_download "$tmpdir/$filename" "$archive_url"; then
|
if curl $download_timeout -fsSL -o "$tmpdir/$filename" "$archive_url"; then
|
||||||
download_success=true
|
download_success=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -2846,18 +2621,16 @@ function fetch_and_deploy_codeberg_release() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local attempt=0 success=false resp http_code
|
local max_retries=3 retry_delay=2 attempt=1 success=false resp http_code
|
||||||
|
|
||||||
while ((attempt < ${#api_timeouts[@]})); do
|
while ((attempt <= max_retries)); do
|
||||||
resp=$(curl --connect-timeout 10 --max-time "${api_timeouts[$attempt]}" -fsSL -w "%{http_code}" -o /tmp/codeberg_rel.json "$api_url") && success=true && break
|
resp=$(curl $api_timeout -fsSL -w "%{http_code}" -o /tmp/codeberg_rel.json "$api_url") && success=true && break
|
||||||
|
sleep "$retry_delay"
|
||||||
((attempt++))
|
((attempt++))
|
||||||
if ((attempt < ${#api_timeouts[@]})); then
|
|
||||||
msg_warn "API request timed out after ${api_timeouts[$((attempt - 1))]}s, retrying... (attempt $((attempt + 1))/${#api_timeouts[@]})"
|
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
|
|
||||||
if ! $success; then
|
if ! $success; then
|
||||||
msg_error "Failed to fetch release metadata from $api_url after ${#api_timeouts[@]} attempts"
|
msg_error "Failed to fetch release metadata from $api_url after $max_retries attempts"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -2898,7 +2671,7 @@ function fetch_and_deploy_codeberg_release() {
|
|||||||
|
|
||||||
# Codeberg archive URL format
|
# Codeberg archive URL format
|
||||||
local archive_url="https://codeberg.org/$repo/archive/${tag_name}.tar.gz"
|
local archive_url="https://codeberg.org/$repo/archive/${tag_name}.tar.gz"
|
||||||
if curl_download "$tmpdir/$filename" "$archive_url"; then
|
if curl $download_timeout -fsSL -o "$tmpdir/$filename" "$archive_url"; then
|
||||||
download_success=true
|
download_success=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -2972,7 +2745,7 @@ function fetch_and_deploy_codeberg_release() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
filename="${url_match##*/}"
|
filename="${url_match##*/}"
|
||||||
curl_download "$tmpdir/$filename" "$url_match" || {
|
curl $download_timeout -fsSL -o "$tmpdir/$filename" "$url_match" || {
|
||||||
msg_error "Download failed: $url_match"
|
msg_error "Download failed: $url_match"
|
||||||
rm -rf "$tmpdir"
|
rm -rf "$tmpdir"
|
||||||
return 1
|
return 1
|
||||||
@@ -3015,7 +2788,7 @@ function fetch_and_deploy_codeberg_release() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
filename="${asset_url##*/}"
|
filename="${asset_url##*/}"
|
||||||
curl_download "$tmpdir/$filename" "$asset_url" || {
|
curl $download_timeout -fsSL -o "$tmpdir/$filename" "$asset_url" || {
|
||||||
msg_error "Download failed: $asset_url"
|
msg_error "Download failed: $asset_url"
|
||||||
rm -rf "$tmpdir"
|
rm -rf "$tmpdir"
|
||||||
return 1
|
return 1
|
||||||
@@ -3116,7 +2889,7 @@ function fetch_and_deploy_codeberg_release() {
|
|||||||
local target_file="$app"
|
local target_file="$app"
|
||||||
[[ "$use_filename" == "true" ]] && target_file="$filename"
|
[[ "$use_filename" == "true" ]] && target_file="$filename"
|
||||||
|
|
||||||
curl_download "$target/$target_file" "$asset_url" || {
|
curl $download_timeout -fsSL -o "$target/$target_file" "$asset_url" || {
|
||||||
msg_error "Download failed: $asset_url"
|
msg_error "Download failed: $asset_url"
|
||||||
rm -rf "$tmpdir"
|
rm -rf "$tmpdir"
|
||||||
return 1
|
return 1
|
||||||
@@ -3311,7 +3084,8 @@ function fetch_and_deploy_gh_release() {
|
|||||||
local app_lc=$(echo "${app,,}" | tr -d ' ')
|
local app_lc=$(echo "${app,,}" | tr -d ' ')
|
||||||
local version_file="$HOME/.${app_lc}"
|
local version_file="$HOME/.${app_lc}"
|
||||||
|
|
||||||
local api_timeouts=(60 120 240)
|
local api_timeout="--connect-timeout 10 --max-time 60"
|
||||||
|
local download_timeout="--connect-timeout 15 --max-time 900"
|
||||||
|
|
||||||
local current_version=""
|
local current_version=""
|
||||||
[[ -f "$version_file" ]] && current_version=$(<"$version_file")
|
[[ -f "$version_file" ]] && current_version=$(<"$version_file")
|
||||||
@@ -3331,37 +3105,18 @@ function fetch_and_deploy_gh_release() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local max_retries=${#api_timeouts[@]} retry_delay=2 attempt=1 success=false http_code
|
local max_retries=3 retry_delay=2 attempt=1 success=false http_code
|
||||||
|
|
||||||
while ((attempt <= max_retries)); do
|
while ((attempt <= max_retries)); do
|
||||||
http_code=$(curl --connect-timeout 10 --max-time "${api_timeouts[$((attempt - 1))]:-240}" -sSL -w "%{http_code}" -o /tmp/gh_rel.json "${header[@]}" "$api_url" 2>/dev/null) || true
|
http_code=$(curl $api_timeout -sSL -w "%{http_code}" -o /tmp/gh_rel.json "${header[@]}" "$api_url" 2>/dev/null) || true
|
||||||
if [[ "$http_code" == "200" ]]; then
|
if [[ "$http_code" == "200" ]]; then
|
||||||
success=true
|
success=true
|
||||||
break
|
break
|
||||||
elif [[ "$http_code" == "401" ]]; then
|
|
||||||
msg_error "GitHub API authentication failed (HTTP 401)."
|
|
||||||
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
|
|
||||||
msg_error "Your GITHUB_TOKEN appears to be invalid or expired."
|
|
||||||
else
|
|
||||||
msg_error "The repository may require authentication."
|
|
||||||
fi
|
|
||||||
if prompt_for_github_token; then
|
|
||||||
header=(-H "Authorization: token $GITHUB_TOKEN")
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
break
|
|
||||||
elif [[ "$http_code" == "403" ]]; then
|
elif [[ "$http_code" == "403" ]]; then
|
||||||
if ((attempt < max_retries)); then
|
if ((attempt < max_retries)); then
|
||||||
msg_warn "GitHub API rate limit hit, retrying in ${retry_delay}s... (attempt $attempt/$max_retries)"
|
msg_warn "GitHub API rate limit hit, retrying in ${retry_delay}s... (attempt $attempt/$max_retries)"
|
||||||
sleep "$retry_delay"
|
sleep "$retry_delay"
|
||||||
retry_delay=$((retry_delay * 2))
|
retry_delay=$((retry_delay * 2))
|
||||||
else
|
|
||||||
msg_error "GitHub API rate limit exceeded (HTTP 403)."
|
|
||||||
if prompt_for_github_token; then
|
|
||||||
header=(-H "Authorization: token $GITHUB_TOKEN")
|
|
||||||
retry_delay=2
|
|
||||||
attempt=0
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
sleep "$retry_delay"
|
sleep "$retry_delay"
|
||||||
@@ -3370,10 +3125,21 @@ function fetch_and_deploy_gh_release() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
if ! $success; then
|
if ! $success; then
|
||||||
if [[ "$http_code" == "000" || -z "$http_code" ]]; then
|
if [[ "$http_code" == "401" ]]; then
|
||||||
|
msg_error "GitHub API authentication failed (HTTP 401)."
|
||||||
|
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
|
||||||
|
msg_error "Your GITHUB_TOKEN appears to be invalid or expired."
|
||||||
|
else
|
||||||
|
msg_error "The repository may require authentication. Try: export GITHUB_TOKEN=\"ghp_your_token\""
|
||||||
|
fi
|
||||||
|
elif [[ "$http_code" == "403" ]]; then
|
||||||
|
msg_error "GitHub API rate limit exceeded (HTTP 403)."
|
||||||
|
msg_error "To increase the limit, export a GitHub token before running the script:"
|
||||||
|
msg_error " export GITHUB_TOKEN=\"ghp_your_token_here\""
|
||||||
|
elif [[ "$http_code" == "000" || -z "$http_code" ]]; then
|
||||||
msg_error "GitHub API connection failed (no response)."
|
msg_error "GitHub API connection failed (no response)."
|
||||||
msg_error "Check your network/DNS: curl -sSL https://api.github.com/rate_limit"
|
msg_error "Check your network/DNS: curl -sSL https://api.github.com/rate_limit"
|
||||||
elif [[ "$http_code" != "401" ]]; then
|
else
|
||||||
msg_error "Failed to fetch release metadata (HTTP $http_code)"
|
msg_error "Failed to fetch release metadata (HTTP $http_code)"
|
||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
@@ -3408,7 +3174,7 @@ function fetch_and_deploy_gh_release() {
|
|||||||
local direct_tarball_url="https://github.com/$repo/archive/refs/tags/$tag_name.tar.gz"
|
local direct_tarball_url="https://github.com/$repo/archive/refs/tags/$tag_name.tar.gz"
|
||||||
filename="${app_lc}-${version_safe}.tar.gz"
|
filename="${app_lc}-${version_safe}.tar.gz"
|
||||||
|
|
||||||
curl_download "$tmpdir/$filename" "$direct_tarball_url" || {
|
curl $download_timeout -fsSL -o "$tmpdir/$filename" "$direct_tarball_url" || {
|
||||||
msg_error "Download failed: $direct_tarball_url"
|
msg_error "Download failed: $direct_tarball_url"
|
||||||
rm -rf "$tmpdir"
|
rm -rf "$tmpdir"
|
||||||
return 1
|
return 1
|
||||||
@@ -3511,7 +3277,7 @@ function fetch_and_deploy_gh_release() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
filename="${url_match##*/}"
|
filename="${url_match##*/}"
|
||||||
curl_download "$tmpdir/$filename" "$url_match" || {
|
curl $download_timeout -fsSL -o "$tmpdir/$filename" "$url_match" || {
|
||||||
msg_error "Download failed: $url_match"
|
msg_error "Download failed: $url_match"
|
||||||
rm -rf "$tmpdir"
|
rm -rf "$tmpdir"
|
||||||
return 1
|
return 1
|
||||||
@@ -3578,7 +3344,7 @@ function fetch_and_deploy_gh_release() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
filename="${asset_url##*/}"
|
filename="${asset_url##*/}"
|
||||||
curl_download "$tmpdir/$filename" "$asset_url" || {
|
curl $download_timeout -fsSL -o "$tmpdir/$filename" "$asset_url" || {
|
||||||
msg_error "Download failed: $asset_url"
|
msg_error "Download failed: $asset_url"
|
||||||
rm -rf "$tmpdir"
|
rm -rf "$tmpdir"
|
||||||
return 1
|
return 1
|
||||||
@@ -3699,7 +3465,7 @@ function fetch_and_deploy_gh_release() {
|
|||||||
local target_file="$app"
|
local target_file="$app"
|
||||||
[[ "$use_filename" == "true" ]] && target_file="$filename"
|
[[ "$use_filename" == "true" ]] && target_file="$filename"
|
||||||
|
|
||||||
curl_download "$target/$target_file" "$asset_url" || {
|
curl $download_timeout -fsSL -o "$target/$target_file" "$asset_url" || {
|
||||||
msg_error "Download failed: $asset_url"
|
msg_error "Download failed: $asset_url"
|
||||||
rm -rf "$tmpdir"
|
rm -rf "$tmpdir"
|
||||||
return 1
|
return 1
|
||||||
@@ -4256,8 +4022,6 @@ function setup_gs() {
|
|||||||
# - NVIDIA requires matching host driver version
|
# - NVIDIA requires matching host driver version
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
function setup_hwaccel() {
|
function setup_hwaccel() {
|
||||||
local service_user="${1:-}"
|
|
||||||
|
|
||||||
# Check if user explicitly disabled GPU in advanced settings
|
# Check if user explicitly disabled GPU in advanced settings
|
||||||
# ENABLE_GPU is exported from build.func
|
# ENABLE_GPU is exported from build.func
|
||||||
if [[ "${ENABLE_GPU:-no}" == "no" ]]; then
|
if [[ "${ENABLE_GPU:-no}" == "no" ]]; then
|
||||||
@@ -4509,7 +4273,7 @@ function setup_hwaccel() {
|
|||||||
# ═══════════════════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════════════════
|
||||||
# Device Permissions
|
# Device Permissions
|
||||||
# ═══════════════════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════════════════
|
||||||
_setup_gpu_permissions "$in_ct" "$service_user"
|
_setup_gpu_permissions "$in_ct"
|
||||||
|
|
||||||
cache_installed_version "hwaccel" "1.0"
|
cache_installed_version "hwaccel" "1.0"
|
||||||
msg_ok "Setup Hardware Acceleration"
|
msg_ok "Setup Hardware Acceleration"
|
||||||
@@ -4676,8 +4440,9 @@ _setup_amd_gpu() {
|
|||||||
fi
|
fi
|
||||||
# Ubuntu includes AMD firmware in linux-firmware by default
|
# Ubuntu includes AMD firmware in linux-firmware by default
|
||||||
|
|
||||||
# ROCm compute stack (OpenCL + HIP)
|
# ROCm for compute (optional - large download)
|
||||||
_setup_rocm "$os_id" "$os_codename"
|
# Uncomment if needed:
|
||||||
|
# $STD apt -y install rocm-opencl-runtime 2>/dev/null || true
|
||||||
|
|
||||||
msg_ok "AMD GPU configured"
|
msg_ok "AMD GPU configured"
|
||||||
}
|
}
|
||||||
@@ -4705,109 +4470,6 @@ _setup_amd_apu() {
|
|||||||
msg_ok "AMD APU configured"
|
msg_ok "AMD APU configured"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ══════════════════════════════════════════════════════════════════════════════
|
|
||||||
# AMD ROCm Compute Setup
|
|
||||||
# Adds ROCm repository and installs the ROCm compute stack for AMD GPUs/APUs.
|
|
||||||
# Provides: OpenCL, HIP, rocm-smi, rocminfo
|
|
||||||
# Supported: Debian 12/13, Ubuntu 22.04/24.04 (amd64 only)
|
|
||||||
# ══════════════════════════════════════════════════════════════════════════════
|
|
||||||
_setup_rocm() {
|
|
||||||
local os_id="$1" os_codename="$2"
|
|
||||||
|
|
||||||
# Only amd64 is supported
|
|
||||||
if [[ "$(dpkg --print-architecture 2>/dev/null)" != "amd64" ]]; then
|
|
||||||
msg_warn "ROCm is only available for amd64 — skipping"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
local ROCM_VERSION="7.2"
|
|
||||||
local ROCM_REPO_CODENAME
|
|
||||||
|
|
||||||
# Map OS codename to ROCm repository codename (Ubuntu-based repos)
|
|
||||||
case "${os_id}-${os_codename}" in
|
|
||||||
debian-bookworm) ROCM_REPO_CODENAME="jammy" ;;
|
|
||||||
debian-trixie | debian-sid) ROCM_REPO_CODENAME="noble" ;;
|
|
||||||
ubuntu-jammy) ROCM_REPO_CODENAME="jammy" ;;
|
|
||||||
ubuntu-noble) ROCM_REPO_CODENAME="noble" ;;
|
|
||||||
*)
|
|
||||||
msg_warn "ROCm not supported on ${os_id} ${os_codename} — skipping"
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
msg_info "Installing ROCm ${ROCM_VERSION} compute stack"
|
|
||||||
|
|
||||||
# ROCm main repository (userspace compute libs)
|
|
||||||
setup_deb822_repo \
|
|
||||||
"rocm" \
|
|
||||||
"https://repo.radeon.com/rocm/rocm.gpg.key" \
|
|
||||||
"https://repo.radeon.com/rocm/apt/${ROCM_VERSION}" \
|
|
||||||
"${ROCM_REPO_CODENAME}" \
|
|
||||||
"main" \
|
|
||||||
"amd64" || {
|
|
||||||
msg_warn "Failed to add ROCm repository — skipping ROCm"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# Note: The amdgpu/latest/ubuntu repo (kernel driver packages) is intentionally
|
|
||||||
# omitted — kernel drivers are managed by the Proxmox host, not the LXC container.
|
|
||||||
# Only the ROCm userspace compute stack is needed inside the container.
|
|
||||||
|
|
||||||
# Pin ROCm packages to prefer radeon repo
|
|
||||||
cat <<EOF >/etc/apt/preferences.d/rocm-pin-600
|
|
||||||
Package: *
|
|
||||||
Pin: release o=repo.radeon.com
|
|
||||||
Pin-Priority: 600
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# apt update with retry — repo.radeon.com CDN can be mid-sync (transient size mismatches).
|
|
||||||
# Run with ERR trap disabled so a transient failure does not abort the entire install.
|
|
||||||
local _apt_ok=0
|
|
||||||
for _attempt in 1 2 3; do
|
|
||||||
if (
|
|
||||||
set +e
|
|
||||||
apt-get update -qq 2>&1
|
|
||||||
exit $?
|
|
||||||
) 2>/dev/null; then
|
|
||||||
_apt_ok=1
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
msg_warn "apt update failed (attempt ${_attempt}/3) — AMD repo may be temporarily unavailable, retrying in 30s…"
|
|
||||||
sleep 30
|
|
||||||
done
|
|
||||||
if [[ $_apt_ok -eq 0 ]]; then
|
|
||||||
msg_warn "apt update still failing after 3 attempts — skipping ROCm install"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install only runtime packages — full 'rocm' meta-package includes 15GB+ dev tools
|
|
||||||
$STD apt install -y rocm-opencl-runtime rocm-hip-runtime rocm-smi-lib 2>/dev/null || {
|
|
||||||
msg_warn "ROCm runtime install failed — trying minimal set"
|
|
||||||
$STD apt install -y rocm-opencl-runtime rocm-smi-lib 2>/dev/null || msg_warn "ROCm minimal install also failed"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Group membership for GPU access
|
|
||||||
usermod -aG render,video root 2>/dev/null || true
|
|
||||||
|
|
||||||
# Environment (PATH + LD_LIBRARY_PATH)
|
|
||||||
if [[ -d /opt/rocm ]]; then
|
|
||||||
cat <<'ENVEOF' >/etc/profile.d/rocm.sh
|
|
||||||
export PATH="$PATH:/opt/rocm/bin"
|
|
||||||
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}/opt/rocm/lib"
|
|
||||||
ENVEOF
|
|
||||||
chmod +x /etc/profile.d/rocm.sh
|
|
||||||
# Also make available for current session / systemd services
|
|
||||||
echo "/opt/rocm/lib" >/etc/ld.so.conf.d/rocm.conf
|
|
||||||
ldconfig 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -x /opt/rocm/bin/rocminfo ]]; then
|
|
||||||
msg_ok "ROCm ${ROCM_VERSION} installed"
|
|
||||||
else
|
|
||||||
msg_warn "ROCm installed but rocminfo not found — GPU may not be available in container"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# ══════════════════════════════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
# NVIDIA GPU Setup
|
# NVIDIA GPU Setup
|
||||||
# ══════════════════════════════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
@@ -4824,10 +4486,10 @@ _setup_nvidia_gpu() {
|
|||||||
# Format varies by driver type:
|
# Format varies by driver type:
|
||||||
# Proprietary: "NVRM version: NVIDIA UNIX x86_64 Kernel Module 550.54.14 Thu..."
|
# Proprietary: "NVRM version: NVIDIA UNIX x86_64 Kernel Module 550.54.14 Thu..."
|
||||||
# Open: "NVRM version: NVIDIA UNIX Open Kernel Module for x86_64 590.48.01 Release..."
|
# Open: "NVRM version: NVIDIA UNIX Open Kernel Module for x86_64 590.48.01 Release..."
|
||||||
# Use regex to extract version number (###.##.## or ###.## pattern)
|
# Use regex to extract version number (###.##.## pattern)
|
||||||
local nvidia_host_version=""
|
local nvidia_host_version=""
|
||||||
if [[ -f /proc/driver/nvidia/version ]]; then
|
if [[ -f /proc/driver/nvidia/version ]]; then
|
||||||
nvidia_host_version=$(grep -oP '\d{3,}\.\d+(\.\d+)?' /proc/driver/nvidia/version 2>/dev/null | head -1)
|
nvidia_host_version=$(grep -oP '\d{3,}\.\d+\.\d+' /proc/driver/nvidia/version 2>/dev/null | head -1)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "$nvidia_host_version" ]]; then
|
if [[ -z "$nvidia_host_version" ]]; then
|
||||||
@@ -5143,7 +4805,6 @@ EOF
|
|||||||
# ══════════════════════════════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
_setup_gpu_permissions() {
|
_setup_gpu_permissions() {
|
||||||
local in_ct="$1"
|
local in_ct="$1"
|
||||||
local service_user="${2:-}"
|
|
||||||
|
|
||||||
# /dev/dri permissions (Intel/AMD)
|
# /dev/dri permissions (Intel/AMD)
|
||||||
if [[ "$in_ct" == "0" && -d /dev/dri ]]; then
|
if [[ "$in_ct" == "0" && -d /dev/dri ]]; then
|
||||||
@@ -5210,12 +4871,6 @@ _setup_gpu_permissions() {
|
|||||||
chmod 666 /dev/kfd 2>/dev/null || true
|
chmod 666 /dev/kfd 2>/dev/null || true
|
||||||
msg_info "AMD ROCm compute device configured"
|
msg_info "AMD ROCm compute device configured"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Add service user to render and video groups for GPU hardware acceleration
|
|
||||||
if [[ -n "$service_user" ]]; then
|
|
||||||
$STD usermod -aG render "$service_user" 2>/dev/null || true
|
|
||||||
$STD usermod -aG video "$service_user" 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -5487,7 +5142,7 @@ current_ip="$(get_current_ip)"
|
|||||||
|
|
||||||
if [[ -z "$current_ip" ]]; then
|
if [[ -z "$current_ip" ]]; then
|
||||||
echo "[ERROR] Could not detect local IP" >&2
|
echo "[ERROR] Could not detect local IP" >&2
|
||||||
exit 123
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -f "$IP_FILE" ]]; then
|
if [[ -f "$IP_FILE" ]]; then
|
||||||
@@ -5988,20 +5643,20 @@ function setup_mongodb() {
|
|||||||
# - Handles Debian Trixie libaio1t64 transition
|
# - Handles Debian Trixie libaio1t64 transition
|
||||||
#
|
#
|
||||||
# Variables:
|
# Variables:
|
||||||
# USE_MYSQL_REPO - Use official MySQL repository (default: true)
|
# USE_MYSQL_REPO - Set to "true" to use official MySQL repository
|
||||||
# Set to "false" to use distro packages instead
|
# (default: false, uses distro packages)
|
||||||
# MYSQL_VERSION - MySQL version to install when using official repo
|
# MYSQL_VERSION - MySQL version to install when using official repo
|
||||||
# (e.g. 8.0, 8.4) (default: 8.0)
|
# (e.g. 8.0, 8.4) (default: 8.0)
|
||||||
#
|
#
|
||||||
# Examples:
|
# Examples:
|
||||||
# setup_mysql # Uses official MySQL repo, 8.0
|
# setup_mysql # Uses distro package (recommended)
|
||||||
# MYSQL_VERSION="8.4" setup_mysql # Specific version from MySQL repo
|
# USE_MYSQL_REPO=true setup_mysql # Uses official MySQL repo
|
||||||
# USE_MYSQL_REPO=false setup_mysql # Uses distro package instead
|
# USE_MYSQL_REPO=true MYSQL_VERSION="8.4" setup_mysql # Specific version
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
function setup_mysql() {
|
function setup_mysql() {
|
||||||
local MYSQL_VERSION="${MYSQL_VERSION:-8.0}"
|
local MYSQL_VERSION="${MYSQL_VERSION:-8.0}"
|
||||||
local USE_MYSQL_REPO="${USE_MYSQL_REPO:-true}"
|
local USE_MYSQL_REPO="${USE_MYSQL_REPO:-false}"
|
||||||
local DISTRO_ID DISTRO_CODENAME
|
local DISTRO_ID DISTRO_CODENAME
|
||||||
DISTRO_ID=$(awk -F= '/^ID=/{print $2}' /etc/os-release | tr -d '"')
|
DISTRO_ID=$(awk -F= '/^ID=/{print $2}' /etc/os-release | tr -d '"')
|
||||||
DISTRO_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release)
|
DISTRO_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release)
|
||||||
|
|||||||
@@ -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://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/LICENSE
|
# License: MIT | https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/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://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/LICENSE
|
# License: MIT | https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/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://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/${app_type}/headers/${app_name}"
|
local header_url="https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/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")"
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.or
|
|||||||
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
||||||
|
|
||||||
function header_info {
|
function header_info {
|
||||||
clear
|
clear
|
||||||
cat <<"EOF"
|
cat <<"EOF"
|
||||||
___ __ __ _ _ ____ ___
|
___ __ __ _ _ ____ ___
|
||||||
/ | __________/ /_ / / (_)___ __ ___ __ | | / / |/ /
|
/ | __________/ /_ / / (_)___ __ ___ __ | | / / |/ /
|
||||||
/ /| | / ___/ ___/ __ \ / / / / __ \/ / / / |/_/ | | / / /|_/ /
|
/ /| | / ___/ ___/ __ \ / / / / __ \/ / / / |/_/ | | / / /|_/ /
|
||||||
@@ -66,340 +66,340 @@ trap cleanup EXIT
|
|||||||
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
||||||
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
||||||
function error_handler() {
|
function error_handler() {
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
local line_number="$1"
|
local line_number="$1"
|
||||||
local command="$2"
|
local command="$2"
|
||||||
post_update_to_api "failed" "${commad}"
|
post_update_to_api "failed" "${commad}"
|
||||||
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
||||||
echo -e "\n$error_message\n"
|
echo -e "\n$error_message\n"
|
||||||
cleanup_vmid
|
cleanup_vmid
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_valid_nextid() {
|
function get_valid_nextid() {
|
||||||
local try_id
|
local try_id
|
||||||
try_id=$(pvesh get /cluster/nextid)
|
try_id=$(pvesh get /cluster/nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
break
|
break
|
||||||
done
|
done
|
||||||
echo "$try_id"
|
echo "$try_id"
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup_vmid() {
|
function cleanup_vmid() {
|
||||||
if qm status $VMID &>/dev/null; then
|
if qm status $VMID &>/dev/null; then
|
||||||
qm stop $VMID &>/dev/null
|
qm stop $VMID &>/dev/null
|
||||||
qm destroy $VMID &>/dev/null
|
qm destroy $VMID &>/dev/null
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
pushd $TEMP_DIR >/dev/null
|
pushd $TEMP_DIR >/dev/null
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Arch Linux VM" --yesno "This will create a New Arch Linux VM. Proceed?" 10 58; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Arch Linux VM" --yesno "This will create a New Arch Linux VM. Proceed?" 10 58; then
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
|
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function msg_info() {
|
function msg_info() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
|
echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_ok() {
|
function msg_ok() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_error() {
|
function msg_error() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_root() {
|
function check_root() {
|
||||||
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
||||||
clear
|
clear
|
||||||
msg_error "Please run this script as root."
|
msg_error "Please run this script as root."
|
||||||
echo -e "\nExiting..."
|
echo -e "\nExiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function pve_check() {
|
function pve_check() {
|
||||||
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
||||||
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
||||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function arch_check() {
|
function arch_check() {
|
||||||
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
||||||
echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
|
echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
|
||||||
echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
|
echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function ssh_check() {
|
function ssh_check() {
|
||||||
if command -v pveversion >/dev/null 2>&1; then
|
if command -v pveversion >/dev/null 2>&1; then
|
||||||
if [ -n "${SSH_CLIENT:+x}" ]; then
|
if [ -n "${SSH_CLIENT:+x}" ]; then
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
||||||
echo "you've been warned"
|
echo "you've been warned"
|
||||||
else
|
else
|
||||||
clear
|
clear
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function exit-script() {
|
function exit-script() {
|
||||||
clear
|
clear
|
||||||
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
|
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
MACHINE=""
|
MACHINE=""
|
||||||
DISK_SIZE="4G"
|
DISK_SIZE="4G"
|
||||||
DISK_CACHE=""
|
DISK_CACHE=""
|
||||||
HN="arch-linux"
|
HN="arch-linux"
|
||||||
CPU_TYPE=""
|
CPU_TYPE=""
|
||||||
CORE_COUNT="1"
|
CORE_COUNT="1"
|
||||||
RAM_SIZE="1024"
|
RAM_SIZE="1024"
|
||||||
BRG="vmbr0"
|
BRG="vmbr0"
|
||||||
MAC="$GEN_MAC"
|
MAC="$GEN_MAC"
|
||||||
VLAN=""
|
VLAN=""
|
||||||
MTU=""
|
MTU=""
|
||||||
START_VM="yes"
|
START_VM="yes"
|
||||||
METHOD="default"
|
METHOD="default"
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
echo -e "${CREATING}${BOLD}${DGN}Creating a Arch Linux VM using the above default settings${CL}"
|
echo -e "${CREATING}${BOLD}${DGN}Creating a Arch Linux VM using the above default settings${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function advanced_settings() {
|
function advanced_settings() {
|
||||||
METHOD="advanced"
|
METHOD="advanced"
|
||||||
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z "$VMID" ]; then
|
if [ -z "$VMID" ]; then
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
fi
|
fi
|
||||||
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
||||||
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
||||||
sleep 2
|
sleep 2
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
||||||
break
|
break
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
||||||
|
"i440fx" "Machine i440fx" ON \
|
||||||
|
"q35" "Machine q35" OFF \
|
||||||
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $MACH = q35 ]; then
|
||||||
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=""
|
||||||
|
MACHINE=" -machine q35"
|
||||||
|
else
|
||||||
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=",efitype=4m"
|
||||||
|
MACHINE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
exit-script
|
exit-script
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
|
||||||
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"i440fx" "Machine i440fx" ON \
|
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
|
||||||
"q35" "Machine q35" OFF \
|
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
|
||||||
3>&1 1>&2 2>&3); then
|
DISK_SIZE="${DISK_SIZE}G"
|
||||||
if [ $MACH = q35 ]; then
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
|
||||||
FORMAT=""
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
||||||
MACHINE=" -machine q35"
|
else
|
||||||
|
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
exit-script
|
||||||
FORMAT=",efitype=4m"
|
|
||||||
MACHINE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
|
"0" "None (Default)" ON \
|
||||||
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
|
"1" "Write Through" OFF \
|
||||||
DISK_SIZE="${DISK_SIZE}G"
|
3>&1 1>&2 2>&3); then
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
if [ $DISK_CACHE = "1" ]; then
|
||||||
elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
DISK_CACHE="cache=writethrough,"
|
||||||
|
else
|
||||||
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
||||||
|
DISK_CACHE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
|
exit-script
|
||||||
exit-script
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 arch-linux --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "None (Default)" ON \
|
if [ -z $VM_NAME ]; then
|
||||||
"1" "Write Through" OFF \
|
HN="arch-linux"
|
||||||
3>&1 1>&2 2>&3); then
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
if [ $DISK_CACHE = "1" ]; then
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
|
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
||||||
DISK_CACHE="cache=writethrough,"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
exit-script
|
||||||
DISK_CACHE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 arch-linux --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
if [ -z $VM_NAME ]; then
|
"0" "KVM64 (Default)" ON \
|
||||||
HN="arch-linux"
|
"1" "Host" OFF \
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $CPU_TYPE1 = "1" ]; then
|
||||||
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
|
||||||
|
CPU_TYPE=" -cpu host"
|
||||||
|
else
|
||||||
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
||||||
|
CPU_TYPE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
exit-script
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "KVM64 (Default)" ON \
|
if [ -z $CORE_COUNT ]; then
|
||||||
"1" "Host" OFF \
|
CORE_COUNT="2"
|
||||||
3>&1 1>&2 2>&3); then
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
if [ $CPU_TYPE1 = "1" ]; then
|
else
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
CPU_TYPE=" -cpu host"
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
exit-script
|
||||||
CPU_TYPE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $CORE_COUNT ]; then
|
if [ -z $RAM_SIZE ]; then
|
||||||
CORE_COUNT="2"
|
RAM_SIZE="2048"
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $RAM_SIZE ]; then
|
if [ -z $BRG ]; then
|
||||||
RAM_SIZE="2048"
|
BRG="vmbr0"
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $BRG ]; then
|
if [ -z $MAC1 ]; then
|
||||||
BRG="vmbr0"
|
MAC="$GEN_MAC"
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
|
||||||
|
else
|
||||||
|
MAC="$MAC1"
|
||||||
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $MAC1 ]; then
|
if [ -z $VLAN1 ]; then
|
||||||
MAC="$GEN_MAC"
|
VLAN1="Default"
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
|
VLAN=""
|
||||||
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
||||||
|
else
|
||||||
|
VLAN=",tag=$VLAN1"
|
||||||
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
MAC="$MAC1"
|
exit-script
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $VLAN1 ]; then
|
if [ -z $MTU1 ]; then
|
||||||
VLAN1="Default"
|
MTU1="Default"
|
||||||
VLAN=""
|
MTU=""
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
else
|
||||||
|
MTU=",mtu=$MTU1"
|
||||||
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
VLAN=",tag=$VLAN1"
|
exit-script
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
||||||
if [ -z $MTU1 ]; then
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
MTU1="Default"
|
START_VM="yes"
|
||||||
MTU=""
|
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
|
||||||
else
|
else
|
||||||
MTU=",mtu=$MTU1"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
START_VM="no"
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Arch Linux VM?" --no-button Do-Over 10 58); then
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
echo -e "${CREATING}${BOLD}${DGN}Creating a Arch Linux VM using the above advanced settings${CL}"
|
||||||
START_VM="yes"
|
else
|
||||||
else
|
header_info
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
|
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
||||||
START_VM="no"
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Arch Linux VM?" --no-button Do-Over 10 58); then
|
|
||||||
echo -e "${CREATING}${BOLD}${DGN}Creating a Arch Linux VM using the above advanced settings${CL}"
|
|
||||||
else
|
|
||||||
header_info
|
|
||||||
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
|
||||||
advanced_settings
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function start_script() {
|
function start_script() {
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
||||||
header_info
|
header_info
|
||||||
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
|
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
|
||||||
default_settings
|
default_settings
|
||||||
else
|
else
|
||||||
header_info
|
header_info
|
||||||
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
||||||
advanced_settings
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
check_root
|
check_root
|
||||||
@@ -411,29 +411,29 @@ post_to_api_vm
|
|||||||
|
|
||||||
msg_info "Validating Storage"
|
msg_info "Validating Storage"
|
||||||
while read -r line; do
|
while read -r line; do
|
||||||
TAG=$(echo $line | awk '{print $1}')
|
TAG=$(echo $line | awk '{print $1}')
|
||||||
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
||||||
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
||||||
ITEM=" Type: $TYPE Free: $FREE "
|
ITEM=" Type: $TYPE Free: $FREE "
|
||||||
OFFSET=2
|
OFFSET=2
|
||||||
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
||||||
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
||||||
fi
|
fi
|
||||||
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
||||||
done < <(pvesm status -content images | awk 'NR>1')
|
done < <(pvesm status -content images | awk 'NR>1')
|
||||||
VALID=$(pvesm status -content images | awk 'NR>1')
|
VALID=$(pvesm status -content images | awk 'NR>1')
|
||||||
if [ -z "$VALID" ]; then
|
if [ -z "$VALID" ]; then
|
||||||
msg_error "Unable to detect a valid storage location."
|
msg_error "Unable to detect a valid storage location."
|
||||||
exit
|
exit
|
||||||
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
||||||
STORAGE=${STORAGE_MENU[0]}
|
STORAGE=${STORAGE_MENU[0]}
|
||||||
else
|
else
|
||||||
while [ -z "${STORAGE:+x}" ]; do
|
while [ -z "${STORAGE:+x}" ]; do
|
||||||
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
||||||
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
||||||
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
||||||
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
||||||
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
||||||
@@ -449,38 +449,38 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
|
|||||||
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
||||||
case $STORAGE_TYPE in
|
case $STORAGE_TYPE in
|
||||||
nfs | dir | cifs)
|
nfs | dir | cifs)
|
||||||
DISK_EXT=".qcow2"
|
DISK_EXT=".qcow2"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format qcow2"
|
DISK_IMPORT="-format qcow2"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
btrfs)
|
btrfs)
|
||||||
DISK_EXT=".raw"
|
DISK_EXT=".raw"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format raw"
|
DISK_IMPORT="-format raw"
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
for i in {0,1}; do
|
for i in {0,1}; do
|
||||||
disk="DISK$i"
|
disk="DISK$i"
|
||||||
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
||||||
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
||||||
done
|
done
|
||||||
|
|
||||||
msg_info "Creating a Arch Linux VM"
|
msg_info "Creating a Arch Linux VM"
|
||||||
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
||||||
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
|
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
|
||||||
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
||||||
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
||||||
qm set $VMID \
|
qm set $VMID \
|
||||||
-efidisk0 ${DISK0_REF}${FORMAT} \
|
-efidisk0 ${DISK0_REF}${FORMAT} \
|
||||||
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
|
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
|
||||||
-ide2 ${STORAGE}:cloudinit \
|
-ide2 ${STORAGE}:cloudinit \
|
||||||
-boot order=scsi0 \
|
-boot order=scsi0 \
|
||||||
-serial0 socket >/dev/null
|
-serial0 socket >/dev/null
|
||||||
DESCRIPTION=$(
|
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://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
<img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
||||||
@@ -511,18 +511,18 @@ EOF
|
|||||||
)
|
)
|
||||||
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
||||||
if [ -n "$DISK_SIZE" ]; then
|
if [ -n "$DISK_SIZE" ]; then
|
||||||
msg_info "Resizing disk to $DISK_SIZE GB"
|
msg_info "Resizing disk to $DISK_SIZE GB"
|
||||||
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
|
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
|
||||||
else
|
else
|
||||||
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
|
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
|
||||||
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
|
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_ok "Created a Arch Linux VM ${CL}${BL}(${HN})"
|
msg_ok "Created a Arch Linux VM ${CL}${BL}(${HN})"
|
||||||
if [ "$START_VM" == "yes" ]; then
|
if [ "$START_VM" == "yes" ]; then
|
||||||
msg_info "Starting Arch Linux VM"
|
msg_info "Starting Arch Linux VM"
|
||||||
qm start $VMID
|
qm start $VMID
|
||||||
msg_ok "Started Arch Linux VM"
|
msg_ok "Started Arch Linux VM"
|
||||||
fi
|
fi
|
||||||
post_update_to_api "done" "none"
|
post_update_to_api "done" "none"
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# CachyOS VM - Creates a CachyOS Virtual Machine
|
# CachyOS VM - Creates a CachyOS Virtual Machine
|
||||||
# CachyOS is a performance-focused Arch Linux distribution with optimized
|
# CachyOS is a performance-focused Arch Linux distribution with optimized
|
||||||
# packages, custom kernels, and various desktop environment options.
|
# packages, custom kernels, and various desktop environment options.
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
|||||||
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/helpers.func")
|
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/helpers.func")
|
||||||
|
|
||||||
function header_info {
|
function header_info {
|
||||||
clear
|
clear
|
||||||
cat <<"EOF"
|
cat <<"EOF"
|
||||||
____ __ _ ______
|
____ __ _ ______
|
||||||
/ __ \___ / /_ (_)___ _____ < /__ \
|
/ __ \___ / /_ (_)___ _____ < /__ \
|
||||||
/ / / / _ \/ __ \/ / __ `/ __ \ / /__/ /
|
/ / / / _ \/ __ \/ / __ `/ __ \ / /__/ /
|
||||||
@@ -38,247 +38,247 @@ trap cleanup EXIT
|
|||||||
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
||||||
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
||||||
function error_handler() {
|
function error_handler() {
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
local line_number="$1"
|
local line_number="$1"
|
||||||
local command="$2"
|
local command="$2"
|
||||||
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
||||||
post_update_to_api "failed" "${command}"
|
post_update_to_api "failed" "${command}"
|
||||||
echo -e "\n$error_message\n"
|
echo -e "\n$error_message\n"
|
||||||
cleanup_vmid
|
cleanup_vmid
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup_vmid() {
|
function cleanup_vmid() {
|
||||||
if qm status $VMID &>/dev/null; then
|
if qm status $VMID &>/dev/null; then
|
||||||
qm stop $VMID &>/dev/null
|
qm stop $VMID &>/dev/null
|
||||||
qm destroy $VMID &>/dev/null
|
qm destroy $VMID &>/dev/null
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
post_update_to_api "done" "none"
|
post_update_to_api "done" "none"
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
pushd $TEMP_DIR >/dev/null
|
pushd $TEMP_DIR >/dev/null
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Debian 12 VM" --yesno "This will create a New Debian 12 VM. Proceed?" 10 58; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Debian 12 VM" --yesno "This will create a New Debian 12 VM. Proceed?" 10 58; then
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
|
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
VMID="$NEXTID"
|
VMID="$NEXTID"
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
MACHINE=""
|
MACHINE=""
|
||||||
DISK_SIZE="8G"
|
DISK_SIZE="8G"
|
||||||
DISK_CACHE=""
|
DISK_CACHE=""
|
||||||
HN="debian"
|
HN="debian"
|
||||||
CPU_TYPE=""
|
CPU_TYPE=""
|
||||||
CORE_COUNT="2"
|
CORE_COUNT="2"
|
||||||
RAM_SIZE="2048"
|
RAM_SIZE="2048"
|
||||||
BRG="vmbr0"
|
BRG="vmbr0"
|
||||||
MAC="$GEN_MAC"
|
MAC="$GEN_MAC"
|
||||||
VLAN=""
|
VLAN=""
|
||||||
MTU=""
|
MTU=""
|
||||||
START_VM="yes"
|
START_VM="yes"
|
||||||
METHOD="default"
|
METHOD="default"
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
echo -e "${CREATING}${BOLD}${DGN}Creating a Debian 12 VM using the above default settings${CL}"
|
echo -e "${CREATING}${BOLD}${DGN}Creating a Debian 12 VM using the above default settings${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function advanced_settings() {
|
function advanced_settings() {
|
||||||
METHOD="advanced"
|
METHOD="advanced"
|
||||||
while true; do
|
while true; do
|
||||||
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $NEXTID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $NEXTID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z "$VMID" ]; then
|
if [ -z "$VMID" ]; then
|
||||||
VMID="$NEXTID"
|
VMID="$NEXTID"
|
||||||
fi
|
fi
|
||||||
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
||||||
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
||||||
sleep 2
|
sleep 2
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
||||||
break
|
break
|
||||||
|
else
|
||||||
|
exit_script
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
||||||
|
"i440fx" "Machine i440fx" ON \
|
||||||
|
"q35" "Machine q35" OFF \
|
||||||
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $MACH = q35 ]; then
|
||||||
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=""
|
||||||
|
MACHINE=" -machine q35"
|
||||||
|
else
|
||||||
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=",efitype=4m"
|
||||||
|
MACHINE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
exit_script
|
exit_script
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
|
||||||
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"i440fx" "Machine i440fx" ON \
|
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
|
||||||
"q35" "Machine q35" OFF \
|
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
|
||||||
3>&1 1>&2 2>&3); then
|
DISK_SIZE="${DISK_SIZE}G"
|
||||||
if [ $MACH = q35 ]; then
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
|
||||||
FORMAT=""
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
||||||
MACHINE=" -machine q35"
|
else
|
||||||
|
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
|
||||||
|
exit_script
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
exit_script
|
||||||
FORMAT=",efitype=4m"
|
|
||||||
MACHINE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
|
"0" "None (Default)" ON \
|
||||||
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
|
"1" "Write Through" OFF \
|
||||||
DISK_SIZE="${DISK_SIZE}G"
|
3>&1 1>&2 2>&3); then
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
if [ $DISK_CACHE = "1" ]; then
|
||||||
elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
DISK_CACHE="cache=writethrough,"
|
||||||
|
else
|
||||||
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
||||||
|
DISK_CACHE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
|
exit_script
|
||||||
exit_script
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 debian --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "None (Default)" ON \
|
if [ -z $VM_NAME ]; then
|
||||||
"1" "Write Through" OFF \
|
HN="debian"
|
||||||
3>&1 1>&2 2>&3); then
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
if [ $DISK_CACHE = "1" ]; then
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
|
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
||||||
DISK_CACHE="cache=writethrough,"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
exit_script
|
||||||
DISK_CACHE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 debian --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
if [ -z $VM_NAME ]; then
|
"0" "KVM64 (Default)" ON \
|
||||||
HN="debian"
|
"1" "Host" OFF \
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $CPU_TYPE1 = "1" ]; then
|
||||||
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
|
||||||
|
CPU_TYPE=" -cpu host"
|
||||||
|
else
|
||||||
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
||||||
|
CPU_TYPE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
exit_script
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "KVM64 (Default)" ON \
|
if [ -z $CORE_COUNT ]; then
|
||||||
"1" "Host" OFF \
|
CORE_COUNT="2"
|
||||||
3>&1 1>&2 2>&3); then
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
if [ $CPU_TYPE1 = "1" ]; then
|
else
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
CPU_TYPE=" -cpu host"
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
exit_script
|
||||||
CPU_TYPE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $CORE_COUNT ]; then
|
if [ -z $RAM_SIZE ]; then
|
||||||
CORE_COUNT="2"
|
RAM_SIZE="2048"
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
exit_script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $RAM_SIZE ]; then
|
if [ -z $BRG ]; then
|
||||||
RAM_SIZE="2048"
|
BRG="vmbr0"
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
exit_script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $BRG ]; then
|
if [ -z $MAC1 ]; then
|
||||||
BRG="vmbr0"
|
MAC="$GEN_MAC"
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
|
||||||
|
else
|
||||||
|
MAC="$MAC1"
|
||||||
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
exit_script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $MAC1 ]; then
|
if [ -z $VLAN1 ]; then
|
||||||
MAC="$GEN_MAC"
|
VLAN1="Default"
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
|
VLAN=""
|
||||||
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
||||||
|
else
|
||||||
|
VLAN=",tag=$VLAN1"
|
||||||
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
MAC="$MAC1"
|
exit_script
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $VLAN1 ]; then
|
if [ -z $MTU1 ]; then
|
||||||
VLAN1="Default"
|
MTU1="Default"
|
||||||
VLAN=""
|
MTU=""
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
else
|
||||||
|
MTU=",mtu=$MTU1"
|
||||||
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
VLAN=",tag=$VLAN1"
|
exit_script
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
||||||
if [ -z $MTU1 ]; then
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
MTU1="Default"
|
START_VM="yes"
|
||||||
MTU=""
|
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
|
||||||
else
|
else
|
||||||
MTU=",mtu=$MTU1"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
START_VM="no"
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Debian 12 VM?" --no-button Do-Over 10 58); then
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
echo -e "${CREATING}${BOLD}${DGN}Creating a Debian 12 VM using the above advanced settings${CL}"
|
||||||
START_VM="yes"
|
else
|
||||||
else
|
header_info
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
|
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
||||||
START_VM="no"
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Debian 12 VM?" --no-button Do-Over 10 58); then
|
|
||||||
echo -e "${CREATING}${BOLD}${DGN}Creating a Debian 12 VM using the above advanced settings${CL}"
|
|
||||||
else
|
|
||||||
header_info
|
|
||||||
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
|
||||||
advanced_settings
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
root_check
|
root_check
|
||||||
@@ -290,29 +290,29 @@ post_to_api_vm
|
|||||||
|
|
||||||
msg_info "Validating Storage"
|
msg_info "Validating Storage"
|
||||||
while read -r line; do
|
while read -r line; do
|
||||||
TAG=$(echo $line | awk '{print $1}')
|
TAG=$(echo $line | awk '{print $1}')
|
||||||
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
||||||
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
||||||
ITEM=" Type: $TYPE Free: $FREE "
|
ITEM=" Type: $TYPE Free: $FREE "
|
||||||
OFFSET=2
|
OFFSET=2
|
||||||
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
||||||
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
||||||
fi
|
fi
|
||||||
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
||||||
done < <(pvesm status -content images | awk 'NR>1')
|
done < <(pvesm status -content images | awk 'NR>1')
|
||||||
VALID=$(pvesm status -content images | awk 'NR>1')
|
VALID=$(pvesm status -content images | awk 'NR>1')
|
||||||
if [ -z "$VALID" ]; then
|
if [ -z "$VALID" ]; then
|
||||||
msg_error "Unable to detect a valid storage location."
|
msg_error "Unable to detect a valid storage location."
|
||||||
exit
|
exit
|
||||||
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
||||||
STORAGE=${STORAGE_MENU[0]}
|
STORAGE=${STORAGE_MENU[0]}
|
||||||
else
|
else
|
||||||
while [ -z "${STORAGE:+x}" ]; do
|
while [ -z "${STORAGE:+x}" ]; do
|
||||||
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
||||||
"Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
"Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
||||||
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
||||||
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3) || exit
|
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3) || exit
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
||||||
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
||||||
@@ -328,37 +328,37 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
|
|||||||
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
||||||
case $STORAGE_TYPE in
|
case $STORAGE_TYPE in
|
||||||
nfs | dir)
|
nfs | dir)
|
||||||
DISK_EXT=".qcow2"
|
DISK_EXT=".qcow2"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format qcow2"
|
DISK_IMPORT="-format qcow2"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
btrfs)
|
btrfs)
|
||||||
DISK_EXT=".raw"
|
DISK_EXT=".raw"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format raw"
|
DISK_IMPORT="-format raw"
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
for i in {0,1}; do
|
for i in {0,1}; do
|
||||||
disk="DISK$i"
|
disk="DISK$i"
|
||||||
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
||||||
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
||||||
done
|
done
|
||||||
|
|
||||||
msg_info "Creating a Debian 12 VM"
|
msg_info "Creating a Debian 12 VM"
|
||||||
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
||||||
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
|
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
|
||||||
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
||||||
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
||||||
qm set $VMID \
|
qm set $VMID \
|
||||||
-efidisk0 ${DISK0_REF}${FORMAT} \
|
-efidisk0 ${DISK0_REF}${FORMAT} \
|
||||||
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
|
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
|
||||||
-boot order=scsi0 \
|
-boot order=scsi0 \
|
||||||
-serial0 socket >/dev/null
|
-serial0 socket >/dev/null
|
||||||
DESCRIPTION=$(
|
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://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
||||||
@@ -389,18 +389,18 @@ EOF
|
|||||||
)
|
)
|
||||||
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
||||||
if [ -n "$DISK_SIZE" ]; then
|
if [ -n "$DISK_SIZE" ]; then
|
||||||
msg_info "Resizing disk to $DISK_SIZE GB"
|
msg_info "Resizing disk to $DISK_SIZE GB"
|
||||||
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
|
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
|
||||||
else
|
else
|
||||||
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
|
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
|
||||||
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
|
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_ok "Created a Debian 12 VM ${CL}${BL}(${HN})"
|
msg_ok "Created a Debian 12 VM ${CL}${BL}(${HN})"
|
||||||
if [ "$START_VM" == "yes" ]; then
|
if [ "$START_VM" == "yes" ]; then
|
||||||
msg_info "Starting Debian 12 VM"
|
msg_info "Starting Debian 12 VM"
|
||||||
qm start $VMID
|
qm start $VMID
|
||||||
msg_ok "Started Debian 12 VM"
|
msg_ok "Started Debian 12 VM"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_ok "Completed successfully!\n"
|
msg_ok "Completed successfully!\n"
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.or
|
|||||||
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
||||||
|
|
||||||
function header_info {
|
function header_info {
|
||||||
clear
|
clear
|
||||||
cat <<"EOF"
|
cat <<"EOF"
|
||||||
______ __ __ _ __ __ __ __ _ ____ ___
|
______ __ __ _ __ __ __ __ _ ____ ___
|
||||||
/_ __/_ _________ / //_/__ __ __ / |/ /____ __/ /_____/ /__ __ _____/ / | | / / |/ /
|
/_ __/_ _________ / //_/__ __ __ / |/ /____ __/ /_____/ /__ __ _____/ / | | / / |/ /
|
||||||
/ / / // / __/ _ \/ ,< / -_) // / / / -_) \ / __/ __/ / _ \/ // / _ / | |/ / /|_/ /
|
/ / / // / __/ _ \/ ,< / -_) // / / / -_) \ / __/ __/ / _ \/ // / _ / | |/ / /|_/ /
|
||||||
@@ -47,322 +47,322 @@ trap cleanup EXIT
|
|||||||
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
||||||
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
||||||
function error_handler() {
|
function error_handler() {
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
local line_number="$1"
|
local line_number="$1"
|
||||||
local command="$2"
|
local command="$2"
|
||||||
post_update_to_api "failed" "${command}"
|
post_update_to_api "failed" "${command}"
|
||||||
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
||||||
echo -e "\n$error_message\n"
|
echo -e "\n$error_message\n"
|
||||||
cleanup_vmid
|
cleanup_vmid
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_valid_nextid() {
|
function get_valid_nextid() {
|
||||||
local try_id
|
local try_id
|
||||||
try_id=$(pvesh get /cluster/nextid)
|
try_id=$(pvesh get /cluster/nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
break
|
break
|
||||||
done
|
done
|
||||||
echo "$try_id"
|
echo "$try_id"
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup_vmid() {
|
function cleanup_vmid() {
|
||||||
if qm status $VMID &>/dev/null; then
|
if qm status $VMID &>/dev/null; then
|
||||||
qm stop $VMID &>/dev/null
|
qm stop $VMID &>/dev/null
|
||||||
qm destroy $VMID &>/dev/null
|
qm destroy $VMID &>/dev/null
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
pushd $TEMP_DIR >/dev/null
|
pushd $TEMP_DIR >/dev/null
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "$NAME" --yesno "This will create a New $NAME. Proceed?" 10 58; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "$NAME" --yesno "This will create a New $NAME. Proceed?" 10 58; then
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
header_info && echo -e "⚠ User exited script \n" && exit
|
header_info && echo -e "⚠ User exited script \n" && exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function msg_info() {
|
function msg_info() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_ok() {
|
function msg_ok() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_error() {
|
function msg_error() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_root() {
|
function check_root() {
|
||||||
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
||||||
clear
|
clear
|
||||||
msg_error "Please run this script as root."
|
msg_error "Please run this script as root."
|
||||||
echo -e "\nExiting..."
|
echo -e "\nExiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function pve_check() {
|
function pve_check() {
|
||||||
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
||||||
msg_error "This version of Proxmox Virtual Environment is not supported"
|
msg_error "This version of Proxmox Virtual Environment is not supported"
|
||||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function arch_check() {
|
function arch_check() {
|
||||||
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
||||||
msg_error "This script will not work with PiMox! \n"
|
msg_error "This script will not work with PiMox! \n"
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function ssh_check() {
|
function ssh_check() {
|
||||||
if command -v pveversion >/dev/null 2>&1; then
|
if command -v pveversion >/dev/null 2>&1; then
|
||||||
if [ -n "${SSH_CLIENT:+x}" ]; then
|
if [ -n "${SSH_CLIENT:+x}" ]; then
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
||||||
echo "you've been warned"
|
echo "you've been warned"
|
||||||
else
|
else
|
||||||
clear
|
clear
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function exit-script() {
|
function exit-script() {
|
||||||
clear
|
clear
|
||||||
echo -e "⚠ User exited script \n"
|
echo -e "⚠ User exited script \n"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
MACHINE=""
|
MACHINE=""
|
||||||
DISK_CACHE=""
|
DISK_CACHE=""
|
||||||
HN="turnkey-nextcloud-vm"
|
HN="turnkey-nextcloud-vm"
|
||||||
CPU_TYPE=""
|
CPU_TYPE=""
|
||||||
CORE_COUNT="2"
|
CORE_COUNT="2"
|
||||||
RAM_SIZE="2048"
|
RAM_SIZE="2048"
|
||||||
BRG="vmbr0"
|
BRG="vmbr0"
|
||||||
MAC="$GEN_MAC"
|
MAC="$GEN_MAC"
|
||||||
VLAN=""
|
VLAN=""
|
||||||
MTU=""
|
MTU=""
|
||||||
START_VM="no"
|
START_VM="no"
|
||||||
METHOD="default"
|
METHOD="default"
|
||||||
echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
|
echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
|
||||||
echo -e "${DGN}Using Machine Type: ${BGN}i440fx${CL}"
|
echo -e "${DGN}Using Machine Type: ${BGN}i440fx${CL}"
|
||||||
echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
|
echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
|
||||||
echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
|
echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
|
||||||
echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
|
echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
|
||||||
echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
|
echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
|
||||||
echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
|
echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
|
||||||
echo -e "${DGN}Using Bridge: ${BGN}${BRG}${CL}"
|
echo -e "${DGN}Using Bridge: ${BGN}${BRG}${CL}"
|
||||||
echo -e "${DGN}Using MAC Address: ${BGN}${MAC}${CL}"
|
echo -e "${DGN}Using MAC Address: ${BGN}${MAC}${CL}"
|
||||||
echo -e "${DGN}Using VLAN: ${BGN}Default${CL}"
|
echo -e "${DGN}Using VLAN: ${BGN}Default${CL}"
|
||||||
echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
|
echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
|
||||||
echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
|
echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
|
||||||
echo -e "${BL}Creating a $NAME using the above default settings${CL}"
|
echo -e "${BL}Creating a $NAME using the above default settings${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function advanced_settings() {
|
function advanced_settings() {
|
||||||
METHOD="advanced"
|
METHOD="advanced"
|
||||||
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z "$VMID" ]; then
|
if [ -z "$VMID" ]; then
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
fi
|
fi
|
||||||
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
||||||
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
||||||
sleep 2
|
sleep 2
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
||||||
break
|
break
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
||||||
|
"i440fx" "Machine i440fx" ON \
|
||||||
|
"q35" "Machine q35" OFF \
|
||||||
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $MACH = q35 ]; then
|
||||||
|
echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=""
|
||||||
|
MACHINE=" -machine q35"
|
||||||
|
else
|
||||||
|
echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=",efitype=4m"
|
||||||
|
MACHINE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
exit-script
|
exit-script
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
|
||||||
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
"i440fx" "Machine i440fx" ON \
|
"0" "None (Default)" ON \
|
||||||
"q35" "Machine q35" OFF \
|
"1" "Write Through" OFF \
|
||||||
3>&1 1>&2 2>&3); then
|
3>&1 1>&2 2>&3); then
|
||||||
if [ $MACH = q35 ]; then
|
if [ $DISK_CACHE = "1" ]; then
|
||||||
echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
|
echo -e "${DGN}Using Disk Cache: ${BGN}Write Through${CL}"
|
||||||
FORMAT=""
|
DISK_CACHE="cache=writethrough,"
|
||||||
MACHINE=" -machine q35"
|
else
|
||||||
|
echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
|
||||||
|
DISK_CACHE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
|
exit-script
|
||||||
FORMAT=",efitype=4m"
|
|
||||||
MACHINE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 turnkey-nextcloud-vm --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "None (Default)" ON \
|
if [ -z $VM_NAME ]; then
|
||||||
"1" "Write Through" OFF \
|
HN="$HN"
|
||||||
3>&1 1>&2 2>&3); then
|
echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
|
||||||
if [ $DISK_CACHE = "1" ]; then
|
else
|
||||||
echo -e "${DGN}Using Disk Cache: ${BGN}Write Through${CL}"
|
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
||||||
DISK_CACHE="cache=writethrough,"
|
echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
|
exit-script
|
||||||
DISK_CACHE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 turnkey-nextcloud-vm --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
if [ -z $VM_NAME ]; then
|
"0" "KVM64 (Default)" ON \
|
||||||
HN="$HN"
|
"1" "Host" OFF \
|
||||||
echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $CPU_TYPE1 = "1" ]; then
|
||||||
|
echo -e "${DGN}Using CPU Model: ${BGN}Host${CL}"
|
||||||
|
CPU_TYPE=" -cpu host"
|
||||||
|
else
|
||||||
|
echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
|
||||||
|
CPU_TYPE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
exit-script
|
||||||
echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "KVM64 (Default)" ON \
|
if [ -z $CORE_COUNT ]; then
|
||||||
"1" "Host" OFF \
|
CORE_COUNT="2"
|
||||||
3>&1 1>&2 2>&3); then
|
echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
if [ $CPU_TYPE1 = "1" ]; then
|
else
|
||||||
echo -e "${DGN}Using CPU Model: ${BGN}Host${CL}"
|
echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
CPU_TYPE=" -cpu host"
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
|
exit-script
|
||||||
CPU_TYPE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $CORE_COUNT ]; then
|
if [ -z $RAM_SIZE ]; then
|
||||||
CORE_COUNT="2"
|
RAM_SIZE="2048"
|
||||||
echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
|
echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $RAM_SIZE ]; then
|
if [ -z $BRG ]; then
|
||||||
RAM_SIZE="2048"
|
BRG="vmbr0"
|
||||||
echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
|
echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $BRG ]; then
|
if [ -z $MAC1 ]; then
|
||||||
BRG="vmbr0"
|
MAC="$GEN_MAC"
|
||||||
echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
|
echo -e "${DGN}Using MAC Address: ${BGN}$MAC${CL}"
|
||||||
|
else
|
||||||
|
MAC="$MAC1"
|
||||||
|
echo -e "${DGN}Using MAC Address: ${BGN}$MAC1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $MAC1 ]; then
|
if [ -z $VLAN1 ]; then
|
||||||
MAC="$GEN_MAC"
|
VLAN1="Default"
|
||||||
echo -e "${DGN}Using MAC Address: ${BGN}$MAC${CL}"
|
VLAN=""
|
||||||
|
echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
|
||||||
|
else
|
||||||
|
VLAN=",tag=$VLAN1"
|
||||||
|
echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
MAC="$MAC1"
|
exit-script
|
||||||
echo -e "${DGN}Using MAC Address: ${BGN}$MAC1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $VLAN1 ]; then
|
if [ -z $MTU1 ]; then
|
||||||
VLAN1="Default"
|
MTU1="Default"
|
||||||
VLAN=""
|
MTU=""
|
||||||
echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
|
echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
else
|
||||||
|
MTU=",mtu=$MTU1"
|
||||||
|
echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
VLAN=",tag=$VLAN1"
|
exit-script
|
||||||
echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
||||||
if [ -z $MTU1 ]; then
|
echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
MTU1="Default"
|
START_VM="yes"
|
||||||
MTU=""
|
|
||||||
echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
|
|
||||||
else
|
else
|
||||||
MTU=",mtu=$MTU1"
|
echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
|
||||||
echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
|
START_VM="no"
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a $NAME?" --no-button Do-Over 10 58); then
|
||||||
echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
|
echo -e "${RD}Creating a $NAME using the above advanced settings${CL}"
|
||||||
START_VM="yes"
|
else
|
||||||
else
|
header_info
|
||||||
echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
|
echo -e "${RD}Using Advanced Settings${CL}"
|
||||||
START_VM="no"
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a $NAME?" --no-button Do-Over 10 58); then
|
|
||||||
echo -e "${RD}Creating a $NAME using the above advanced settings${CL}"
|
|
||||||
else
|
|
||||||
header_info
|
|
||||||
echo -e "${RD}Using Advanced Settings${CL}"
|
|
||||||
advanced_settings
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function start_script() {
|
function start_script() {
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
||||||
header_info
|
header_info
|
||||||
echo -e "${BL}Using Default Settings${CL}"
|
echo -e "${BL}Using Default Settings${CL}"
|
||||||
default_settings
|
default_settings
|
||||||
else
|
else
|
||||||
header_info
|
header_info
|
||||||
echo -e "${RD}Using Advanced Settings${CL}"
|
echo -e "${RD}Using Advanced Settings${CL}"
|
||||||
advanced_settings
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
check_root
|
check_root
|
||||||
@@ -375,29 +375,29 @@ post_to_api_vm
|
|||||||
|
|
||||||
msg_info "Validating Storage"
|
msg_info "Validating Storage"
|
||||||
while read -r line; do
|
while read -r line; do
|
||||||
TAG=$(echo $line | awk '{print $1}')
|
TAG=$(echo $line | awk '{print $1}')
|
||||||
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
||||||
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
||||||
ITEM=" Type: $TYPE Free: $FREE "
|
ITEM=" Type: $TYPE Free: $FREE "
|
||||||
OFFSET=2
|
OFFSET=2
|
||||||
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
||||||
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
||||||
fi
|
fi
|
||||||
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
||||||
done < <(pvesm status -content images | awk 'NR>1')
|
done < <(pvesm status -content images | awk 'NR>1')
|
||||||
VALID=$(pvesm status -content images | awk 'NR>1')
|
VALID=$(pvesm status -content images | awk 'NR>1')
|
||||||
if [ -z "$VALID" ]; then
|
if [ -z "$VALID" ]; then
|
||||||
msg_error "Unable to detect a valid storage location."
|
msg_error "Unable to detect a valid storage location."
|
||||||
exit
|
exit
|
||||||
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
||||||
STORAGE=${STORAGE_MENU[0]}
|
STORAGE=${STORAGE_MENU[0]}
|
||||||
else
|
else
|
||||||
while [ -z "${STORAGE:+x}" ]; do
|
while [ -z "${STORAGE:+x}" ]; do
|
||||||
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
||||||
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
||||||
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
||||||
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
||||||
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
||||||
@@ -413,38 +413,38 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
|
|||||||
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
||||||
case $STORAGE_TYPE in
|
case $STORAGE_TYPE in
|
||||||
nfs | dir)
|
nfs | dir)
|
||||||
DISK_EXT=".raw"
|
DISK_EXT=".raw"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format raw"
|
DISK_IMPORT="-format raw"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
btrfs)
|
btrfs)
|
||||||
DISK_EXT=".raw"
|
DISK_EXT=".raw"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format raw"
|
DISK_IMPORT="-format raw"
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
for i in {0,1,2}; do
|
for i in {0,1,2}; do
|
||||||
disk="DISK$i"
|
disk="DISK$i"
|
||||||
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
||||||
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
||||||
done
|
done
|
||||||
|
|
||||||
msg_info "Creating a $NAME"
|
msg_info "Creating a $NAME"
|
||||||
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios seabios${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios seabios${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
||||||
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
|
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
|
||||||
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
||||||
pvesm alloc $STORAGE $VMID $DISK1 12G 1>&/dev/null
|
pvesm alloc $STORAGE $VMID $DISK1 12G 1>&/dev/null
|
||||||
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
||||||
qm set $VMID \
|
qm set $VMID \
|
||||||
-efidisk0 ${DISK0_REF}${FORMAT} \
|
-efidisk0 ${DISK0_REF}${FORMAT} \
|
||||||
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN} \
|
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN} \
|
||||||
-scsi1 ${DISK2_REF},${DISK_CACHE}${THIN} \
|
-scsi1 ${DISK2_REF},${DISK_CACHE}${THIN} \
|
||||||
-boot order='scsi1;scsi0' >/dev/null
|
-boot order='scsi1;scsi0' >/dev/null
|
||||||
DESCRIPTION=$(
|
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://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
<img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
||||||
@@ -477,9 +477,9 @@ qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
|||||||
|
|
||||||
msg_ok "Created a $NAME ${CL}${BL}(${HN})"
|
msg_ok "Created a $NAME ${CL}${BL}(${HN})"
|
||||||
if [ "$START_VM" == "yes" ]; then
|
if [ "$START_VM" == "yes" ]; then
|
||||||
msg_info "Starting $NAME"
|
msg_info "Starting $NAME"
|
||||||
qm start $VMID
|
qm start $VMID
|
||||||
msg_ok "Started $NAME"
|
msg_ok "Started $NAME"
|
||||||
fi
|
fi
|
||||||
post_update_to_api "done" "none"
|
post_update_to_api "done" "none"
|
||||||
msg_ok "Completed successfully!\n"
|
msg_ok "Completed successfully!\n"
|
||||||
|
|||||||
690
vm/openwrt.sh
690
vm/openwrt.sh
@@ -11,8 +11,8 @@ COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.or
|
|||||||
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
||||||
|
|
||||||
function header_info {
|
function header_info {
|
||||||
clear
|
clear
|
||||||
cat <<"EOF"
|
cat <<"EOF"
|
||||||
____ _ __ __
|
____ _ __ __
|
||||||
/ __ \____ ___ ____| | / /____/ /_
|
/ __ \____ ___ ____| | / /____/ /_
|
||||||
/ / / / __ \/ _ \/ __ \ | /| / / ___/ __/
|
/ / / / __ \/ _ \/ __ \ | /| / / ___/ __/
|
||||||
@@ -51,380 +51,380 @@ trap cleanup EXIT
|
|||||||
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
||||||
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
||||||
function error_handler() {
|
function error_handler() {
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
local line_number="$1"
|
local line_number="$1"
|
||||||
local command="$2"
|
local command="$2"
|
||||||
post_update_to_api "failed" "$command"
|
post_update_to_api "failed" "$command"
|
||||||
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
||||||
echo -e "\n$error_message\n"
|
echo -e "\n$error_message\n"
|
||||||
cleanup_vmid
|
cleanup_vmid
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_valid_nextid() {
|
function get_valid_nextid() {
|
||||||
local try_id
|
local try_id
|
||||||
try_id=$(pvesh get /cluster/nextid)
|
try_id=$(pvesh get /cluster/nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
break
|
break
|
||||||
done
|
done
|
||||||
echo "$try_id"
|
echo "$try_id"
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup_vmid() {
|
function cleanup_vmid() {
|
||||||
if qm status $VMID &>/dev/null; then
|
if qm status $VMID &>/dev/null; then
|
||||||
qm stop $VMID &>/dev/null
|
qm stop $VMID &>/dev/null
|
||||||
qm destroy $VMID &>/dev/null
|
qm destroy $VMID &>/dev/null
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
pushd $TEMP_DIR >/dev/null
|
pushd $TEMP_DIR >/dev/null
|
||||||
function send_line_to_vm() {
|
function send_line_to_vm() {
|
||||||
echo -e "${DGN}Sending line: ${YW}$1${CL}"
|
echo -e "${DGN}Sending line: ${YW}$1${CL}"
|
||||||
for ((i = 0; i < ${#1}; i++)); do
|
for ((i = 0; i < ${#1}; i++)); do
|
||||||
character=${1:i:1}
|
character=${1:i:1}
|
||||||
case $character in
|
case $character in
|
||||||
" ") character="spc" ;;
|
" ") character="spc" ;;
|
||||||
"-") character="minus" ;;
|
"-") character="minus" ;;
|
||||||
"=") character="equal" ;;
|
"=") character="equal" ;;
|
||||||
",") character="comma" ;;
|
",") character="comma" ;;
|
||||||
".") character="dot" ;;
|
".") character="dot" ;;
|
||||||
"/") character="slash" ;;
|
"/") character="slash" ;;
|
||||||
"'") character="apostrophe" ;;
|
"'") character="apostrophe" ;;
|
||||||
";") character="semicolon" ;;
|
";") character="semicolon" ;;
|
||||||
'\') character="backslash" ;;
|
'\') character="backslash" ;;
|
||||||
'`') character="grave_accent" ;;
|
'`') character="grave_accent" ;;
|
||||||
"[") character="bracket_left" ;;
|
"[") character="bracket_left" ;;
|
||||||
"]") character="bracket_right" ;;
|
"]") character="bracket_right" ;;
|
||||||
"_") character="shift-minus" ;;
|
"_") character="shift-minus" ;;
|
||||||
"+") character="shift-equal" ;;
|
"+") character="shift-equal" ;;
|
||||||
"?") character="shift-slash" ;;
|
"?") character="shift-slash" ;;
|
||||||
"<") character="shift-comma" ;;
|
"<") character="shift-comma" ;;
|
||||||
">") character="shift-dot" ;;
|
">") character="shift-dot" ;;
|
||||||
'"') character="shift-apostrophe" ;;
|
'"') character="shift-apostrophe" ;;
|
||||||
":") character="shift-semicolon" ;;
|
":") character="shift-semicolon" ;;
|
||||||
"|") character="shift-backslash" ;;
|
"|") character="shift-backslash" ;;
|
||||||
"~") character="shift-grave_accent" ;;
|
"~") character="shift-grave_accent" ;;
|
||||||
"{") character="shift-bracket_left" ;;
|
"{") character="shift-bracket_left" ;;
|
||||||
"}") character="shift-bracket_right" ;;
|
"}") character="shift-bracket_right" ;;
|
||||||
"A") character="shift-a" ;;
|
"A") character="shift-a" ;;
|
||||||
"B") character="shift-b" ;;
|
"B") character="shift-b" ;;
|
||||||
"C") character="shift-c" ;;
|
"C") character="shift-c" ;;
|
||||||
"D") character="shift-d" ;;
|
"D") character="shift-d" ;;
|
||||||
"E") character="shift-e" ;;
|
"E") character="shift-e" ;;
|
||||||
"F") character="shift-f" ;;
|
"F") character="shift-f" ;;
|
||||||
"G") character="shift-g" ;;
|
"G") character="shift-g" ;;
|
||||||
"H") character="shift-h" ;;
|
"H") character="shift-h" ;;
|
||||||
"I") character="shift-i" ;;
|
"I") character="shift-i" ;;
|
||||||
"J") character="shift-j" ;;
|
"J") character="shift-j" ;;
|
||||||
"K") character="shift-k" ;;
|
"K") character="shift-k" ;;
|
||||||
"L") character="shift-l" ;;
|
"L") character="shift-l" ;;
|
||||||
"M") character="shift-m" ;;
|
"M") character="shift-m" ;;
|
||||||
"N") character="shift-n" ;;
|
"N") character="shift-n" ;;
|
||||||
"O") character="shift-o" ;;
|
"O") character="shift-o" ;;
|
||||||
"P") character="shift-p" ;;
|
"P") character="shift-p" ;;
|
||||||
"Q") character="shift-q" ;;
|
"Q") character="shift-q" ;;
|
||||||
"R") character="shift-r" ;;
|
"R") character="shift-r" ;;
|
||||||
"S") character="shift-s" ;;
|
"S") character="shift-s" ;;
|
||||||
"T") character="shift-t" ;;
|
"T") character="shift-t" ;;
|
||||||
"U") character="shift-u" ;;
|
"U") character="shift-u" ;;
|
||||||
"V") character="shift-v" ;;
|
"V") character="shift-v" ;;
|
||||||
"W") character="shift-w" ;;
|
"W") character="shift-w" ;;
|
||||||
"X") character="shift=x" ;;
|
"X") character="shift=x" ;;
|
||||||
"Y") character="shift-y" ;;
|
"Y") character="shift-y" ;;
|
||||||
"Z") character="shift-z" ;;
|
"Z") character="shift-z" ;;
|
||||||
"!") character="shift-1" ;;
|
"!") character="shift-1" ;;
|
||||||
"@") character="shift-2" ;;
|
"@") character="shift-2" ;;
|
||||||
"#") character="shift-3" ;;
|
"#") character="shift-3" ;;
|
||||||
'$') character="shift-4" ;;
|
'$') character="shift-4" ;;
|
||||||
"%") character="shift-5" ;;
|
"%") character="shift-5" ;;
|
||||||
"^") character="shift-6" ;;
|
"^") character="shift-6" ;;
|
||||||
"&") character="shift-7" ;;
|
"&") character="shift-7" ;;
|
||||||
"*") character="shift-8" ;;
|
"*") character="shift-8" ;;
|
||||||
"(") character="shift-9" ;;
|
"(") character="shift-9" ;;
|
||||||
")") character="shift-0" ;;
|
")") character="shift-0" ;;
|
||||||
esac
|
esac
|
||||||
qm sendkey $VMID "$character"
|
qm sendkey $VMID "$character"
|
||||||
done
|
done
|
||||||
qm sendkey $VMID ret
|
qm sendkey $VMID ret
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
pushd $TEMP_DIR >/dev/null
|
pushd $TEMP_DIR >/dev/null
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "OpenWrt VM" --yesno "This will create a New OpenWrt VM. Proceed?" 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "OpenWrt VM" --yesno "This will create a New OpenWrt VM. Proceed?" 10 58); then
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
header_info && echo -e "⚠ User exited script \n" && exit
|
header_info && echo -e "⚠ User exited script \n" && exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function msg_info() {
|
function msg_info() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_ok() {
|
function msg_ok() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_error() {
|
function msg_error() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function pve_check() {
|
function pve_check() {
|
||||||
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
||||||
msg_error "This version of Proxmox Virtual Environment is not supported"
|
msg_error "This version of Proxmox Virtual Environment is not supported"
|
||||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function arch_check() {
|
function arch_check() {
|
||||||
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
||||||
echo -e "\n ${CROSS} This script will not work with PiMox! \n"
|
echo -e "\n ${CROSS} This script will not work with PiMox! \n"
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function ssh_check() {
|
function ssh_check() {
|
||||||
if command -v pveversion >/dev/null 2>&1; then
|
if command -v pveversion >/dev/null 2>&1; then
|
||||||
if [ -n "${SSH_CLIENT:+x}" ]; then
|
if [ -n "${SSH_CLIENT:+x}" ]; then
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
||||||
echo "you've been warned"
|
echo "you've been warned"
|
||||||
else
|
else
|
||||||
clear
|
clear
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function exit-script() {
|
function exit-script() {
|
||||||
clear
|
clear
|
||||||
echo -e "⚠ User exited script \n"
|
echo -e "⚠ User exited script \n"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
HN=openwrt
|
HN=openwrt
|
||||||
CORE_COUNT="1"
|
CORE_COUNT="1"
|
||||||
RAM_SIZE="256"
|
RAM_SIZE="256"
|
||||||
BRG="vmbr0"
|
BRG="vmbr0"
|
||||||
VLAN=""
|
VLAN=""
|
||||||
MAC=$GEN_MAC
|
MAC=$GEN_MAC
|
||||||
LAN_MAC=$GEN_MAC_LAN
|
LAN_MAC=$GEN_MAC_LAN
|
||||||
LAN_BRG="vmbr0"
|
LAN_BRG="vmbr0"
|
||||||
LAN_IP_ADDR="192.168.1.1"
|
LAN_IP_ADDR="192.168.1.1"
|
||||||
LAN_NETMASK="255.255.255.0"
|
LAN_NETMASK="255.255.255.0"
|
||||||
LAN_VLAN=",tag=999"
|
LAN_VLAN=",tag=999"
|
||||||
MTU=""
|
MTU=""
|
||||||
START_VM="yes"
|
START_VM="yes"
|
||||||
METHOD="default"
|
METHOD="default"
|
||||||
echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
|
echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
|
||||||
echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
|
echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
|
||||||
echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
|
echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
|
||||||
echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
|
echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
|
||||||
echo -e "${DGN}Using WAN Bridge: ${BGN}${BRG}${CL}"
|
echo -e "${DGN}Using WAN Bridge: ${BGN}${BRG}${CL}"
|
||||||
echo -e "${DGN}Using WAN VLAN: ${BGN}Default${CL}"
|
echo -e "${DGN}Using WAN VLAN: ${BGN}Default${CL}"
|
||||||
echo -e "${DGN}Using WAN MAC Address: ${BGN}${MAC}${CL}"
|
echo -e "${DGN}Using WAN MAC Address: ${BGN}${MAC}${CL}"
|
||||||
echo -e "${DGN}Using LAN MAC Address: ${BGN}${LAN_MAC}${CL}"
|
echo -e "${DGN}Using LAN MAC Address: ${BGN}${LAN_MAC}${CL}"
|
||||||
echo -e "${DGN}Using LAN Bridge: ${BGN}${LAN_BRG}${CL}"
|
echo -e "${DGN}Using LAN Bridge: ${BGN}${LAN_BRG}${CL}"
|
||||||
echo -e "${DGN}Using LAN VLAN: ${BGN}999${CL}"
|
echo -e "${DGN}Using LAN VLAN: ${BGN}999${CL}"
|
||||||
echo -e "${DGN}Using LAN IP Address: ${BGN}${LAN_IP_ADDR}${CL}"
|
echo -e "${DGN}Using LAN IP Address: ${BGN}${LAN_IP_ADDR}${CL}"
|
||||||
echo -e "${DGN}Using LAN NETMASK: ${BGN}${LAN_NETMASK}${CL}"
|
echo -e "${DGN}Using LAN NETMASK: ${BGN}${LAN_NETMASK}${CL}"
|
||||||
echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
|
echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
|
||||||
echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
|
echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
echo -e "${BL}Creating a OpenWrt VM using the above default settings${CL}"
|
echo -e "${BL}Creating a OpenWrt VM using the above default settings${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function advanced_settings() {
|
function advanced_settings() {
|
||||||
METHOD="advanced"
|
METHOD="advanced"
|
||||||
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z "$VMID" ]; then
|
if [ -z "$VMID" ]; then
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
fi
|
fi
|
||||||
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
||||||
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
||||||
sleep 2
|
sleep 2
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
||||||
break
|
break
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 openwrt --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
|
if [ -z $VM_NAME ]; then
|
||||||
|
HN="openwrt"
|
||||||
|
else
|
||||||
|
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
||||||
|
fi
|
||||||
|
echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
|
||||||
else
|
else
|
||||||
exit-script
|
exit-script
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
|
||||||
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 openwrt --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 1 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $VM_NAME ]; then
|
if [ -z $CORE_COUNT ]; then
|
||||||
HN="openwrt"
|
CORE_COUNT="1"
|
||||||
|
fi
|
||||||
|
echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
else
|
else
|
||||||
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
exit-script
|
||||||
fi
|
fi
|
||||||
echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
|
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 1 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 256 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $CORE_COUNT ]; then
|
if [ -z $RAM_SIZE ]; then
|
||||||
CORE_COUNT="1"
|
RAM_SIZE="256"
|
||||||
fi
|
fi
|
||||||
echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
|
echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 256 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
|
||||||
if [ -z $RAM_SIZE ]; then
|
|
||||||
RAM_SIZE="256"
|
|
||||||
fi
|
|
||||||
echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
|
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN Bridge" 8 58 vmbr0 --title "WAN BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
|
||||||
if [ -z $BRG ]; then
|
|
||||||
BRG="vmbr0"
|
|
||||||
fi
|
|
||||||
echo -e "${DGN}Using WAN Bridge: ${BGN}$BRG${CL}"
|
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if LAN_BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN Bridge" 8 58 vmbr0 --title "LAN BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
|
||||||
if [ -z $LAN_BRG ]; then
|
|
||||||
LAN_BRG="vmbr0"
|
|
||||||
fi
|
|
||||||
echo -e "${DGN}Using LAN Bridge: ${BGN}$LAN_BRG${CL}"
|
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if LAN_IP_ADDR=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a router IP" 8 58 $LAN_IP_ADDR --title "LAN IP ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
|
||||||
if [ -z $LAN_IP_ADDR ]; then
|
|
||||||
LAN_IP_ADDR="192.168.1.1"
|
|
||||||
fi
|
|
||||||
echo -e "${DGN}Using LAN IP ADDRESS: ${BGN}$LAN_IP_ADDR${CL}"
|
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if LAN_NETMASK=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a router netmask" 8 58 $LAN_NETMASK --title "LAN NETMASK" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
|
||||||
if [ -z $LAN_NETMASK ]; then
|
|
||||||
LAN_NETMASK="255.255.255.0"
|
|
||||||
fi
|
|
||||||
echo -e "${DGN}Using LAN NETMASK: ${BGN}$LAN_NETMASK${CL}"
|
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN MAC Address" 8 58 $GEN_MAC --title "WAN MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
|
||||||
if [ -z $MAC1 ]; then
|
|
||||||
MAC="$GEN_MAC"
|
|
||||||
else
|
else
|
||||||
MAC="$MAC1"
|
exit-script
|
||||||
fi
|
fi
|
||||||
echo -e "${DGN}Using WAN MAC Address: ${BGN}$MAC${CL}"
|
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MAC2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN MAC Address" 8 58 $GEN_MAC_LAN --title "LAN MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN Bridge" 8 58 vmbr0 --title "WAN BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $MAC2 ]; then
|
if [ -z $BRG ]; then
|
||||||
LAN_MAC="$GEN_MAC_LAN"
|
BRG="vmbr0"
|
||||||
|
fi
|
||||||
|
echo -e "${DGN}Using WAN Bridge: ${BGN}$BRG${CL}"
|
||||||
else
|
else
|
||||||
LAN_MAC="$MAC2"
|
exit-script
|
||||||
fi
|
fi
|
||||||
echo -e "${DGN}Using LAN MAC Address: ${BGN}$LAN_MAC${CL}"
|
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN Vlan (leave blank for default)" 8 58 --title "WAN VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if LAN_BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN Bridge" 8 58 vmbr0 --title "LAN BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $VLAN1 ]; then
|
if [ -z $LAN_BRG ]; then
|
||||||
VLAN1="Default"
|
LAN_BRG="vmbr0"
|
||||||
VLAN=""
|
fi
|
||||||
|
echo -e "${DGN}Using LAN Bridge: ${BGN}$LAN_BRG${CL}"
|
||||||
else
|
else
|
||||||
VLAN=",tag=$VLAN1"
|
exit-script
|
||||||
fi
|
fi
|
||||||
echo -e "${DGN}Using WAN Vlan: ${BGN}$VLAN1${CL}"
|
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VLAN2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN Vlan" 8 58 999 --title "LAN VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if LAN_IP_ADDR=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a router IP" 8 58 $LAN_IP_ADDR --title "LAN IP ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $VLAN2 ]; then
|
if [ -z $LAN_IP_ADDR ]; then
|
||||||
VLAN2="999"
|
LAN_IP_ADDR="192.168.1.1"
|
||||||
LAN_VLAN=",tag=$VLAN2"
|
fi
|
||||||
|
echo -e "${DGN}Using LAN IP ADDRESS: ${BGN}$LAN_IP_ADDR${CL}"
|
||||||
else
|
else
|
||||||
LAN_VLAN=",tag=$VLAN2"
|
exit-script
|
||||||
fi
|
fi
|
||||||
echo -e "${DGN}Using LAN Vlan: ${BGN}$VLAN2${CL}"
|
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if LAN_NETMASK=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a router netmask" 8 58 $LAN_NETMASK --title "LAN NETMASK" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $MTU1 ]; then
|
if [ -z $LAN_NETMASK ]; then
|
||||||
MTU1="Default"
|
LAN_NETMASK="255.255.255.0"
|
||||||
MTU=""
|
fi
|
||||||
|
echo -e "${DGN}Using LAN NETMASK: ${BGN}$LAN_NETMASK${CL}"
|
||||||
else
|
else
|
||||||
MTU=",mtu=$MTU1"
|
exit-script
|
||||||
fi
|
fi
|
||||||
echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
|
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN MAC Address" 8 58 $GEN_MAC --title "WAN MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
START_VM="yes"
|
if [ -z $MAC1 ]; then
|
||||||
else
|
MAC="$GEN_MAC"
|
||||||
START_VM="no"
|
else
|
||||||
fi
|
MAC="$MAC1"
|
||||||
echo -e "${DGN}Start VM when completed: ${BGN}$START_VM${CL}"
|
fi
|
||||||
|
echo -e "${DGN}Using WAN MAC Address: ${BGN}$MAC${CL}"
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create OpenWrt VM?" --no-button Do-Over 10 58); then
|
if MAC2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN MAC Address" 8 58 $GEN_MAC_LAN --title "LAN MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
echo -e "${RD}Creating a OpenWrt VM using the above advanced settings${CL}"
|
if [ -z $MAC2 ]; then
|
||||||
else
|
LAN_MAC="$GEN_MAC_LAN"
|
||||||
header_info
|
else
|
||||||
echo -e "${RD}Using Advanced Settings${CL}"
|
LAN_MAC="$MAC2"
|
||||||
advanced_settings
|
fi
|
||||||
fi
|
echo -e "${DGN}Using LAN MAC Address: ${BGN}$LAN_MAC${CL}"
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
|
||||||
|
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN Vlan (leave blank for default)" 8 58 --title "WAN VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
|
if [ -z $VLAN1 ]; then
|
||||||
|
VLAN1="Default"
|
||||||
|
VLAN=""
|
||||||
|
else
|
||||||
|
VLAN=",tag=$VLAN1"
|
||||||
|
fi
|
||||||
|
echo -e "${DGN}Using WAN Vlan: ${BGN}$VLAN1${CL}"
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
|
||||||
|
if VLAN2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN Vlan" 8 58 999 --title "LAN VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
|
if [ -z $VLAN2 ]; then
|
||||||
|
VLAN2="999"
|
||||||
|
LAN_VLAN=",tag=$VLAN2"
|
||||||
|
else
|
||||||
|
LAN_VLAN=",tag=$VLAN2"
|
||||||
|
fi
|
||||||
|
echo -e "${DGN}Using LAN Vlan: ${BGN}$VLAN2${CL}"
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
|
||||||
|
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
|
if [ -z $MTU1 ]; then
|
||||||
|
MTU1="Default"
|
||||||
|
MTU=""
|
||||||
|
else
|
||||||
|
MTU=",mtu=$MTU1"
|
||||||
|
fi
|
||||||
|
echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
||||||
|
START_VM="yes"
|
||||||
|
else
|
||||||
|
START_VM="no"
|
||||||
|
fi
|
||||||
|
echo -e "${DGN}Start VM when completed: ${BGN}$START_VM${CL}"
|
||||||
|
|
||||||
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create OpenWrt VM?" --no-button Do-Over 10 58); then
|
||||||
|
echo -e "${RD}Creating a OpenWrt VM using the above advanced settings${CL}"
|
||||||
|
else
|
||||||
|
header_info
|
||||||
|
echo -e "${RD}Using Advanced Settings${CL}"
|
||||||
|
advanced_settings
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function start_script() {
|
function start_script() {
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
||||||
header_info
|
header_info
|
||||||
echo -e "${BL}Using Default Settings${CL}"
|
echo -e "${BL}Using Default Settings${CL}"
|
||||||
default_settings
|
default_settings
|
||||||
else
|
else
|
||||||
header_info
|
header_info
|
||||||
echo -e "${RD}Using Advanced Settings${CL}"
|
echo -e "${RD}Using Advanced Settings${CL}"
|
||||||
advanced_settings
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
arch_check
|
arch_check
|
||||||
@@ -435,30 +435,30 @@ post_to_api_vm
|
|||||||
|
|
||||||
msg_info "Validating Storage"
|
msg_info "Validating Storage"
|
||||||
while read -r line; do
|
while read -r line; do
|
||||||
TAG=$(echo $line | awk '{print $1}')
|
TAG=$(echo $line | awk '{print $1}')
|
||||||
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
||||||
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
||||||
ITEM=" Type: $TYPE Free: $FREE "
|
ITEM=" Type: $TYPE Free: $FREE "
|
||||||
OFFSET=2
|
OFFSET=2
|
||||||
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
||||||
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
||||||
fi
|
fi
|
||||||
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
||||||
done < <(pvesm status -content images | awk 'NR>1')
|
done < <(pvesm status -content images | awk 'NR>1')
|
||||||
VALID=$(pvesm status -content images | awk 'NR>1')
|
VALID=$(pvesm status -content images | awk 'NR>1')
|
||||||
if [ -z "$VALID" ]; then
|
if [ -z "$VALID" ]; then
|
||||||
echo -e "\n${RD}⚠ Unable to detect a valid storage location.${CL}"
|
echo -e "\n${RD}⚠ Unable to detect a valid storage location.${CL}"
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
exit
|
exit
|
||||||
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
||||||
STORAGE=${STORAGE_MENU[0]}
|
STORAGE=${STORAGE_MENU[0]}
|
||||||
else
|
else
|
||||||
while [ -z "${STORAGE:+x}" ]; do
|
while [ -z "${STORAGE:+x}" ]; do
|
||||||
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
||||||
"Which storage pool would you like to use for the OpenWrt VM?\n\n" \
|
"Which storage pool would you like to use for the OpenWrt VM?\n\n" \
|
||||||
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
||||||
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
||||||
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
||||||
@@ -483,35 +483,35 @@ msg_ok "Extracted & Resized OpenWrt Disk Image ${CL}${BL}$FILE${CL}"
|
|||||||
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
||||||
case $STORAGE_TYPE in
|
case $STORAGE_TYPE in
|
||||||
nfs | dir)
|
nfs | dir)
|
||||||
DISK_EXT=".qcow2"
|
DISK_EXT=".qcow2"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format qcow2"
|
DISK_IMPORT="-format qcow2"
|
||||||
;;
|
;;
|
||||||
btrfs)
|
btrfs)
|
||||||
DISK_EXT=".raw"
|
DISK_EXT=".raw"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format raw"
|
DISK_IMPORT="-format raw"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
for i in {0,1}; do
|
for i in {0,1}; do
|
||||||
disk="DISK$i"
|
disk="DISK$i"
|
||||||
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
||||||
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
||||||
done
|
done
|
||||||
|
|
||||||
msg_info "Creating OpenWrt VM"
|
msg_info "Creating OpenWrt VM"
|
||||||
qm create $VMID -cores $CORE_COUNT -memory $RAM_SIZE -name $HN \
|
qm create $VMID -cores $CORE_COUNT -memory $RAM_SIZE -name $HN \
|
||||||
-onboot 1 -ostype l26 -scsihw virtio-scsi-pci --tablet 0
|
-onboot 1 -ostype l26 -scsihw virtio-scsi-pci --tablet 0
|
||||||
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
||||||
qm importdisk $VMID ${FILE%.*} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
qm importdisk $VMID ${FILE%.*} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
||||||
qm set $VMID \
|
qm set $VMID \
|
||||||
-efidisk0 ${DISK0_REF},efitype=4m,size=4M \
|
-efidisk0 ${DISK0_REF},efitype=4m,size=4M \
|
||||||
-scsi0 ${DISK1_REF},size=512M \
|
-scsi0 ${DISK1_REF},size=512M \
|
||||||
-boot order=scsi0 \
|
-boot order=scsi0 \
|
||||||
-tags community-script >/dev/null
|
-tags community-script >/dev/null
|
||||||
|
|
||||||
DESCRIPTION=$(
|
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://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
<img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
||||||
@@ -562,21 +562,21 @@ send_line_to_vm "uci commit"
|
|||||||
send_line_to_vm "halt"
|
send_line_to_vm "halt"
|
||||||
msg_ok "Network interfaces have been successfully configured."
|
msg_ok "Network interfaces have been successfully configured."
|
||||||
until qm status $VMID | grep -q "stopped"; do
|
until qm status $VMID | grep -q "stopped"; do
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
msg_info "Bridge interfaces are being added."
|
msg_info "Bridge interfaces are being added."
|
||||||
qm set $VMID \
|
qm set $VMID \
|
||||||
-net0 virtio,bridge=${LAN_BRG},macaddr=${LAN_MAC}${LAN_VLAN}${MTU} \
|
-net0 virtio,bridge=${LAN_BRG},macaddr=${LAN_MAC}${LAN_VLAN}${MTU} \
|
||||||
-net1 virtio,bridge=${BRG},macaddr=${MAC}${VLAN}${MTU} >/dev/null 2>/dev/null
|
-net1 virtio,bridge=${BRG},macaddr=${MAC}${VLAN}${MTU} >/dev/null 2>/dev/null
|
||||||
msg_ok "Bridge interfaces have been successfully added."
|
msg_ok "Bridge interfaces have been successfully added."
|
||||||
if [ "$START_VM" == "yes" ]; then
|
if [ "$START_VM" == "yes" ]; then
|
||||||
msg_info "Starting OpenWrt VM"
|
msg_info "Starting OpenWrt VM"
|
||||||
qm start $VMID
|
qm start $VMID
|
||||||
msg_ok "Started OpenWrt VM"
|
msg_ok "Started OpenWrt VM"
|
||||||
fi
|
fi
|
||||||
VLAN_FINISH=""
|
VLAN_FINISH=""
|
||||||
if [ "$VLAN" == "" ] && [ "$VLAN2" != "999" ]; then
|
if [ "$VLAN" == "" ] && [ "$VLAN2" != "999" ]; then
|
||||||
VLAN_FINISH=" Please remember to adjust the VLAN tags to suit your network."
|
VLAN_FINISH=" Please remember to adjust the VLAN tags to suit your network."
|
||||||
fi
|
fi
|
||||||
post_update_to_api "done" "none"
|
post_update_to_api "done" "none"
|
||||||
msg_ok "Completed Successfully!\n${VLAN_FINISH}"
|
msg_ok "Completed Successfully!\n${VLAN_FINISH}"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -9,8 +9,8 @@ COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.or
|
|||||||
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
||||||
|
|
||||||
function header_info {
|
function header_info {
|
||||||
clear
|
clear
|
||||||
cat <<"EOF"
|
cat <<"EOF"
|
||||||
______ __ __ _______ __ _ ____ ___
|
______ __ __ _______ __ _ ____ ___
|
||||||
/_ __/_ _________ / //_/__ __ __ ___ _ _____ / ___/ /__ __ _____/ / | | / / |/ /
|
/_ __/_ _________ / //_/__ __ __ ___ _ _____ / ___/ /__ __ _____/ / | | / / |/ /
|
||||||
/ / / // / __/ _ \/ ,< / -_) // / / _ \ |/|/ / _ \/ /__/ / _ \/ // / _ / | |/ / /|_/ /
|
/ / / // / __/ _ \/ ,< / -_) // / / _ \ |/|/ / _ \/ /__/ / _ \/ // / _ / | |/ / /|_/ /
|
||||||
@@ -48,322 +48,322 @@ trap cleanup EXIT
|
|||||||
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
||||||
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
||||||
function error_handler() {
|
function error_handler() {
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
local line_number="$1"
|
local line_number="$1"
|
||||||
local command="$2"
|
local command="$2"
|
||||||
post_update_to_api "failed" "$command"
|
post_update_to_api "failed" "$command"
|
||||||
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
||||||
echo -e "\n$error_message\n"
|
echo -e "\n$error_message\n"
|
||||||
cleanup_vmid
|
cleanup_vmid
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_valid_nextid() {
|
function get_valid_nextid() {
|
||||||
local try_id
|
local try_id
|
||||||
try_id=$(pvesh get /cluster/nextid)
|
try_id=$(pvesh get /cluster/nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
break
|
break
|
||||||
done
|
done
|
||||||
echo "$try_id"
|
echo "$try_id"
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup_vmid() {
|
function cleanup_vmid() {
|
||||||
if qm status $VMID &>/dev/null; then
|
if qm status $VMID &>/dev/null; then
|
||||||
qm stop $VMID &>/dev/null
|
qm stop $VMID &>/dev/null
|
||||||
qm destroy $VMID &>/dev/null
|
qm destroy $VMID &>/dev/null
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
pushd $TEMP_DIR >/dev/null
|
pushd $TEMP_DIR >/dev/null
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "$NAME" --yesno "This will create a New $NAME. Proceed?" 10 58; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "$NAME" --yesno "This will create a New $NAME. Proceed?" 10 58; then
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
header_info && echo -e "⚠ User exited script \n" && exit
|
header_info && echo -e "⚠ User exited script \n" && exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function msg_info() {
|
function msg_info() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_ok() {
|
function msg_ok() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_error() {
|
function msg_error() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_root() {
|
function check_root() {
|
||||||
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
||||||
clear
|
clear
|
||||||
msg_error "Please run this script as root."
|
msg_error "Please run this script as root."
|
||||||
echo -e "\nExiting..."
|
echo -e "\nExiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function pve_check() {
|
function pve_check() {
|
||||||
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
||||||
msg_error "This version of Proxmox Virtual Environment is not supported"
|
msg_error "This version of Proxmox Virtual Environment is not supported"
|
||||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function arch_check() {
|
function arch_check() {
|
||||||
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
||||||
msg_error "This script will not work with PiMox! \n"
|
msg_error "This script will not work with PiMox! \n"
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function ssh_check() {
|
function ssh_check() {
|
||||||
if command -v pveversion >/dev/null 2>&1; then
|
if command -v pveversion >/dev/null 2>&1; then
|
||||||
if [ -n "${SSH_CLIENT:+x}" ]; then
|
if [ -n "${SSH_CLIENT:+x}" ]; then
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
||||||
echo "you've been warned"
|
echo "you've been warned"
|
||||||
else
|
else
|
||||||
clear
|
clear
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function exit-script() {
|
function exit-script() {
|
||||||
clear
|
clear
|
||||||
echo -e "⚠ User exited script \n"
|
echo -e "⚠ User exited script \n"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
MACHINE=""
|
MACHINE=""
|
||||||
DISK_CACHE=""
|
DISK_CACHE=""
|
||||||
HN="turnkey-owncloud-vm"
|
HN="turnkey-owncloud-vm"
|
||||||
CPU_TYPE=""
|
CPU_TYPE=""
|
||||||
CORE_COUNT="2"
|
CORE_COUNT="2"
|
||||||
RAM_SIZE="2048"
|
RAM_SIZE="2048"
|
||||||
BRG="vmbr0"
|
BRG="vmbr0"
|
||||||
MAC="$GEN_MAC"
|
MAC="$GEN_MAC"
|
||||||
VLAN=""
|
VLAN=""
|
||||||
MTU=""
|
MTU=""
|
||||||
START_VM="no"
|
START_VM="no"
|
||||||
METHOD="default"
|
METHOD="default"
|
||||||
echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
|
echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
|
||||||
echo -e "${DGN}Using Machine Type: ${BGN}i440fx${CL}"
|
echo -e "${DGN}Using Machine Type: ${BGN}i440fx${CL}"
|
||||||
echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
|
echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
|
||||||
echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
|
echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
|
||||||
echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
|
echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
|
||||||
echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
|
echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
|
||||||
echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
|
echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
|
||||||
echo -e "${DGN}Using Bridge: ${BGN}${BRG}${CL}"
|
echo -e "${DGN}Using Bridge: ${BGN}${BRG}${CL}"
|
||||||
echo -e "${DGN}Using MAC Address: ${BGN}${MAC}${CL}"
|
echo -e "${DGN}Using MAC Address: ${BGN}${MAC}${CL}"
|
||||||
echo -e "${DGN}Using VLAN: ${BGN}Default${CL}"
|
echo -e "${DGN}Using VLAN: ${BGN}Default${CL}"
|
||||||
echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
|
echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
|
||||||
echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
|
echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
|
||||||
echo -e "${BL}Creating a $NAME using the above default settings${CL}"
|
echo -e "${BL}Creating a $NAME using the above default settings${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function advanced_settings() {
|
function advanced_settings() {
|
||||||
METHOD="advanced"
|
METHOD="advanced"
|
||||||
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z "$VMID" ]; then
|
if [ -z "$VMID" ]; then
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
fi
|
fi
|
||||||
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
||||||
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
||||||
sleep 2
|
sleep 2
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
||||||
break
|
break
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
||||||
|
"i440fx" "Machine i440fx" ON \
|
||||||
|
"q35" "Machine q35" OFF \
|
||||||
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $MACH = q35 ]; then
|
||||||
|
echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=""
|
||||||
|
MACHINE=" -machine q35"
|
||||||
|
else
|
||||||
|
echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=",efitype=4m"
|
||||||
|
MACHINE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
exit-script
|
exit-script
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
|
||||||
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
"i440fx" "Machine i440fx" ON \
|
"0" "None (Default)" ON \
|
||||||
"q35" "Machine q35" OFF \
|
"1" "Write Through" OFF \
|
||||||
3>&1 1>&2 2>&3); then
|
3>&1 1>&2 2>&3); then
|
||||||
if [ $MACH = q35 ]; then
|
if [ $DISK_CACHE = "1" ]; then
|
||||||
echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
|
echo -e "${DGN}Using Disk Cache: ${BGN}Write Through${CL}"
|
||||||
FORMAT=""
|
DISK_CACHE="cache=writethrough,"
|
||||||
MACHINE=" -machine q35"
|
else
|
||||||
|
echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
|
||||||
|
DISK_CACHE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
|
exit-script
|
||||||
FORMAT=",efitype=4m"
|
|
||||||
MACHINE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 turnkey-owncloud-vm --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "None (Default)" ON \
|
if [ -z $VM_NAME ]; then
|
||||||
"1" "Write Through" OFF \
|
HN="turnkey-owncloud-vm"
|
||||||
3>&1 1>&2 2>&3); then
|
echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
|
||||||
if [ $DISK_CACHE = "1" ]; then
|
else
|
||||||
echo -e "${DGN}Using Disk Cache: ${BGN}Write Through${CL}"
|
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
||||||
DISK_CACHE="cache=writethrough,"
|
echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
|
exit-script
|
||||||
DISK_CACHE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 turnkey-owncloud-vm --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
if [ -z $VM_NAME ]; then
|
"0" "KVM64 (Default)" ON \
|
||||||
HN="turnkey-owncloud-vm"
|
"1" "Host" OFF \
|
||||||
echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $CPU_TYPE1 = "1" ]; then
|
||||||
|
echo -e "${DGN}Using CPU Model: ${BGN}Host${CL}"
|
||||||
|
CPU_TYPE=" -cpu host"
|
||||||
|
else
|
||||||
|
echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
|
||||||
|
CPU_TYPE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
exit-script
|
||||||
echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "KVM64 (Default)" ON \
|
if [ -z $CORE_COUNT ]; then
|
||||||
"1" "Host" OFF \
|
CORE_COUNT="2"
|
||||||
3>&1 1>&2 2>&3); then
|
echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
if [ $CPU_TYPE1 = "1" ]; then
|
else
|
||||||
echo -e "${DGN}Using CPU Model: ${BGN}Host${CL}"
|
echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
CPU_TYPE=" -cpu host"
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
|
exit-script
|
||||||
CPU_TYPE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $CORE_COUNT ]; then
|
if [ -z $RAM_SIZE ]; then
|
||||||
CORE_COUNT="2"
|
RAM_SIZE="2048"
|
||||||
echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
|
echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $RAM_SIZE ]; then
|
if [ -z $BRG ]; then
|
||||||
RAM_SIZE="2048"
|
BRG="vmbr0"
|
||||||
echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
|
echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $BRG ]; then
|
if [ -z $MAC1 ]; then
|
||||||
BRG="vmbr0"
|
MAC="$GEN_MAC"
|
||||||
echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
|
echo -e "${DGN}Using MAC Address: ${BGN}$MAC${CL}"
|
||||||
|
else
|
||||||
|
MAC="$MAC1"
|
||||||
|
echo -e "${DGN}Using MAC Address: ${BGN}$MAC1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $MAC1 ]; then
|
if [ -z $VLAN1 ]; then
|
||||||
MAC="$GEN_MAC"
|
VLAN1="Default"
|
||||||
echo -e "${DGN}Using MAC Address: ${BGN}$MAC${CL}"
|
VLAN=""
|
||||||
|
echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
|
||||||
|
else
|
||||||
|
VLAN=",tag=$VLAN1"
|
||||||
|
echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
MAC="$MAC1"
|
exit-script
|
||||||
echo -e "${DGN}Using MAC Address: ${BGN}$MAC1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $VLAN1 ]; then
|
if [ -z $MTU1 ]; then
|
||||||
VLAN1="Default"
|
MTU1="Default"
|
||||||
VLAN=""
|
MTU=""
|
||||||
echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
|
echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
else
|
||||||
|
MTU=",mtu=$MTU1"
|
||||||
|
echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
VLAN=",tag=$VLAN1"
|
exit-script
|
||||||
echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
||||||
if [ -z $MTU1 ]; then
|
echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
MTU1="Default"
|
START_VM="yes"
|
||||||
MTU=""
|
|
||||||
echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
|
|
||||||
else
|
else
|
||||||
MTU=",mtu=$MTU1"
|
echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
|
||||||
echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
|
START_VM="no"
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a $NAME?" --no-button Do-Over 10 58); then
|
||||||
echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
|
echo -e "${RD}Creating a $NAME using the above advanced settings${CL}"
|
||||||
START_VM="yes"
|
else
|
||||||
else
|
header_info
|
||||||
echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
|
echo -e "${RD}Using Advanced Settings${CL}"
|
||||||
START_VM="no"
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a $NAME?" --no-button Do-Over 10 58); then
|
|
||||||
echo -e "${RD}Creating a $NAME using the above advanced settings${CL}"
|
|
||||||
else
|
|
||||||
header_info
|
|
||||||
echo -e "${RD}Using Advanced Settings${CL}"
|
|
||||||
advanced_settings
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function start_script() {
|
function start_script() {
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
||||||
header_info
|
header_info
|
||||||
echo -e "${BL}Using Default Settings${CL}"
|
echo -e "${BL}Using Default Settings${CL}"
|
||||||
default_settings
|
default_settings
|
||||||
else
|
else
|
||||||
header_info
|
header_info
|
||||||
echo -e "${RD}Using Advanced Settings${CL}"
|
echo -e "${RD}Using Advanced Settings${CL}"
|
||||||
advanced_settings
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
check_root
|
check_root
|
||||||
@@ -376,29 +376,29 @@ post_to_api_vm
|
|||||||
|
|
||||||
msg_info "Validating Storage"
|
msg_info "Validating Storage"
|
||||||
while read -r line; do
|
while read -r line; do
|
||||||
TAG=$(echo $line | awk '{print $1}')
|
TAG=$(echo $line | awk '{print $1}')
|
||||||
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
||||||
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
||||||
ITEM=" Type: $TYPE Free: $FREE "
|
ITEM=" Type: $TYPE Free: $FREE "
|
||||||
OFFSET=2
|
OFFSET=2
|
||||||
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
||||||
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
||||||
fi
|
fi
|
||||||
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
||||||
done < <(pvesm status -content images | awk 'NR>1')
|
done < <(pvesm status -content images | awk 'NR>1')
|
||||||
VALID=$(pvesm status -content images | awk 'NR>1')
|
VALID=$(pvesm status -content images | awk 'NR>1')
|
||||||
if [ -z "$VALID" ]; then
|
if [ -z "$VALID" ]; then
|
||||||
msg_error "Unable to detect a valid storage location."
|
msg_error "Unable to detect a valid storage location."
|
||||||
exit
|
exit
|
||||||
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
||||||
STORAGE=${STORAGE_MENU[0]}
|
STORAGE=${STORAGE_MENU[0]}
|
||||||
else
|
else
|
||||||
while [ -z "${STORAGE:+x}" ]; do
|
while [ -z "${STORAGE:+x}" ]; do
|
||||||
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
||||||
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
||||||
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
||||||
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
||||||
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
||||||
@@ -414,39 +414,39 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
|
|||||||
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
||||||
case $STORAGE_TYPE in
|
case $STORAGE_TYPE in
|
||||||
nfs | dir)
|
nfs | dir)
|
||||||
DISK_EXT=".raw"
|
DISK_EXT=".raw"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format raw"
|
DISK_IMPORT="-format raw"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
btrfs)
|
btrfs)
|
||||||
DISK_EXT=".raw"
|
DISK_EXT=".raw"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format raw"
|
DISK_IMPORT="-format raw"
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
for i in {0,1,2}; do
|
for i in {0,1,2}; do
|
||||||
disk="DISK$i"
|
disk="DISK$i"
|
||||||
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
||||||
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
||||||
done
|
done
|
||||||
|
|
||||||
msg_info "Creating a $NAME"
|
msg_info "Creating a $NAME"
|
||||||
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios seabios${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios seabios${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
||||||
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
|
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
|
||||||
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
||||||
pvesm alloc $STORAGE $VMID $DISK1 12G 1>&/dev/null
|
pvesm alloc $STORAGE $VMID $DISK1 12G 1>&/dev/null
|
||||||
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
||||||
qm set $VMID \
|
qm set $VMID \
|
||||||
-efidisk0 ${DISK0_REF}${FORMAT} \
|
-efidisk0 ${DISK0_REF}${FORMAT} \
|
||||||
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN} \
|
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN} \
|
||||||
-scsi1 ${DISK2_REF},${DISK_CACHE}${THIN} \
|
-scsi1 ${DISK2_REF},${DISK_CACHE}${THIN} \
|
||||||
-boot order='scsi1;scsi0' >/dev/null
|
-boot order='scsi1;scsi0' >/dev/null
|
||||||
|
|
||||||
DESCRIPTION=$(
|
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://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
<img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
||||||
@@ -478,9 +478,9 @@ EOF
|
|||||||
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
||||||
msg_ok "Created a $NAME ${CL}${BL}(${HN})"
|
msg_ok "Created a $NAME ${CL}${BL}(${HN})"
|
||||||
if [ "$START_VM" == "yes" ]; then
|
if [ "$START_VM" == "yes" ]; then
|
||||||
msg_info "Starting $NAME"
|
msg_info "Starting $NAME"
|
||||||
qm start $VMID
|
qm start $VMID
|
||||||
msg_ok "Started $NAME"
|
msg_ok "Started $NAME"
|
||||||
fi
|
fi
|
||||||
post_update_to_api "done" "none"
|
post_update_to_api "done" "none"
|
||||||
msg_ok "Completed successfully!\n"
|
msg_ok "Completed successfully!\n"
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.or
|
|||||||
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
||||||
|
|
||||||
function header_info {
|
function header_info {
|
||||||
clear
|
clear
|
||||||
cat <<"EOF"
|
cat <<"EOF"
|
||||||
__ ____ __ ___ ___ ____ __ __ _ ____ ___
|
__ ____ __ ___ ___ ____ __ __ _ ____ ___
|
||||||
/ / / / /_ __ ______ / /___ __ |__ \|__ \ / __ \/ // / | | / / |/ /
|
/ / / / /_ __ ______ / /___ __ |__ \|__ \ / __ \/ // / | | / / |/ /
|
||||||
/ / / / __ \/ / / / __ \/ __/ / / / __/ /__/ / / / / / // /_ | | / / /|_/ /
|
/ / / / __ \/ / / / __ \/ __/ / / / __/ /__/ / / / / / // /_ | | / / /|_/ /
|
||||||
@@ -64,340 +64,340 @@ trap cleanup EXIT
|
|||||||
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
||||||
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
||||||
function error_handler() {
|
function error_handler() {
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
local line_number="$1"
|
local line_number="$1"
|
||||||
local command="$2"
|
local command="$2"
|
||||||
post_update_to_api "failed" "$command"
|
post_update_to_api "failed" "$command"
|
||||||
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
||||||
echo -e "\n$error_message\n"
|
echo -e "\n$error_message\n"
|
||||||
cleanup_vmid
|
cleanup_vmid
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_valid_nextid() {
|
function get_valid_nextid() {
|
||||||
local try_id
|
local try_id
|
||||||
try_id=$(pvesh get /cluster/nextid)
|
try_id=$(pvesh get /cluster/nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
break
|
break
|
||||||
done
|
done
|
||||||
echo "$try_id"
|
echo "$try_id"
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup_vmid() {
|
function cleanup_vmid() {
|
||||||
if qm status $VMID &>/dev/null; then
|
if qm status $VMID &>/dev/null; then
|
||||||
qm stop $VMID &>/dev/null
|
qm stop $VMID &>/dev/null
|
||||||
qm destroy $VMID &>/dev/null
|
qm destroy $VMID &>/dev/null
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
pushd $TEMP_DIR >/dev/null
|
pushd $TEMP_DIR >/dev/null
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Ubuntu 22.04 VM" --yesno "This will create a New Ubuntu 22.04 VM. Proceed?" 10 58; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Ubuntu 22.04 VM" --yesno "This will create a New Ubuntu 22.04 VM. Proceed?" 10 58; then
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
|
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function msg_info() {
|
function msg_info() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
|
echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_ok() {
|
function msg_ok() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_error() {
|
function msg_error() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_root() {
|
function check_root() {
|
||||||
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
||||||
clear
|
clear
|
||||||
msg_error "Please run this script as root."
|
msg_error "Please run this script as root."
|
||||||
echo -e "\nExiting..."
|
echo -e "\nExiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function pve_check() {
|
function pve_check() {
|
||||||
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
||||||
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
||||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function arch_check() {
|
function arch_check() {
|
||||||
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
||||||
echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
|
echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
|
||||||
echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
|
echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function ssh_check() {
|
function ssh_check() {
|
||||||
if command -v pveversion >/dev/null 2>&1; then
|
if command -v pveversion >/dev/null 2>&1; then
|
||||||
if [ -n "${SSH_CLIENT:+x}" ]; then
|
if [ -n "${SSH_CLIENT:+x}" ]; then
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
||||||
echo "you've been warned"
|
echo "you've been warned"
|
||||||
else
|
else
|
||||||
clear
|
clear
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function exit-script() {
|
function exit-script() {
|
||||||
clear
|
clear
|
||||||
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
|
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
MACHINE=""
|
MACHINE=""
|
||||||
DISK_SIZE="5G"
|
DISK_SIZE="5G"
|
||||||
DISK_CACHE=""
|
DISK_CACHE=""
|
||||||
HN="ubuntu"
|
HN="ubuntu"
|
||||||
CPU_TYPE=""
|
CPU_TYPE=""
|
||||||
CORE_COUNT="2"
|
CORE_COUNT="2"
|
||||||
RAM_SIZE="2048"
|
RAM_SIZE="2048"
|
||||||
BRG="vmbr0"
|
BRG="vmbr0"
|
||||||
MAC="$GEN_MAC"
|
MAC="$GEN_MAC"
|
||||||
VLAN=""
|
VLAN=""
|
||||||
MTU=""
|
MTU=""
|
||||||
START_VM="yes"
|
START_VM="yes"
|
||||||
METHOD="default"
|
METHOD="default"
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 22.04 VM using the above default settings${CL}"
|
echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 22.04 VM using the above default settings${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function advanced_settings() {
|
function advanced_settings() {
|
||||||
METHOD="advanced"
|
METHOD="advanced"
|
||||||
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z "$VMID" ]; then
|
if [ -z "$VMID" ]; then
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
fi
|
fi
|
||||||
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
||||||
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
||||||
sleep 2
|
sleep 2
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
||||||
break
|
break
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
||||||
|
"i440fx" "Machine i440fx" ON \
|
||||||
|
"q35" "Machine q35" OFF \
|
||||||
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $MACH = q35 ]; then
|
||||||
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=""
|
||||||
|
MACHINE=" -machine q35"
|
||||||
|
else
|
||||||
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=",efitype=4m"
|
||||||
|
MACHINE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
exit-script
|
exit-script
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
|
||||||
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"i440fx" "Machine i440fx" ON \
|
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
|
||||||
"q35" "Machine q35" OFF \
|
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
|
||||||
3>&1 1>&2 2>&3); then
|
DISK_SIZE="${DISK_SIZE}G"
|
||||||
if [ $MACH = q35 ]; then
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
|
||||||
FORMAT=""
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
||||||
MACHINE=" -machine q35"
|
else
|
||||||
|
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
exit-script
|
||||||
FORMAT=",efitype=4m"
|
|
||||||
MACHINE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
|
"0" "None (Default)" ON \
|
||||||
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
|
"1" "Write Through" OFF \
|
||||||
DISK_SIZE="${DISK_SIZE}G"
|
3>&1 1>&2 2>&3); then
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
if [ $DISK_CACHE = "1" ]; then
|
||||||
elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
DISK_CACHE="cache=writethrough,"
|
||||||
|
else
|
||||||
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
||||||
|
DISK_CACHE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
|
exit-script
|
||||||
exit-script
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 ubuntu --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "None (Default)" ON \
|
if [ -z $VM_NAME ]; then
|
||||||
"1" "Write Through" OFF \
|
HN="ubuntu"
|
||||||
3>&1 1>&2 2>&3); then
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
if [ $DISK_CACHE = "1" ]; then
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
|
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
||||||
DISK_CACHE="cache=writethrough,"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
exit-script
|
||||||
DISK_CACHE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 ubuntu --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
if [ -z $VM_NAME ]; then
|
"0" "KVM64 (Default)" ON \
|
||||||
HN="ubuntu"
|
"1" "Host" OFF \
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $CPU_TYPE1 = "1" ]; then
|
||||||
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
|
||||||
|
CPU_TYPE=" -cpu host"
|
||||||
|
else
|
||||||
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
||||||
|
CPU_TYPE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
exit-script
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "KVM64 (Default)" ON \
|
if [ -z $CORE_COUNT ]; then
|
||||||
"1" "Host" OFF \
|
CORE_COUNT="2"
|
||||||
3>&1 1>&2 2>&3); then
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
if [ $CPU_TYPE1 = "1" ]; then
|
else
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
CPU_TYPE=" -cpu host"
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
exit-script
|
||||||
CPU_TYPE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $CORE_COUNT ]; then
|
if [ -z $RAM_SIZE ]; then
|
||||||
CORE_COUNT="2"
|
RAM_SIZE="2048"
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $RAM_SIZE ]; then
|
if [ -z $BRG ]; then
|
||||||
RAM_SIZE="2048"
|
BRG="vmbr0"
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $BRG ]; then
|
if [ -z $MAC1 ]; then
|
||||||
BRG="vmbr0"
|
MAC="$GEN_MAC"
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
|
||||||
|
else
|
||||||
|
MAC="$MAC1"
|
||||||
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $MAC1 ]; then
|
if [ -z $VLAN1 ]; then
|
||||||
MAC="$GEN_MAC"
|
VLAN1="Default"
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
|
VLAN=""
|
||||||
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
||||||
|
else
|
||||||
|
VLAN=",tag=$VLAN1"
|
||||||
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
MAC="$MAC1"
|
exit-script
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $VLAN1 ]; then
|
if [ -z $MTU1 ]; then
|
||||||
VLAN1="Default"
|
MTU1="Default"
|
||||||
VLAN=""
|
MTU=""
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
else
|
||||||
|
MTU=",mtu=$MTU1"
|
||||||
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
VLAN=",tag=$VLAN1"
|
exit-script
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
||||||
if [ -z $MTU1 ]; then
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
MTU1="Default"
|
START_VM="yes"
|
||||||
MTU=""
|
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
|
||||||
else
|
else
|
||||||
MTU=",mtu=$MTU1"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
START_VM="no"
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Ubuntu 22.04 VM?" --no-button Do-Over 10 58); then
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 22.04 VM using the above advanced settings${CL}"
|
||||||
START_VM="yes"
|
else
|
||||||
else
|
header_info
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
|
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
||||||
START_VM="no"
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Ubuntu 22.04 VM?" --no-button Do-Over 10 58); then
|
|
||||||
echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 22.04 VM using the above advanced settings${CL}"
|
|
||||||
else
|
|
||||||
header_info
|
|
||||||
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
|
||||||
advanced_settings
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function start_script() {
|
function start_script() {
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
||||||
header_info
|
header_info
|
||||||
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
|
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
|
||||||
default_settings
|
default_settings
|
||||||
else
|
else
|
||||||
header_info
|
header_info
|
||||||
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
||||||
advanced_settings
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
check_root
|
check_root
|
||||||
@@ -409,29 +409,29 @@ post_to_api_vm
|
|||||||
|
|
||||||
msg_info "Validating Storage"
|
msg_info "Validating Storage"
|
||||||
while read -r line; do
|
while read -r line; do
|
||||||
TAG=$(echo $line | awk '{print $1}')
|
TAG=$(echo $line | awk '{print $1}')
|
||||||
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
||||||
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
||||||
ITEM=" Type: $TYPE Free: $FREE "
|
ITEM=" Type: $TYPE Free: $FREE "
|
||||||
OFFSET=2
|
OFFSET=2
|
||||||
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
||||||
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
||||||
fi
|
fi
|
||||||
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
||||||
done < <(pvesm status -content images | awk 'NR>1')
|
done < <(pvesm status -content images | awk 'NR>1')
|
||||||
VALID=$(pvesm status -content images | awk 'NR>1')
|
VALID=$(pvesm status -content images | awk 'NR>1')
|
||||||
if [ -z "$VALID" ]; then
|
if [ -z "$VALID" ]; then
|
||||||
msg_error "Unable to detect a valid storage location."
|
msg_error "Unable to detect a valid storage location."
|
||||||
exit
|
exit
|
||||||
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
||||||
STORAGE=${STORAGE_MENU[0]}
|
STORAGE=${STORAGE_MENU[0]}
|
||||||
else
|
else
|
||||||
while [ -z "${STORAGE:+x}" ]; do
|
while [ -z "${STORAGE:+x}" ]; do
|
||||||
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
||||||
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
||||||
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
||||||
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
||||||
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
||||||
@@ -447,38 +447,38 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
|
|||||||
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
||||||
case $STORAGE_TYPE in
|
case $STORAGE_TYPE in
|
||||||
nfs | dir | cifs)
|
nfs | dir | cifs)
|
||||||
DISK_EXT=".qcow2"
|
DISK_EXT=".qcow2"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format qcow2"
|
DISK_IMPORT="-format qcow2"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
btrfs)
|
btrfs)
|
||||||
DISK_EXT=".raw"
|
DISK_EXT=".raw"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format raw"
|
DISK_IMPORT="-format raw"
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
for i in {0,1}; do
|
for i in {0,1}; do
|
||||||
disk="DISK$i"
|
disk="DISK$i"
|
||||||
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
||||||
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
||||||
done
|
done
|
||||||
|
|
||||||
msg_info "Creating a Ubuntu 22.04 VM"
|
msg_info "Creating a Ubuntu 22.04 VM"
|
||||||
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
||||||
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
|
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
|
||||||
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
||||||
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
||||||
qm set $VMID \
|
qm set $VMID \
|
||||||
-efidisk0 ${DISK0_REF}${FORMAT} \
|
-efidisk0 ${DISK0_REF}${FORMAT} \
|
||||||
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
|
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
|
||||||
-ide2 ${STORAGE}:cloudinit \
|
-ide2 ${STORAGE}:cloudinit \
|
||||||
-boot order=scsi0 \
|
-boot order=scsi0 \
|
||||||
-serial0 socket >/dev/null
|
-serial0 socket >/dev/null
|
||||||
DESCRIPTION=$(
|
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://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
<img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
||||||
@@ -509,18 +509,18 @@ EOF
|
|||||||
)
|
)
|
||||||
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
||||||
if [ -n "$DISK_SIZE" ]; then
|
if [ -n "$DISK_SIZE" ]; then
|
||||||
msg_info "Resizing disk to $DISK_SIZE GB"
|
msg_info "Resizing disk to $DISK_SIZE GB"
|
||||||
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
|
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
|
||||||
else
|
else
|
||||||
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
|
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
|
||||||
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
|
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_ok "Created a Ubuntu 22.04 VM ${CL}${BL}(${HN})"
|
msg_ok "Created a Ubuntu 22.04 VM ${CL}${BL}(${HN})"
|
||||||
if [ "$START_VM" == "yes" ]; then
|
if [ "$START_VM" == "yes" ]; then
|
||||||
msg_info "Starting Ubuntu 22.04 VM"
|
msg_info "Starting Ubuntu 22.04 VM"
|
||||||
qm start $VMID
|
qm start $VMID
|
||||||
msg_ok "Started Ubuntu 22.04 VM"
|
msg_ok "Started Ubuntu 22.04 VM"
|
||||||
fi
|
fi
|
||||||
post_update_to_api "done" "none"
|
post_update_to_api "done" "none"
|
||||||
msg_ok "Completed successfully!\n"
|
msg_ok "Completed successfully!\n"
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.or
|
|||||||
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
||||||
|
|
||||||
function header_info {
|
function header_info {
|
||||||
clear
|
clear
|
||||||
cat <<"EOF"
|
cat <<"EOF"
|
||||||
__ ____ __ ___ __ __ ____ __ __ _ ____ ___
|
__ ____ __ ___ __ __ ____ __ __ _ ____ ___
|
||||||
/ / / / /_ __ ______ / /___ __ |__ \/ // / / __ \/ // / | | / / |/ /
|
/ / / / /_ __ ______ / /___ __ |__ \/ // / / __ \/ // / | | / / |/ /
|
||||||
/ / / / __ \/ / / / __ \/ __/ / / / __/ / // /_ / / / / // /_ | | / / /|_/ /
|
/ / / / __ \/ / / / __ \/ __/ / / / __/ / // /_ / / / / // /_ | | / / /|_/ /
|
||||||
@@ -67,340 +67,340 @@ trap cleanup EXIT
|
|||||||
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
||||||
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
||||||
function error_handler() {
|
function error_handler() {
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
local line_number="$1"
|
local line_number="$1"
|
||||||
local command="$2"
|
local command="$2"
|
||||||
post_update_to_api "failed" "$command"
|
post_update_to_api "failed" "$command"
|
||||||
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
||||||
echo -e "\n$error_message\n"
|
echo -e "\n$error_message\n"
|
||||||
cleanup_vmid
|
cleanup_vmid
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_valid_nextid() {
|
function get_valid_nextid() {
|
||||||
local try_id
|
local try_id
|
||||||
try_id=$(pvesh get /cluster/nextid)
|
try_id=$(pvesh get /cluster/nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
break
|
break
|
||||||
done
|
done
|
||||||
echo "$try_id"
|
echo "$try_id"
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup_vmid() {
|
function cleanup_vmid() {
|
||||||
if qm status $VMID &>/dev/null; then
|
if qm status $VMID &>/dev/null; then
|
||||||
qm stop $VMID &>/dev/null
|
qm stop $VMID &>/dev/null
|
||||||
qm destroy $VMID &>/dev/null
|
qm destroy $VMID &>/dev/null
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
pushd $TEMP_DIR >/dev/null
|
pushd $TEMP_DIR >/dev/null
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Ubuntu 24.04 VM" --yesno "This will create a New Ubuntu 24.04 VM. Proceed?" 10 58; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Ubuntu 24.04 VM" --yesno "This will create a New Ubuntu 24.04 VM. Proceed?" 10 58; then
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
|
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function msg_info() {
|
function msg_info() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
|
echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_ok() {
|
function msg_ok() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_error() {
|
function msg_error() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_root() {
|
function check_root() {
|
||||||
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
||||||
clear
|
clear
|
||||||
msg_error "Please run this script as root."
|
msg_error "Please run this script as root."
|
||||||
echo -e "\nExiting..."
|
echo -e "\nExiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function pve_check() {
|
function pve_check() {
|
||||||
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
||||||
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
||||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function arch_check() {
|
function arch_check() {
|
||||||
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
||||||
echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
|
echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
|
||||||
echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
|
echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function ssh_check() {
|
function ssh_check() {
|
||||||
if command -v pveversion >/dev/null 2>&1; then
|
if command -v pveversion >/dev/null 2>&1; then
|
||||||
if [ -n "${SSH_CLIENT:+x}" ]; then
|
if [ -n "${SSH_CLIENT:+x}" ]; then
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
||||||
echo "you've been warned"
|
echo "you've been warned"
|
||||||
else
|
else
|
||||||
clear
|
clear
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function exit-script() {
|
function exit-script() {
|
||||||
clear
|
clear
|
||||||
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
|
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
MACHINE=""
|
MACHINE=""
|
||||||
DISK_SIZE="7G"
|
DISK_SIZE="7G"
|
||||||
DISK_CACHE=""
|
DISK_CACHE=""
|
||||||
HN="ubuntu"
|
HN="ubuntu"
|
||||||
CPU_TYPE=""
|
CPU_TYPE=""
|
||||||
CORE_COUNT="2"
|
CORE_COUNT="2"
|
||||||
RAM_SIZE="2048"
|
RAM_SIZE="2048"
|
||||||
BRG="vmbr0"
|
BRG="vmbr0"
|
||||||
MAC="$GEN_MAC"
|
MAC="$GEN_MAC"
|
||||||
VLAN=""
|
VLAN=""
|
||||||
MTU=""
|
MTU=""
|
||||||
START_VM="yes"
|
START_VM="yes"
|
||||||
METHOD="default"
|
METHOD="default"
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 24.04 VM using the above default settings${CL}"
|
echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 24.04 VM using the above default settings${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function advanced_settings() {
|
function advanced_settings() {
|
||||||
METHOD="advanced"
|
METHOD="advanced"
|
||||||
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z "$VMID" ]; then
|
if [ -z "$VMID" ]; then
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
fi
|
fi
|
||||||
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
||||||
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
||||||
sleep 2
|
sleep 2
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
||||||
break
|
break
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
||||||
|
"i440fx" "Machine i440fx" ON \
|
||||||
|
"q35" "Machine q35" OFF \
|
||||||
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $MACH = q35 ]; then
|
||||||
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=""
|
||||||
|
MACHINE=" -machine q35"
|
||||||
|
else
|
||||||
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=",efitype=4m"
|
||||||
|
MACHINE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
exit-script
|
exit-script
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
|
||||||
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"i440fx" "Machine i440fx" ON \
|
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
|
||||||
"q35" "Machine q35" OFF \
|
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
|
||||||
3>&1 1>&2 2>&3); then
|
DISK_SIZE="${DISK_SIZE}G"
|
||||||
if [ $MACH = q35 ]; then
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
|
||||||
FORMAT=""
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
||||||
MACHINE=" -machine q35"
|
else
|
||||||
|
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
exit-script
|
||||||
FORMAT=",efitype=4m"
|
|
||||||
MACHINE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
|
"0" "None (Default)" ON \
|
||||||
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
|
"1" "Write Through" OFF \
|
||||||
DISK_SIZE="${DISK_SIZE}G"
|
3>&1 1>&2 2>&3); then
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
if [ $DISK_CACHE = "1" ]; then
|
||||||
elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
DISK_CACHE="cache=writethrough,"
|
||||||
|
else
|
||||||
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
||||||
|
DISK_CACHE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
|
exit-script
|
||||||
exit-script
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 ubuntu --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "None (Default)" ON \
|
if [ -z $VM_NAME ]; then
|
||||||
"1" "Write Through" OFF \
|
HN="ubuntu"
|
||||||
3>&1 1>&2 2>&3); then
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
if [ $DISK_CACHE = "1" ]; then
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
|
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
||||||
DISK_CACHE="cache=writethrough,"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
exit-script
|
||||||
DISK_CACHE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 ubuntu --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
if [ -z $VM_NAME ]; then
|
"0" "KVM64 (Default)" ON \
|
||||||
HN="ubuntu"
|
"1" "Host" OFF \
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $CPU_TYPE1 = "1" ]; then
|
||||||
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
|
||||||
|
CPU_TYPE=" -cpu host"
|
||||||
|
else
|
||||||
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
||||||
|
CPU_TYPE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
exit-script
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "KVM64 (Default)" ON \
|
if [ -z $CORE_COUNT ]; then
|
||||||
"1" "Host" OFF \
|
CORE_COUNT="2"
|
||||||
3>&1 1>&2 2>&3); then
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
if [ $CPU_TYPE1 = "1" ]; then
|
else
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
CPU_TYPE=" -cpu host"
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
exit-script
|
||||||
CPU_TYPE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $CORE_COUNT ]; then
|
if [ -z $RAM_SIZE ]; then
|
||||||
CORE_COUNT="2"
|
RAM_SIZE="2048"
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $RAM_SIZE ]; then
|
if [ -z $BRG ]; then
|
||||||
RAM_SIZE="2048"
|
BRG="vmbr0"
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $BRG ]; then
|
if [ -z $MAC1 ]; then
|
||||||
BRG="vmbr0"
|
MAC="$GEN_MAC"
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
|
||||||
|
else
|
||||||
|
MAC="$MAC1"
|
||||||
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $MAC1 ]; then
|
if [ -z $VLAN1 ]; then
|
||||||
MAC="$GEN_MAC"
|
VLAN1="Default"
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
|
VLAN=""
|
||||||
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
||||||
|
else
|
||||||
|
VLAN=",tag=$VLAN1"
|
||||||
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
MAC="$MAC1"
|
exit-script
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $VLAN1 ]; then
|
if [ -z $MTU1 ]; then
|
||||||
VLAN1="Default"
|
MTU1="Default"
|
||||||
VLAN=""
|
MTU=""
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
else
|
||||||
|
MTU=",mtu=$MTU1"
|
||||||
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
VLAN=",tag=$VLAN1"
|
exit-script
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
||||||
if [ -z $MTU1 ]; then
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
MTU1="Default"
|
START_VM="yes"
|
||||||
MTU=""
|
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
|
||||||
else
|
else
|
||||||
MTU=",mtu=$MTU1"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
START_VM="no"
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Ubuntu 24.04 VM?" --no-button Do-Over 10 58); then
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 24.04 VM using the above advanced settings${CL}"
|
||||||
START_VM="yes"
|
else
|
||||||
else
|
header_info
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
|
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
||||||
START_VM="no"
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Ubuntu 24.04 VM?" --no-button Do-Over 10 58); then
|
|
||||||
echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 24.04 VM using the above advanced settings${CL}"
|
|
||||||
else
|
|
||||||
header_info
|
|
||||||
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
|
||||||
advanced_settings
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function start_script() {
|
function start_script() {
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
||||||
header_info
|
header_info
|
||||||
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
|
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
|
||||||
default_settings
|
default_settings
|
||||||
else
|
else
|
||||||
header_info
|
header_info
|
||||||
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
||||||
advanced_settings
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
check_root
|
check_root
|
||||||
arch_check
|
arch_check
|
||||||
@@ -411,29 +411,29 @@ post_to_api_vm
|
|||||||
|
|
||||||
msg_info "Validating Storage"
|
msg_info "Validating Storage"
|
||||||
while read -r line; do
|
while read -r line; do
|
||||||
TAG=$(echo $line | awk '{print $1}')
|
TAG=$(echo $line | awk '{print $1}')
|
||||||
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
||||||
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
||||||
ITEM=" Type: $TYPE Free: $FREE "
|
ITEM=" Type: $TYPE Free: $FREE "
|
||||||
OFFSET=2
|
OFFSET=2
|
||||||
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
||||||
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
||||||
fi
|
fi
|
||||||
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
||||||
done < <(pvesm status -content images | awk 'NR>1')
|
done < <(pvesm status -content images | awk 'NR>1')
|
||||||
VALID=$(pvesm status -content images | awk 'NR>1')
|
VALID=$(pvesm status -content images | awk 'NR>1')
|
||||||
if [ -z "$VALID" ]; then
|
if [ -z "$VALID" ]; then
|
||||||
msg_error "Unable to detect a valid storage location."
|
msg_error "Unable to detect a valid storage location."
|
||||||
exit
|
exit
|
||||||
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
||||||
STORAGE=${STORAGE_MENU[0]}
|
STORAGE=${STORAGE_MENU[0]}
|
||||||
else
|
else
|
||||||
while [ -z "${STORAGE:+x}" ]; do
|
while [ -z "${STORAGE:+x}" ]; do
|
||||||
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
||||||
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
||||||
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
||||||
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
||||||
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
||||||
@@ -449,38 +449,38 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
|
|||||||
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
||||||
case $STORAGE_TYPE in
|
case $STORAGE_TYPE in
|
||||||
nfs | dir | cifs)
|
nfs | dir | cifs)
|
||||||
DISK_EXT=".qcow2"
|
DISK_EXT=".qcow2"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format qcow2"
|
DISK_IMPORT="-format qcow2"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
btrfs)
|
btrfs)
|
||||||
DISK_EXT=".raw"
|
DISK_EXT=".raw"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format raw"
|
DISK_IMPORT="-format raw"
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
for i in {0,1}; do
|
for i in {0,1}; do
|
||||||
disk="DISK$i"
|
disk="DISK$i"
|
||||||
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
||||||
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
||||||
done
|
done
|
||||||
|
|
||||||
msg_info "Creating a Ubuntu 24.04 VM"
|
msg_info "Creating a Ubuntu 24.04 VM"
|
||||||
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
||||||
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
|
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
|
||||||
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
||||||
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
||||||
qm set $VMID \
|
qm set $VMID \
|
||||||
-efidisk0 ${DISK0_REF}${FORMAT} \
|
-efidisk0 ${DISK0_REF}${FORMAT} \
|
||||||
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
|
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
|
||||||
-ide2 ${STORAGE}:cloudinit \
|
-ide2 ${STORAGE}:cloudinit \
|
||||||
-boot order=scsi0 \
|
-boot order=scsi0 \
|
||||||
-serial0 socket >/dev/null
|
-serial0 socket >/dev/null
|
||||||
DESCRIPTION=$(
|
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://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
<img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
||||||
@@ -511,18 +511,18 @@ EOF
|
|||||||
)
|
)
|
||||||
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
||||||
if [ -n "$DISK_SIZE" ]; then
|
if [ -n "$DISK_SIZE" ]; then
|
||||||
msg_info "Resizing disk to $DISK_SIZE GB"
|
msg_info "Resizing disk to $DISK_SIZE GB"
|
||||||
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
|
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
|
||||||
else
|
else
|
||||||
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
|
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
|
||||||
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
|
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_ok "Created a Ubuntu 24.04 VM ${CL}${BL}(${HN})"
|
msg_ok "Created a Ubuntu 24.04 VM ${CL}${BL}(${HN})"
|
||||||
if [ "$START_VM" == "yes" ]; then
|
if [ "$START_VM" == "yes" ]; then
|
||||||
msg_info "Starting Ubuntu 24.04 VM"
|
msg_info "Starting Ubuntu 24.04 VM"
|
||||||
qm start $VMID
|
qm start $VMID
|
||||||
msg_ok "Started Ubuntu 24.04 VM"
|
msg_ok "Started Ubuntu 24.04 VM"
|
||||||
fi
|
fi
|
||||||
post_update_to_api "done" "none"
|
post_update_to_api "done" "none"
|
||||||
msg_ok "Completed successfully!\n"
|
msg_ok "Completed successfully!\n"
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.or
|
|||||||
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
source /dev/stdin <<<$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/api.func")
|
||||||
|
|
||||||
function header_info {
|
function header_info {
|
||||||
clear
|
clear
|
||||||
cat <<"EOF"
|
cat <<"EOF"
|
||||||
__ ____ __ ___ __ __ _______ _ ____ ___
|
__ ____ __ ___ __ __ _______ _ ____ ___
|
||||||
/ / / / /_ __ ______ / /___ __ |__ \/ // / < / __ \ | | / / |/ /
|
/ / / / /_ __ ______ / /___ __ |__ \/ // / < / __ \ | | / / |/ /
|
||||||
/ / / / __ \/ / / / __ \/ __/ / / / __/ / // /_ / / / / / | | / / /|_/ /
|
/ / / / __ \/ / / / __ \/ __/ / / / __/ / // /_ / / / / / | | / / /|_/ /
|
||||||
@@ -67,467 +67,467 @@ trap cleanup EXIT
|
|||||||
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
||||||
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
||||||
function error_handler() {
|
function error_handler() {
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
local line_number="$1"
|
local line_number="$1"
|
||||||
local command="$2"
|
local command="$2"
|
||||||
post_update_to_api "failed" "$command"
|
post_update_to_api "failed" "$command"
|
||||||
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
||||||
echo -e "\n$error_message\n"
|
echo -e "\n$error_message\n"
|
||||||
cleanup_vmid
|
cleanup_vmid
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_valid_nextid() {
|
function get_valid_nextid() {
|
||||||
local try_id
|
local try_id
|
||||||
try_id=$(pvesh get /cluster/nextid)
|
try_id=$(pvesh get /cluster/nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
break
|
break
|
||||||
done
|
done
|
||||||
echo "$try_id"
|
echo "$try_id"
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup_vmid() {
|
function cleanup_vmid() {
|
||||||
if qm status $VMID &>/dev/null; then
|
if qm status $VMID &>/dev/null; then
|
||||||
qm stop $VMID &>/dev/null
|
qm stop $VMID &>/dev/null
|
||||||
qm destroy $VMID &>/dev/null
|
qm destroy $VMID &>/dev/null
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
pushd $TEMP_DIR >/dev/null
|
pushd $TEMP_DIR >/dev/null
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "$APP" --yesno "This will create a New $APP. Proceed?" 10 58; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "$APP" --yesno "This will create a New $APP. Proceed?" 10 58; then
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
|
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function msg_info() {
|
function msg_info() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
|
echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_ok() {
|
function msg_ok() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_error() {
|
function msg_error() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_root() {
|
function check_root() {
|
||||||
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
||||||
clear
|
clear
|
||||||
msg_error "Please run this script as root."
|
msg_error "Please run this script as root."
|
||||||
echo -e "\nExiting..."
|
echo -e "\nExiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function pve_check() {
|
function pve_check() {
|
||||||
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
||||||
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
||||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function arch_check() {
|
function arch_check() {
|
||||||
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
||||||
echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
|
echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
|
||||||
echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
|
echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function ssh_check() {
|
function ssh_check() {
|
||||||
if command -v pveversion >/dev/null 2>&1; then
|
if command -v pveversion >/dev/null 2>&1; then
|
||||||
if [ -n "${SSH_CLIENT:+x}" ]; then
|
if [ -n "${SSH_CLIENT:+x}" ]; then
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
||||||
echo "you've been warned"
|
echo "you've been warned"
|
||||||
else
|
else
|
||||||
clear
|
clear
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function exit-script() {
|
function exit-script() {
|
||||||
clear
|
clear
|
||||||
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
|
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
function init_settings() {
|
function init_settings() {
|
||||||
VMID="$(get_valid_nextid)"
|
VMID="$(get_valid_nextid)"
|
||||||
HN="ubuntu"
|
HN="ubuntu"
|
||||||
DISK_SIZE="8G"
|
DISK_SIZE="8G"
|
||||||
DISK_CACHE=""
|
DISK_CACHE=""
|
||||||
DISK_EXT=".qcow2"
|
DISK_EXT=".qcow2"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
CPU_TYPE=""
|
CPU_TYPE=""
|
||||||
CORE_COUNT="2"
|
CORE_COUNT="2"
|
||||||
RAM_SIZE="2048"
|
RAM_SIZE="2048"
|
||||||
MACHINE_TYPE="i440fx"
|
MACHINE_TYPE="i440fx"
|
||||||
MACHINE=""
|
MACHINE=""
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
BRG="vmbr0"
|
BRG="vmbr0"
|
||||||
MAC="$GEN_MAC"
|
MAC="$GEN_MAC"
|
||||||
VLAN=""
|
VLAN=""
|
||||||
MTU=""
|
MTU=""
|
||||||
START_VM="yes"
|
START_VM="yes"
|
||||||
}
|
}
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
METHOD="default"
|
METHOD="default"
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}${DISK_CACHE:-None}${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}${DISK_CACHE:-None}${CL}"
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}${MACHINE_TYPE}${CL}"
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}${MACHINE_TYPE}${CL}"
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}${var_vlan:-Default}${CL}"
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}${var_vlan:-Default}${CL}"
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}${var_mtu:-Default}${CL}"
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}${var_mtu:-Default}${CL}"
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}${START_VM}${CL}"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}${START_VM}${CL}"
|
||||||
echo -e "${CREATING}${BOLD}${DGN}Creating a $APP using default settings${CL}"
|
echo -e "${CREATING}${BOLD}${DGN}Creating a $APP using default settings${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function apply_env_overrides() {
|
function apply_env_overrides() {
|
||||||
METHOD="env"
|
METHOD="env"
|
||||||
[ -n "$var_vmid" ] && VMID="$var_vmid"
|
[ -n "$var_vmid" ] && VMID="$var_vmid"
|
||||||
HN=$(echo "${var_hostname,,}" | tr -cd '[:alnum:]-')
|
HN=$(echo "${var_hostname,,}" | tr -cd '[:alnum:]-')
|
||||||
[[ -z "$HN" ]] && HN="ubuntu"
|
[[ -z "$HN" ]] && HN="ubuntu"
|
||||||
[[ ! "$HN" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ ]] && {
|
[[ ! "$HN" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ ]] && {
|
||||||
msg_error "Invalid hostname: $HN"
|
msg_error "Invalid hostname: $HN"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
case "$var_machine" in
|
case "$var_machine" in
|
||||||
q35)
|
q35)
|
||||||
MACHINE_TYPE="q35"
|
MACHINE_TYPE="q35"
|
||||||
FORMAT=""
|
FORMAT=""
|
||||||
MACHINE=" -machine q35"
|
MACHINE=" -machine q35"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
MACHINE_TYPE="i440fx"
|
MACHINE_TYPE="i440fx"
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
MACHINE=""
|
MACHINE=""
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
case "$var_cpu_type" in
|
case "$var_cpu_type" in
|
||||||
1) CPU_TYPE=" -cpu host" ;;
|
1) CPU_TYPE=" -cpu host" ;;
|
||||||
*) CPU_TYPE="" ;;
|
*) CPU_TYPE="" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
case "$var_disk_cache" in
|
case "$var_disk_cache" in
|
||||||
1) DISK_CACHE="cache=writethrough," ;;
|
1) DISK_CACHE="cache=writethrough," ;;
|
||||||
*) DISK_CACHE="" ;;
|
*) DISK_CACHE="" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
[[ "$var_cpu" =~ ^[1-9][0-9]*$ ]] && CORE_COUNT="$var_cpu" || CORE_COUNT="2"
|
[[ "$var_cpu" =~ ^[1-9][0-9]*$ ]] && CORE_COUNT="$var_cpu" || CORE_COUNT="2"
|
||||||
[[ "$var_ram" =~ ^[1-9][0-9]*$ ]] && RAM_SIZE="$var_ram" || RAM_SIZE="2048"
|
[[ "$var_ram" =~ ^[1-9][0-9]*$ ]] && RAM_SIZE="$var_ram" || RAM_SIZE="2048"
|
||||||
[[ -n "$var_disk" ]] && DISK_SIZE="$var_disk" || DISK_SIZE="8G"
|
[[ -n "$var_disk" ]] && DISK_SIZE="$var_disk" || DISK_SIZE="8G"
|
||||||
[ -n "$var_bridge" ] && BRG="$var_bridge"
|
[ -n "$var_bridge" ] && BRG="$var_bridge"
|
||||||
[ -z "$BRG" ] && BRG="vmbr0"
|
[ -z "$BRG" ] && BRG="vmbr0"
|
||||||
|
|
||||||
[ -n "$var_mac" ] && MAC="$var_mac"
|
[ -n "$var_mac" ] && MAC="$var_mac"
|
||||||
[ -z "$MAC" ] && MAC="$GEN_MAC"
|
[ -z "$MAC" ] && MAC="$GEN_MAC"
|
||||||
VLAN=${var_vlan:+",tag=$var_vlan"}
|
VLAN=${var_vlan:+",tag=$var_vlan"}
|
||||||
MTU=${var_mtu:+",mtu=$var_mtu"}
|
MTU=${var_mtu:+",mtu=$var_mtu"}
|
||||||
START_VM="$var_start_vm"
|
START_VM="$var_start_vm"
|
||||||
|
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}${MACHINE_TYPE}${CL}"
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}${MACHINE_TYPE}${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}${DISK_CACHE:-None}${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}${DISK_CACHE:-None}${CL}"
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}${CPU_TYPE:+Host}${CPU_TYPE:-KVM64}${CL}"
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}${CPU_TYPE:+Host}${CPU_TYPE:-KVM64}${CL}"
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}${var_vlan:-Default}${CL}"
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}${var_vlan:-Default}${CL}"
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}${var_mtu:-Default}${CL}"
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}${var_mtu:-Default}${CL}"
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}${START_VM}${CL}"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}${START_VM}${CL}"
|
||||||
echo -e "${CREATING}${BOLD}${DGN}Creating a $APP using environment settings${CL}"
|
echo -e "${CREATING}${BOLD}${DGN}Creating a $APP using environment settings${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function validate_env_settings() {
|
function validate_env_settings() {
|
||||||
[[ -n "$var_hostname" ]] && {
|
[[ -n "$var_hostname" ]] && {
|
||||||
HN_CLEANED=$(echo "$var_hostname" | tr -cd '[:alnum:]-')
|
HN_CLEANED=$(echo "$var_hostname" | tr -cd '[:alnum:]-')
|
||||||
if [[ ! "$HN_CLEANED" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ ]]; then
|
if [[ ! "$HN_CLEANED" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ ]]; then
|
||||||
msg_error "Invalid hostname: $var_hostname"
|
msg_error "Invalid hostname: $var_hostname"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
[[ -n "$var_vmid" && ! "$var_vmid" =~ ^[1-9][0-9]{2,}$ ]] && {
|
[[ -n "$var_vmid" && ! "$var_vmid" =~ ^[1-9][0-9]{2,}$ ]] && {
|
||||||
msg_error "Invalid VMID: must be a number >= 100"
|
msg_error "Invalid VMID: must be a number >= 100"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
[[ -n "$var_cpu" && ! "$var_cpu" =~ ^[1-9][0-9]*$ ]] && {
|
[[ -n "$var_cpu" && ! "$var_cpu" =~ ^[1-9][0-9]*$ ]] && {
|
||||||
msg_error "Invalid CPU core count: must be > 0"
|
msg_error "Invalid CPU core count: must be > 0"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
[[ -n "$var_ram" && ! "$var_ram" =~ ^[1-9][0-9]*$ ]] && {
|
[[ -n "$var_ram" && ! "$var_ram" =~ ^[1-9][0-9]*$ ]] && {
|
||||||
msg_error "Invalid RAM size: must be > 0"
|
msg_error "Invalid RAM size: must be > 0"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
[[ -n "$var_disk" && ! "$var_disk" =~ ^[1-9][0-9]*G$ ]] && {
|
[[ -n "$var_disk" && ! "$var_disk" =~ ^[1-9][0-9]*G$ ]] && {
|
||||||
msg_error "Invalid disk size: must be like 10G"
|
msg_error "Invalid disk size: must be like 10G"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
[[ -n "$var_mac" && ! "$var_mac" =~ ^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$ ]] && {
|
[[ -n "$var_mac" && ! "$var_mac" =~ ^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$ ]] && {
|
||||||
msg_error "Invalid MAC address: $var_mac"
|
msg_error "Invalid MAC address: $var_mac"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
[[ -n "$var_mtu" && ! "$var_mtu" =~ ^[1-9][0-9]{2,4}$ ]] && {
|
[[ -n "$var_mtu" && ! "$var_mtu" =~ ^[1-9][0-9]{2,4}$ ]] && {
|
||||||
msg_error "Invalid MTU value: $var_mtu"
|
msg_error "Invalid MTU value: $var_mtu"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
[[ -n "$var_vlan" && ! "$var_vlan" =~ ^[0-9]{1,4}$ ]] && {
|
[[ -n "$var_vlan" && ! "$var_vlan" =~ ^[0-9]{1,4}$ ]] && {
|
||||||
msg_error "Invalid VLAN tag: must be numeric"
|
msg_error "Invalid VLAN tag: must be numeric"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
[[ -n "$var_start_vm" && ! "$var_start_vm" =~ ^(yes|no)$ ]] && {
|
[[ -n "$var_start_vm" && ! "$var_start_vm" =~ ^(yes|no)$ ]] && {
|
||||||
msg_error "var_start_vm must be 'yes' or 'no'"
|
msg_error "var_start_vm must be 'yes' or 'no'"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function advanced_settings() {
|
function advanced_settings() {
|
||||||
METHOD="advanced"
|
METHOD="advanced"
|
||||||
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z "$VMID" ]; then
|
if [ -z "$VMID" ]; then
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
fi
|
fi
|
||||||
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
||||||
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
||||||
sleep 2
|
sleep 2
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
||||||
break
|
break
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
||||||
|
"i440fx" "Machine i440fx" ON \
|
||||||
|
"q35" "Machine q35" OFF \
|
||||||
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $MACH = q35 ]; then
|
||||||
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=""
|
||||||
|
MACHINE=" -machine q35"
|
||||||
|
else
|
||||||
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=",efitype=4m"
|
||||||
|
MACHINE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
exit-script
|
exit-script
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
|
||||||
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"i440fx" "Machine i440fx" ON \
|
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
|
||||||
"q35" "Machine q35" OFF \
|
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
|
||||||
3>&1 1>&2 2>&3); then
|
DISK_SIZE="${DISK_SIZE}G"
|
||||||
if [ $MACH = q35 ]; then
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
|
||||||
FORMAT=""
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
||||||
MACHINE=" -machine q35"
|
else
|
||||||
|
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
exit-script
|
||||||
FORMAT=",efitype=4m"
|
|
||||||
MACHINE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
|
"0" "None (Default)" ON \
|
||||||
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
|
"1" "Write Through" OFF \
|
||||||
DISK_SIZE="${DISK_SIZE}G"
|
3>&1 1>&2 2>&3); then
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
if [ $DISK_CACHE = "1" ]; then
|
||||||
elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
DISK_CACHE="cache=writethrough,"
|
||||||
|
else
|
||||||
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
||||||
|
DISK_CACHE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
|
exit-script
|
||||||
exit-script
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 ubuntu --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "None (Default)" ON \
|
if [ -z "$VM_NAME" ]; then
|
||||||
"1" "Write Through" OFF \
|
HN="ubuntu"
|
||||||
3>&1 1>&2 2>&3); then
|
else
|
||||||
if [ $DISK_CACHE = "1" ]; then
|
HN=$(echo "${VM_NAME,,}" | tr -cd '[:alnum:]-')
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
|
fi
|
||||||
DISK_CACHE="cache=writethrough,"
|
if [[ ! "$HN" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ ]]; then
|
||||||
|
msg_error "Invalid hostname: $HN. Must be 1–63 chars, alphanumeric or hyphen, and not start/end with hyphen."
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
else
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
exit-script
|
||||||
DISK_CACHE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 ubuntu --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
if [ -z "$VM_NAME" ]; then
|
"0" "KVM64 (Default)" ON \
|
||||||
HN="ubuntu"
|
"1" "Host" OFF \
|
||||||
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ "$CPU_TYPE1" = "1" ]; then
|
||||||
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
|
||||||
|
CPU_TYPE=" -cpu host"
|
||||||
|
else
|
||||||
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
||||||
|
CPU_TYPE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
HN=$(echo "${VM_NAME,,}" | tr -cd '[:alnum:]-')
|
exit-script
|
||||||
fi
|
fi
|
||||||
if [[ ! "$HN" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ ]]; then
|
|
||||||
msg_error "Invalid hostname: $HN. Must be 1–63 chars, alphanumeric or hyphen, and not start/end with hyphen."
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "KVM64 (Default)" ON \
|
CORE_COUNT=$(echo "$CORE_COUNT" | tr -cd '[:digit:]')
|
||||||
"1" "Host" OFF \
|
if [[ ! "$CORE_COUNT" =~ ^[1-9][0-9]*$ ]]; then
|
||||||
3>&1 1>&2 2>&3); then
|
msg_error "CPU core count must be a positive integer."
|
||||||
if [ "$CPU_TYPE1" = "1" ]; then
|
exit-script
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
|
fi
|
||||||
CPU_TYPE=" -cpu host"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
else
|
else
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
exit-script
|
||||||
CPU_TYPE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
CORE_COUNT=$(echo "$CORE_COUNT" | tr -cd '[:digit:]')
|
RAM_SIZE=$(echo "$RAM_SIZE" | tr -cd '[:digit:]')
|
||||||
if [[ ! "$CORE_COUNT" =~ ^[1-9][0-9]*$ ]]; then
|
if [[ ! "$RAM_SIZE" =~ ^[1-9][0-9]*$ ]]; then
|
||||||
msg_error "CPU core count must be a positive integer."
|
msg_error "RAM size must be a positive integer (in MiB)."
|
||||||
exit-script
|
exit-script
|
||||||
fi
|
fi
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
|
||||||
RAM_SIZE=$(echo "$RAM_SIZE" | tr -cd '[:digit:]')
|
|
||||||
if [[ ! "$RAM_SIZE" =~ ^[1-9][0-9]*$ ]]; then
|
|
||||||
msg_error "RAM size must be a positive integer (in MiB)."
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
|
||||||
if [ -z $BRG ]; then
|
|
||||||
BRG="vmbr0"
|
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
|
||||||
else
|
else
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
exit-script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $MAC1 ]; then
|
if [ -z $BRG ]; then
|
||||||
MAC="$GEN_MAC"
|
BRG="vmbr0"
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
MAC="$MAC1"
|
exit-script
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $VLAN1 ]; then
|
if [ -z $MAC1 ]; then
|
||||||
VLAN1="Default"
|
MAC="$GEN_MAC"
|
||||||
VLAN=""
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
else
|
||||||
|
MAC="$MAC1"
|
||||||
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
VLAN=",tag=$VLAN1"
|
exit-script
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $MTU1 ]; then
|
if [ -z $VLAN1 ]; then
|
||||||
MTU1="Default"
|
VLAN1="Default"
|
||||||
MTU=""
|
VLAN=""
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
||||||
|
else
|
||||||
|
VLAN=",tag=$VLAN1"
|
||||||
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
MTU=",mtu=$MTU1"
|
exit-script
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit-script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
if [ -z $MTU1 ]; then
|
||||||
START_VM="yes"
|
MTU1="Default"
|
||||||
else
|
MTU=""
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
START_VM="no"
|
else
|
||||||
fi
|
MTU=",mtu=$MTU1"
|
||||||
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a $APP?" --no-button Do-Over 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
||||||
echo -e "${CREATING}${BOLD}${DGN}Creating a $APP using the above advanced settings${CL}"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
else
|
START_VM="yes"
|
||||||
header_info
|
else
|
||||||
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
|
||||||
advanced_settings
|
START_VM="no"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a $APP?" --no-button Do-Over 10 58); then
|
||||||
|
echo -e "${CREATING}${BOLD}${DGN}Creating a $APP using the above advanced settings${CL}"
|
||||||
|
else
|
||||||
|
header_info
|
||||||
|
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
||||||
|
advanced_settings
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function has_env_overrides() {
|
function has_env_overrides() {
|
||||||
env | grep -qE "^var_(bridge|cpu|cpu_type|disk|disk_cache|hostname|mac|machine|mtu|ram|start_vm|vlan|vmid)="
|
env | grep -qE "^var_(bridge|cpu|cpu_type|disk|disk_cache|hostname|mac|machine|mtu|ram|start_vm|vlan|vmid)="
|
||||||
}
|
}
|
||||||
|
|
||||||
function start_script() {
|
function start_script() {
|
||||||
header_info
|
header_info
|
||||||
init_settings
|
init_settings
|
||||||
if has_env_overrides; then
|
if has_env_overrides; then
|
||||||
echo -e "${ADVANCED}${BOLD}${BL}Using Environment Variable Overrides${CL}"
|
echo -e "${ADVANCED}${BOLD}${BL}Using Environment Variable Overrides${CL}"
|
||||||
METHOD="env"
|
METHOD="env"
|
||||||
apply_env_overrides
|
apply_env_overrides
|
||||||
elif (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
elif (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
||||||
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
|
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
|
||||||
default_settings
|
default_settings
|
||||||
else
|
else
|
||||||
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
||||||
advanced_settings
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
check_root
|
check_root
|
||||||
@@ -539,29 +539,29 @@ post_to_api_vm
|
|||||||
|
|
||||||
msg_info "Validating Storage"
|
msg_info "Validating Storage"
|
||||||
while read -r line; do
|
while read -r line; do
|
||||||
TAG=$(echo $line | awk '{print $1}')
|
TAG=$(echo $line | awk '{print $1}')
|
||||||
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
||||||
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
||||||
ITEM=" Type: $TYPE Free: $FREE "
|
ITEM=" Type: $TYPE Free: $FREE "
|
||||||
OFFSET=2
|
OFFSET=2
|
||||||
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
||||||
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
||||||
fi
|
fi
|
||||||
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
||||||
done < <(pvesm status -content images | awk 'NR>1')
|
done < <(pvesm status -content images | awk 'NR>1')
|
||||||
VALID=$(pvesm status -content images | awk 'NR>1')
|
VALID=$(pvesm status -content images | awk 'NR>1')
|
||||||
if [ -z "$VALID" ]; then
|
if [ -z "$VALID" ]; then
|
||||||
msg_error "Unable to detect a valid storage location."
|
msg_error "Unable to detect a valid storage location."
|
||||||
exit
|
exit
|
||||||
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
||||||
STORAGE=${STORAGE_MENU[0]}
|
STORAGE=${STORAGE_MENU[0]}
|
||||||
else
|
else
|
||||||
while [ -z "${STORAGE:+x}" ]; do
|
while [ -z "${STORAGE:+x}" ]; do
|
||||||
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
||||||
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
||||||
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
||||||
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
||||||
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
||||||
@@ -577,42 +577,42 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
|
|||||||
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
||||||
case $STORAGE_TYPE in
|
case $STORAGE_TYPE in
|
||||||
nfs | dir | cifs)
|
nfs | dir | cifs)
|
||||||
DISK_EXT=".qcow2"
|
DISK_EXT=".qcow2"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format qcow2"
|
DISK_IMPORT="-format qcow2"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
btrfs)
|
btrfs)
|
||||||
DISK_EXT=".raw"
|
DISK_EXT=".raw"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format raw"
|
DISK_IMPORT="-format raw"
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
for i in {0,1}; do
|
for i in {0,1}; do
|
||||||
disk="DISK$i"
|
disk="DISK$i"
|
||||||
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
||||||
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
||||||
done
|
done
|
||||||
|
|
||||||
msg_info "Creating a $APP"
|
msg_info "Creating a $APP"
|
||||||
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
||||||
-name $HN -tags "community-script;ubuntu" -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
|
-name $HN -tags "community-script;ubuntu" -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
|
||||||
if [[ "$STORAGE_TYPE" != "lvmthin" ]]; then
|
if [[ "$STORAGE_TYPE" != "lvmthin" ]]; then
|
||||||
pvesm alloc $STORAGE $VMID $DISK0 4M >/dev/null
|
pvesm alloc $STORAGE $VMID $DISK0 4M >/dev/null
|
||||||
fi
|
fi
|
||||||
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
||||||
qm set $VMID \
|
qm set $VMID \
|
||||||
-efidisk0 ${DISK0_REF}${FORMAT} \
|
-efidisk0 ${DISK0_REF}${FORMAT} \
|
||||||
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
|
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
|
||||||
-ide2 ${STORAGE}:cloudinit \
|
-ide2 ${STORAGE}:cloudinit \
|
||||||
-boot order=scsi0 \
|
-boot order=scsi0 \
|
||||||
-serial0 socket \
|
-serial0 socket \
|
||||||
-smbios1 type=1 \
|
-smbios1 type=1 \
|
||||||
--ciuser "ubuntu" -cipassword "ubuntu" >/dev/null
|
--ciuser "ubuntu" -cipassword "ubuntu" >/dev/null
|
||||||
DESCRIPTION=$(
|
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://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
<img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
||||||
@@ -643,20 +643,20 @@ EOF
|
|||||||
)
|
)
|
||||||
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
||||||
if [ -n "$DISK_SIZE" ]; then
|
if [ -n "$DISK_SIZE" ]; then
|
||||||
msg_info "Resizing disk to $DISK_SIZE GB"
|
msg_info "Resizing disk to $DISK_SIZE GB"
|
||||||
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
|
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
|
||||||
msg_ok "Resized disk to ${CL}${BL}${DISK_SIZE}${CL} GB"
|
msg_ok "Resized disk to ${CL}${BL}${DISK_SIZE}${CL} GB"
|
||||||
else
|
else
|
||||||
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
|
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
|
||||||
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
|
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
|
||||||
msg_ok "Resized disk to ${CL}${BL}${DEFAULT_DISK_SIZE}${CL} GB"
|
msg_ok "Resized disk to ${CL}${BL}${DEFAULT_DISK_SIZE}${CL} GB"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_ok "Created a $APP ${CL}${BL}(${HN})"
|
msg_ok "Created a $APP ${CL}${BL}(${HN})"
|
||||||
if [ "$START_VM" == "yes" ]; then
|
if [ "$START_VM" == "yes" ]; then
|
||||||
msg_info "Starting $APP"
|
msg_info "Starting $APP"
|
||||||
qm start $VMID
|
qm start $VMID
|
||||||
msg_ok "Started $APP"
|
msg_ok "Started $APP"
|
||||||
fi
|
fi
|
||||||
post_update_to_api "done" "none"
|
post_update_to_api "done" "none"
|
||||||
msg_ok "Completed successfully!\n"
|
msg_ok "Completed successfully!\n"
|
||||||
|
|||||||
@@ -58,341 +58,341 @@ trap cleanup EXIT
|
|||||||
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
|
||||||
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
|
||||||
function error_handler() {
|
function error_handler() {
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
local line_number="$1"
|
local line_number="$1"
|
||||||
local command="$2"
|
local command="$2"
|
||||||
post_update_to_api "failed" "${command}"
|
post_update_to_api "failed" "${command}"
|
||||||
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
||||||
echo -e "\n$error_message\n"
|
echo -e "\n$error_message\n"
|
||||||
cleanup_vmid
|
cleanup_vmid
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_valid_nextid() {
|
function get_valid_nextid() {
|
||||||
local try_id
|
local try_id
|
||||||
try_id=$(pvesh get /cluster/nextid)
|
try_id=$(pvesh get /cluster/nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
||||||
try_id=$((try_id + 1))
|
try_id=$((try_id + 1))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
break
|
break
|
||||||
done
|
done
|
||||||
echo "$try_id"
|
echo "$try_id"
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup_vmid() {
|
function cleanup_vmid() {
|
||||||
if qm status $VMID &>/dev/null; then
|
if qm status $VMID &>/dev/null; then
|
||||||
qm stop $VMID &>/dev/null
|
qm stop $VMID &>/dev/null
|
||||||
qm destroy $VMID &>/dev/null
|
qm destroy $VMID &>/dev/null
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
post_update_to_api "done" "none"
|
post_update_to_api "done" "none"
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
pushd $TEMP_DIR >/dev/null
|
pushd $TEMP_DIR >/dev/null
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Umbrel OS VM" --yesno "This will create a New Umbrel OS VM. Proceed?" 10 58; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Umbrel OS VM" --yesno "This will create a New Umbrel OS VM. Proceed?" 10 58; then
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
|
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function msg_info() {
|
function msg_info() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
|
echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_ok() {
|
function msg_ok() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function msg_error() {
|
function msg_error() {
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_root() {
|
function check_root() {
|
||||||
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
||||||
clear
|
clear
|
||||||
msg_error "Please run this script as root."
|
msg_error "Please run this script as root."
|
||||||
echo -e "\nExiting..."
|
echo -e "\nExiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function pve_check() {
|
function pve_check() {
|
||||||
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
|
||||||
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
||||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function arch_check() {
|
function arch_check() {
|
||||||
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
||||||
echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
|
echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
|
||||||
echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
|
echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
|
||||||
echo -e "Exiting..."
|
echo -e "Exiting..."
|
||||||
sleep 2
|
sleep 2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function ssh_check() {
|
function ssh_check() {
|
||||||
if command -v pveversion >/dev/null 2>&1; then
|
if command -v pveversion >/dev/null 2>&1; then
|
||||||
if [ -n "${SSH_CLIENT:+x}" ]; then
|
if [ -n "${SSH_CLIENT:+x}" ]; then
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
|
||||||
echo "you've been warned"
|
echo "you've been warned"
|
||||||
else
|
else
|
||||||
clear
|
clear
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function exit_script() {
|
function exit_script() {
|
||||||
clear
|
clear
|
||||||
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
|
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
MACHINE=""
|
MACHINE=""
|
||||||
DISK_CACHE=""
|
DISK_CACHE=""
|
||||||
DISK_SIZE="32G"
|
DISK_SIZE="32G"
|
||||||
HN="umbrel-os"
|
HN="umbrel-os"
|
||||||
CPU_TYPE=""
|
CPU_TYPE=""
|
||||||
CORE_COUNT="2"
|
CORE_COUNT="2"
|
||||||
RAM_SIZE="4096"
|
RAM_SIZE="4096"
|
||||||
BRG="vmbr0"
|
BRG="vmbr0"
|
||||||
MAC="$GEN_MAC"
|
MAC="$GEN_MAC"
|
||||||
VLAN=""
|
VLAN=""
|
||||||
MTU=""
|
MTU=""
|
||||||
START_VM="yes"
|
START_VM="yes"
|
||||||
METHOD="default"
|
METHOD="default"
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
echo -e "${CREATING}${BOLD}${DGN}Creating a Umbrel OS VM using the above default settings${CL}"
|
echo -e "${CREATING}${BOLD}${DGN}Creating a Umbrel OS VM using the above default settings${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function advanced_settings() {
|
function advanced_settings() {
|
||||||
METHOD="advanced"
|
METHOD="advanced"
|
||||||
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
||||||
while true; do
|
while true; do
|
||||||
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z "$VMID" ]; then
|
if [ -z "$VMID" ]; then
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
fi
|
fi
|
||||||
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
|
||||||
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
|
||||||
sleep 2
|
sleep 2
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
|
||||||
break
|
break
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
||||||
|
"i440fx" "Machine i440fx" ON \
|
||||||
|
"q35" "Machine q35" OFF \
|
||||||
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $MACH = q35 ]; then
|
||||||
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=""
|
||||||
|
MACHINE=" -machine q35"
|
||||||
|
else
|
||||||
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
||||||
|
FORMAT=",efitype=4m"
|
||||||
|
MACHINE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
exit-script
|
exit_script
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
|
||||||
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"i440fx" "Machine i440fx" ON \
|
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
|
||||||
"q35" "Machine q35" OFF \
|
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
|
||||||
3>&1 1>&2 2>&3); then
|
DISK_SIZE="${DISK_SIZE}G"
|
||||||
if [ $MACH = q35 ]; then
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
|
||||||
FORMAT=""
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
||||||
MACHINE=" -machine q35"
|
else
|
||||||
|
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
|
||||||
|
exit_script
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
exit_script
|
||||||
FORMAT=",efitype=4m"
|
|
||||||
MACHINE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
|
"0" "None (Default)" ON \
|
||||||
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
|
"1" "Write Through" OFF \
|
||||||
DISK_SIZE="${DISK_SIZE}G"
|
3>&1 1>&2 2>&3); then
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
if [ $DISK_CACHE = "1" ]; then
|
||||||
elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
DISK_CACHE="cache=writethrough,"
|
||||||
|
else
|
||||||
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
||||||
|
DISK_CACHE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
|
exit_script
|
||||||
exit_script
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 umbrel-os --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "None (Default)" ON \
|
if [ -z $VM_NAME ]; then
|
||||||
"1" "Write Through" OFF \
|
HN="umbrel-os"
|
||||||
3>&1 1>&2 2>&3); then
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
if [ $DISK_CACHE = "1" ]; then
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
|
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
||||||
DISK_CACHE="cache=writethrough,"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
|
exit_script
|
||||||
DISK_CACHE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 umbrel-os --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
if [ -z $VM_NAME ]; then
|
"0" "KVM64 (Default)" ON \
|
||||||
HN="umbrel-os"
|
"1" "Host" OFF \
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
3>&1 1>&2 2>&3); then
|
||||||
|
if [ $CPU_TYPE1 = "1" ]; then
|
||||||
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
|
||||||
|
CPU_TYPE=" -cpu host"
|
||||||
|
else
|
||||||
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
||||||
|
CPU_TYPE=""
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
exit_script
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
"0" "KVM64 (Default)" ON \
|
if [ -z $CORE_COUNT ]; then
|
||||||
"1" "Host" OFF \
|
CORE_COUNT="2"
|
||||||
3>&1 1>&2 2>&3); then
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
if [ $CPU_TYPE1 = "1" ]; then
|
else
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
CPU_TYPE=" -cpu host"
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
|
exit_script
|
||||||
CPU_TYPE=""
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $CORE_COUNT ]; then
|
if [ -z $RAM_SIZE ]; then
|
||||||
CORE_COUNT="2"
|
RAM_SIZE="2048"
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
exit_script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $RAM_SIZE ]; then
|
if [ -z $BRG ]; then
|
||||||
RAM_SIZE="2048"
|
BRG="vmbr0"
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
exit_script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $BRG ]; then
|
if [ -z $MAC1 ]; then
|
||||||
BRG="vmbr0"
|
MAC="$GEN_MAC"
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
|
||||||
|
else
|
||||||
|
MAC="$MAC1"
|
||||||
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
exit_script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $MAC1 ]; then
|
if [ -z $VLAN1 ]; then
|
||||||
MAC="$GEN_MAC"
|
VLAN1="Default"
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
|
VLAN=""
|
||||||
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
||||||
|
else
|
||||||
|
VLAN=",tag=$VLAN1"
|
||||||
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
MAC="$MAC1"
|
exit_script
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $VLAN1 ]; then
|
if [ -z $MTU1 ]; then
|
||||||
VLAN1="Default"
|
MTU1="Default"
|
||||||
VLAN=""
|
MTU=""
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
else
|
||||||
|
MTU=",mtu=$MTU1"
|
||||||
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
VLAN=",tag=$VLAN1"
|
exit_script
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
||||||
if [ -z $MTU1 ]; then
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
MTU1="Default"
|
START_VM="yes"
|
||||||
MTU=""
|
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
|
||||||
else
|
else
|
||||||
MTU=",mtu=$MTU1"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
START_VM="no"
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Umbrel OS VM?" --no-button Do-Over 10 58); then
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
echo -e "${CREATING}${BOLD}${DGN}Creating a Umbrel OS VM using the above advanced settings${CL}"
|
||||||
START_VM="yes"
|
else
|
||||||
else
|
header_info
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
|
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
||||||
START_VM="no"
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Umbrel OS VM?" --no-button Do-Over 10 58); then
|
|
||||||
echo -e "${CREATING}${BOLD}${DGN}Creating a Umbrel OS VM using the above advanced settings${CL}"
|
|
||||||
else
|
|
||||||
header_info
|
|
||||||
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
|
||||||
advanced_settings
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function start_script() {
|
function start_script() {
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
|
||||||
header_info
|
header_info
|
||||||
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
|
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
|
||||||
default_settings
|
default_settings
|
||||||
else
|
else
|
||||||
header_info
|
header_info
|
||||||
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
|
||||||
advanced_settings
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
check_root
|
check_root
|
||||||
arch_check
|
arch_check
|
||||||
@@ -403,29 +403,29 @@ post_to_api_vm
|
|||||||
|
|
||||||
msg_info "Validating Storage"
|
msg_info "Validating Storage"
|
||||||
while read -r line; do
|
while read -r line; do
|
||||||
TAG=$(echo $line | awk '{print $1}')
|
TAG=$(echo $line | awk '{print $1}')
|
||||||
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
||||||
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
||||||
ITEM=" Type: $TYPE Free: $FREE "
|
ITEM=" Type: $TYPE Free: $FREE "
|
||||||
OFFSET=2
|
OFFSET=2
|
||||||
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
||||||
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
||||||
fi
|
fi
|
||||||
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
|
||||||
done < <(pvesm status -content images | awk 'NR>1')
|
done < <(pvesm status -content images | awk 'NR>1')
|
||||||
VALID=$(pvesm status -content images | awk 'NR>1')
|
VALID=$(pvesm status -content images | awk 'NR>1')
|
||||||
if [ -z "$VALID" ]; then
|
if [ -z "$VALID" ]; then
|
||||||
msg_error "Unable to detect a valid storage location."
|
msg_error "Unable to detect a valid storage location."
|
||||||
exit
|
exit
|
||||||
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
||||||
STORAGE=${STORAGE_MENU[0]}
|
STORAGE=${STORAGE_MENU[0]}
|
||||||
else
|
else
|
||||||
while [ -z "${STORAGE:+x}" ]; do
|
while [ -z "${STORAGE:+x}" ]; do
|
||||||
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
||||||
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
|
||||||
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
||||||
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
|
||||||
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
|
||||||
@@ -438,7 +438,7 @@ curl -f#SL -o "$FILE" "$URL"
|
|||||||
msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
|
msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
|
||||||
|
|
||||||
if ! command -v pv &>/dev/null; then
|
if ! command -v pv &>/dev/null; then
|
||||||
apt-get update &>/dev/null && apt-get install -y pv &>/dev/null
|
apt-get update &>/dev/null && apt-get install -y pv &>/dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_info "Decompressing $FILE with progress${CL}\n"
|
msg_info "Decompressing $FILE with progress${CL}\n"
|
||||||
@@ -450,39 +450,39 @@ msg_ok "Decompressed to ${CL}${BL}${FILE%.xz}${CL}"
|
|||||||
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
|
||||||
case $STORAGE_TYPE in
|
case $STORAGE_TYPE in
|
||||||
nfs | dir)
|
nfs | dir)
|
||||||
DISK_EXT=".raw"
|
DISK_EXT=".raw"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format raw"
|
DISK_IMPORT="-format raw"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
btrfs)
|
btrfs)
|
||||||
DISK_EXT=".raw"
|
DISK_EXT=".raw"
|
||||||
DISK_REF="$VMID/"
|
DISK_REF="$VMID/"
|
||||||
DISK_IMPORT="-format raw"
|
DISK_IMPORT="-format raw"
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
THIN=""
|
THIN=""
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
for i in {0,1,2}; do
|
for i in {0,1,2}; do
|
||||||
disk="DISK$i"
|
disk="DISK$i"
|
||||||
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
||||||
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
||||||
done
|
done
|
||||||
|
|
||||||
msg_info "Creating a Umbrel OS VM"
|
msg_info "Creating a Umbrel OS VM"
|
||||||
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
|
||||||
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci >/dev/null
|
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci >/dev/null
|
||||||
pvesm alloc $STORAGE $VMID $DISK0 4M >/dev/null
|
pvesm alloc $STORAGE $VMID $DISK0 4M >/dev/null
|
||||||
qm importdisk $VMID ${FILE_IMG} $STORAGE ${DISK_IMPORT:-} >/dev/null
|
qm importdisk $VMID ${FILE_IMG} $STORAGE ${DISK_IMPORT:-} >/dev/null
|
||||||
qm set $VMID \
|
qm set $VMID \
|
||||||
-efidisk0 ${DISK0_REF}${FORMAT} \
|
-efidisk0 ${DISK0_REF}${FORMAT} \
|
||||||
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
|
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
|
||||||
-boot order=scsi0 \
|
-boot order=scsi0 \
|
||||||
-serial0 socket >/dev/null
|
-serial0 socket >/dev/null
|
||||||
qm set $VMID --agent enabled=1 >/dev/null
|
qm set $VMID --agent enabled=1 >/dev/null
|
||||||
|
|
||||||
DESCRIPTION=$(
|
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://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
<img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
||||||
@@ -514,18 +514,18 @@ EOF
|
|||||||
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
|
||||||
|
|
||||||
if [ -n "$DISK_SIZE" ]; then
|
if [ -n "$DISK_SIZE" ]; then
|
||||||
msg_info "Resizing disk to $DISK_SIZE GB"
|
msg_info "Resizing disk to $DISK_SIZE GB"
|
||||||
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
|
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
|
||||||
else
|
else
|
||||||
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
|
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
|
||||||
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
|
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_ok "Created a Umbrel OS VM ${CL}${BL}(${HN})"
|
msg_ok "Created a Umbrel OS VM ${CL}${BL}(${HN})"
|
||||||
if [ "$START_VM" == "yes" ]; then
|
if [ "$START_VM" == "yes" ]; then
|
||||||
msg_info "Starting Umbrel OS VM"
|
msg_info "Starting Umbrel OS VM"
|
||||||
qm start $VMID
|
qm start $VMID
|
||||||
msg_ok "Started Umbrel OS VM"
|
msg_ok "Started Umbrel OS VM"
|
||||||
fi
|
fi
|
||||||
post_update_to_api "done" "none"
|
post_update_to_api "done" "none"
|
||||||
msg_ok "Completed successfully!\n"
|
msg_ok "Completed successfully!\n"
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ function set_ssh_keys() {
|
|||||||
if [ -n "$PASTED_KEY" ]; then
|
if [ -n "$PASTED_KEY" ]; then
|
||||||
if [[ "$PASTED_KEY" == ssh-* || "$PASTED_KEY" == ecdsa-* ]]; then
|
if [[ "$PASTED_KEY" == ssh-* || "$PASTED_KEY" == ecdsa-* ]]; then
|
||||||
[ -z "$SSH_KEYS_FILE" ] && SSH_KEYS_FILE=$(mktemp)
|
[ -z "$SSH_KEYS_FILE" ] && SSH_KEYS_FILE=$(mktemp)
|
||||||
echo "$PASTED_KEY" >>"$SSH_KEYS_FILE"
|
echo "$PASTED_KEY" >> "$SSH_KEYS_FILE"
|
||||||
SSH_KEY_COUNT=$((SSH_KEY_COUNT + 1))
|
SSH_KEY_COUNT=$((SSH_KEY_COUNT + 1))
|
||||||
else
|
else
|
||||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID KEY" --msgbox "Key must start with ssh-rsa, ssh-ed25519, ecdsa-, etc." 8 58
|
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID KEY" --msgbox "Key must start with ssh-rsa, ssh-ed25519, ecdsa-, etc." 8 58
|
||||||
@@ -713,7 +713,7 @@ msg_info "Customizing disk image (installing packages, staging installer)"
|
|||||||
|
|
||||||
# Create the first-boot installer script
|
# Create the first-boot installer script
|
||||||
FIRSTBOOT_SCRIPT=$(mktemp)
|
FIRSTBOOT_SCRIPT=$(mktemp)
|
||||||
cat >"$FIRSTBOOT_SCRIPT" <<'FBEOF'
|
cat > "$FIRSTBOOT_SCRIPT" <<'FBEOF'
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
LOG="/var/log/unifi-os-install.log"
|
LOG="/var/log/unifi-os-install.log"
|
||||||
@@ -792,7 +792,7 @@ FBEOF
|
|||||||
|
|
||||||
# Create the systemd service unit file
|
# Create the systemd service unit file
|
||||||
FIRSTBOOT_SVC=$(mktemp)
|
FIRSTBOOT_SVC=$(mktemp)
|
||||||
cat >"$FIRSTBOOT_SVC" <<'SVCEOF'
|
cat > "$FIRSTBOOT_SVC" <<'SVCEOF'
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=UniFi OS Server First Boot Installer
|
Description=UniFi OS Server First Boot Installer
|
||||||
After=network-online.target
|
After=network-online.target
|
||||||
|
|||||||
Reference in New Issue
Block a user