mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-02-05 12:53:27 +01:00
Compare commits
1 Commits
main
...
feat/sqlse
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61cf475dd2 |
31
CHANGELOG.md
31
CHANGELOG.md
@@ -398,30 +398,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## 2026-02-05
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- New: SQL-Server 2025 | Refactor SQL-Server 2022 [@MickLesk](https://github.com/MickLesk) ([#11546](https://github.com/community-scripts/ProxmoxVE/pull/11546))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- Refactor: Docker-VM (Multi-OS / Cloud-Init / Stabilization) [@MickLesk](https://github.com/MickLesk) ([#9047](https://github.com/community-scripts/ProxmoxVE/pull/9047))
|
|
||||||
|
|
||||||
### 💾 Core
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- cloud-init: add interactive SSH key discovery and selection [@MickLesk](https://github.com/MickLesk) ([#11547](https://github.com/community-scripts/ProxmoxVE/pull/11547))
|
|
||||||
|
|
||||||
### 🌐 Website
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- fix(frontend): theme respective syntax highlighting [@ls-root](https://github.com/ls-root) ([#11565](https://github.com/community-scripts/ProxmoxVE/pull/11565))
|
|
||||||
|
|
||||||
## 2026-02-04
|
## 2026-02-04
|
||||||
|
|
||||||
### 🆕 New Scripts
|
### 🆕 New Scripts
|
||||||
@@ -431,11 +407,8 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
|||||||
|
|
||||||
### 🚀 Updated Scripts
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
- Add log directory and permissions for koillection [@shineangelic](https://github.com/shineangelic) ([#11553](https://github.com/community-scripts/ProxmoxVE/pull/11553))
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
- [FIX] Scanopy: ensure Scanopy Daemon update [@vhsdream](https://github.com/vhsdream) ([#11541](https://github.com/community-scripts/ProxmoxVE/pull/11541))
|
|
||||||
- Immich: pin version to 2.5.3 [@vhsdream](https://github.com/vhsdream) ([#11515](https://github.com/community-scripts/ProxmoxVE/pull/11515))
|
- Immich: pin version to 2.5.3 [@vhsdream](https://github.com/vhsdream) ([#11515](https://github.com/community-scripts/ProxmoxVE/pull/11515))
|
||||||
|
|
||||||
### 💾 Core
|
### 💾 Core
|
||||||
@@ -456,10 +429,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
|||||||
|
|
||||||
- fix(frontend): implement weighted search scoring for command menu [@ls-root](https://github.com/ls-root) ([#11534](https://github.com/community-scripts/ProxmoxVE/pull/11534))
|
- fix(frontend): implement weighted search scoring for command menu [@ls-root](https://github.com/ls-root) ([#11534](https://github.com/community-scripts/ProxmoxVE/pull/11534))
|
||||||
|
|
||||||
### ❔ Uncategorized
|
|
||||||
|
|
||||||
- [FIX] Immich Public Proxy docs link [@vhsdream](https://github.com/vhsdream) ([#11543](https://github.com/community-scripts/ProxmoxVE/pull/11543))
|
|
||||||
|
|
||||||
## 2026-02-03
|
## 2026-02-03
|
||||||
|
|
||||||
### 🆕 New Scripts
|
### 🆕 New Scripts
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
_____ ____ __ _____ ___ ____ ___ ______
|
|
||||||
/ ___// __ \ / / / ___/___ ______ _____ _____ |__ \ / __ \__ \ / ____/
|
|
||||||
\__ \/ / / / / / \__ \/ _ \/ ___/ | / / _ \/ ___/ __/ // / / /_/ //___ \
|
|
||||||
___/ / /_/ / / /___ ___/ / __/ / | |/ / __/ / / __// /_/ / __/____/ /
|
|
||||||
/____/\___\_\/_____/ /____/\___/_/ |___/\___/_/ /____/\____/____/_____/
|
|
||||||
|
|
||||||
@@ -59,8 +59,6 @@ function update_script() {
|
|||||||
$STD yarn install
|
$STD yarn install
|
||||||
$STD yarn build
|
$STD yarn build
|
||||||
mkdir -p /opt/koillection/public/uploads
|
mkdir -p /opt/koillection/public/uploads
|
||||||
mkdir -p /opt/koillection/var/log
|
|
||||||
chown -R www-data:www-data /opt/koillection/var/log
|
|
||||||
chown -R www-data:www-data /opt/koillection/public/uploads
|
chown -R www-data:www-data /opt/koillection/public/uploads
|
||||||
rm -r /opt/koillection-backup
|
rm -r /opt/koillection-backup
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ function update_script() {
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if check_for_gh_release "Scanopy" "scanopy/scanopy"; then
|
if check_for_gh_release "scanopy" "scanopy/scanopy"; then
|
||||||
msg_info "Stopping services"
|
msg_info "Stopping services"
|
||||||
systemctl stop scanopy-server
|
systemctl stop scanopy-server
|
||||||
[[ -f /etc/systemd/system/scanopy-daemon.service ]] && systemctl stop scanopy-daemon
|
[[ -f /etc/systemd/system/scanopy-daemon.service ]] && systemctl stop scanopy-daemon
|
||||||
@@ -40,7 +40,7 @@ function update_script() {
|
|||||||
[[ -f /opt/scanopy/oidc.toml ]] && cp /opt/scanopy/oidc.toml /opt/scanopy.oidc.toml
|
[[ -f /opt/scanopy/oidc.toml ]] && cp /opt/scanopy/oidc.toml /opt/scanopy.oidc.toml
|
||||||
msg_ok "Backed up configurations"
|
msg_ok "Backed up configurations"
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Scanopy" "scanopy/scanopy" "tarball" "latest" "/opt/scanopy"
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "scanopy" "scanopy/scanopy" "tarball" "latest" "/opt/scanopy"
|
||||||
|
|
||||||
ensure_dependencies pkg-config libssl-dev
|
ensure_dependencies pkg-config libssl-dev
|
||||||
TOOLCHAIN="$(grep "channel" /opt/scanopy/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
|
TOOLCHAIN="$(grep "channel" /opt/scanopy/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
|
||||||
@@ -61,22 +61,19 @@ function update_script() {
|
|||||||
$STD npm run build
|
$STD npm run build
|
||||||
msg_ok "Created frontend UI"
|
msg_ok "Created frontend UI"
|
||||||
|
|
||||||
msg_info "Building Scanopy Server (patience)"
|
msg_info "Building scanopy-server (patience)"
|
||||||
cd /opt/scanopy/backend
|
cd /opt/scanopy/backend
|
||||||
$STD cargo build --release --bin server
|
$STD cargo build --release --bin server
|
||||||
mv ./target/release/server /usr/bin/scanopy-server
|
mv ./target/release/server /usr/bin/scanopy-server
|
||||||
msg_ok "Built Scanopy Server"
|
msg_ok "Built scanopy-server"
|
||||||
|
|
||||||
if [[ -f /etc/systemd/system/scanopy-daemon.service ]]; then
|
[[ -f /etc/systemd/system/scanopy-daemon.service ]] &&
|
||||||
fetch_and_deploy_gh_release "Scanopy Daemon" "scanopy/scanopy" "singlefile" "latest" "/usr/local/bin" "scanopy-daemon-linux-amd64"
|
fetch_and_deploy_gh_release "scanopy" "scanopy/scanopy" "singlefile" "latest" "/usr/local/bin" "scanopy-daemon-linux-amd64" &&
|
||||||
mv "/usr/local/bin/Scanopy Daemon" /usr/local/bin/scanopy-daemon
|
rm -f /usr/bin/scanopy-daemon ~/configure_daemon.sh &&
|
||||||
rm -f /usr/bin/scanopy-daemon ~/configure_daemon.sh
|
|
||||||
sed -i -e 's|usr/bin|usr/local/bin|' \
|
sed -i -e 's|usr/bin|usr/local/bin|' \
|
||||||
-e 's/push/daemon_poll/' \
|
-e 's/push/daemon_poll/' \
|
||||||
-e 's/pull/server_poll/' /etc/systemd/system/scanopy-daemon.service
|
-e 's/pull/server_poll/' /etc/systemd/system/scanopy-daemon.service &&
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
msg_ok "Updated Scanopy Daemon"
|
|
||||||
fi
|
|
||||||
|
|
||||||
msg_info "Starting services"
|
msg_info "Starting services"
|
||||||
systemctl start scanopy-server
|
systemctl start scanopy-server
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"generated": "2026-02-05T06:22:20Z",
|
"generated": "2026-02-04T18:17:33Z",
|
||||||
"versions": [
|
"versions": [
|
||||||
{
|
{
|
||||||
"slug": "2fauth",
|
"slug": "2fauth",
|
||||||
@@ -221,9 +221,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "cronicle",
|
"slug": "cronicle",
|
||||||
"repo": "jhuckaby/Cronicle",
|
"repo": "jhuckaby/Cronicle",
|
||||||
"version": "v0.9.103",
|
"version": "v0.9.102",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-05T03:09:04Z"
|
"date": "2025-12-19T03:45:13Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "cryptpad",
|
"slug": "cryptpad",
|
||||||
@@ -445,9 +445,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "headscale",
|
"slug": "headscale",
|
||||||
"repo": "juanfont/headscale",
|
"repo": "juanfont/headscale",
|
||||||
"version": "v0.28.0",
|
"version": "v0.27.1",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-04T20:40:23Z"
|
"date": "2025-11-11T19:32:29Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "healthchecks",
|
"slug": "healthchecks",
|
||||||
@@ -494,9 +494,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "homepage",
|
"slug": "homepage",
|
||||||
"repo": "gethomepage/homepage",
|
"repo": "gethomepage/homepage",
|
||||||
"version": "v1.10.0",
|
"version": "v1.9.0",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-05T06:17:32Z"
|
"date": "2026-01-19T05:46:09Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "homer",
|
"slug": "homer",
|
||||||
@@ -515,9 +515,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "huntarr",
|
"slug": "huntarr",
|
||||||
"repo": "plexguide/Huntarr.io",
|
"repo": "plexguide/Huntarr.io",
|
||||||
"version": "9.2.0",
|
"version": "9.1.12",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-05T04:18:08Z"
|
"date": "2026-02-04T14:28:36Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "inspircd",
|
"slug": "inspircd",
|
||||||
@@ -536,16 +536,16 @@
|
|||||||
{
|
{
|
||||||
"slug": "invoiceninja",
|
"slug": "invoiceninja",
|
||||||
"repo": "invoiceninja/invoiceninja",
|
"repo": "invoiceninja/invoiceninja",
|
||||||
"version": "v5.12.55",
|
"version": "v5.12.53",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-05T01:06:15Z"
|
"date": "2026-02-04T00:52:01Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "jackett",
|
"slug": "jackett",
|
||||||
"repo": "Jackett/Jackett",
|
"repo": "Jackett/Jackett",
|
||||||
"version": "v0.24.1032",
|
"version": "v0.24.1027",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-05T05:55:27Z"
|
"date": "2026-02-04T05:56:22Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "joplin-server",
|
"slug": "joplin-server",
|
||||||
@@ -746,9 +746,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "mealie",
|
"slug": "mealie",
|
||||||
"repo": "mealie-recipes/mealie",
|
"repo": "mealie-recipes/mealie",
|
||||||
"version": "v3.10.2",
|
"version": "v3.10.1",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-04T23:32:32Z"
|
"date": "2026-02-03T01:04:38Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "mediamanager",
|
"slug": "mediamanager",
|
||||||
@@ -781,9 +781,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "metube",
|
"slug": "metube",
|
||||||
"repo": "alexta69/metube",
|
"repo": "alexta69/metube",
|
||||||
"version": "2026.02.04",
|
"version": "2026.02.03",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-04T20:01:18Z"
|
"date": "2026-02-03T21:49:49Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "miniflux",
|
"slug": "miniflux",
|
||||||
@@ -1096,9 +1096,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "pulse",
|
"slug": "pulse",
|
||||||
"repo": "rcourtman/Pulse",
|
"repo": "rcourtman/Pulse",
|
||||||
"version": "v5.1.2",
|
"version": "v5.1.0",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-05T00:18:57Z"
|
"date": "2026-02-04T17:43:59Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "pve-scripts-local",
|
"slug": "pve-scripts-local",
|
||||||
@@ -1271,9 +1271,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "speedtest-tracker",
|
"slug": "speedtest-tracker",
|
||||||
"repo": "alexjustesen/speedtest-tracker",
|
"repo": "alexjustesen/speedtest-tracker",
|
||||||
"version": "v1.13.8",
|
"version": "v1.13.7",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-04T19:24:23Z"
|
"date": "2026-02-04T16:47:42Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "spoolman",
|
"slug": "spoolman",
|
||||||
@@ -1292,9 +1292,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "stirling-pdf",
|
"slug": "stirling-pdf",
|
||||||
"repo": "Stirling-Tools/Stirling-PDF",
|
"repo": "Stirling-Tools/Stirling-PDF",
|
||||||
"version": "v2.4.4",
|
"version": "v2.4.3",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-05T00:15:53Z"
|
"date": "2026-01-31T22:19:14Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "streamlink-webui",
|
"slug": "streamlink-webui",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"updateable": true,
|
"updateable": true,
|
||||||
"privileged": false,
|
"privileged": false,
|
||||||
"interface_port": 3000,
|
"interface_port": 3000,
|
||||||
"documentation": "https://github.com/alangrainger/immich-public-proxy/tree/main/docs",
|
"documentation": "https://github.com/alangrainger/immich-public-proxy/docs",
|
||||||
"website": "https://github.com/alangrainger/immich-public-proxy",
|
"website": "https://github.com/alangrainger/immich-public-proxy",
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/immich-public-proxy.webp",
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/immich-public-proxy.webp",
|
||||||
"config_path": "/opt/immich-proxy/app/.env",
|
"config_path": "/opt/immich-proxy/app/.env",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"categories": [
|
"categories": [
|
||||||
8
|
8
|
||||||
],
|
],
|
||||||
"date_created": "2026-02-05",
|
"date_created": "2026-02-04",
|
||||||
"type": "ct",
|
"type": "ct",
|
||||||
"updateable": true,
|
"updateable": true,
|
||||||
"privileged": true,
|
"privileged": true,
|
||||||
|
|||||||
@@ -29,10 +29,9 @@ import { ScriptSchema } from "./_schemas/schemas";
|
|||||||
import Categories from "./_components/categories";
|
import Categories from "./_components/categories";
|
||||||
import Note from "./_components/note";
|
import Note from "./_components/note";
|
||||||
|
|
||||||
import { githubGist, nord } from "react-syntax-highlighter/dist/esm/styles/hljs";
|
import { nord } from "react-syntax-highlighter/dist/esm/styles/hljs";
|
||||||
import SyntaxHighlighter from "react-syntax-highlighter";
|
import SyntaxHighlighter from "react-syntax-highlighter";
|
||||||
import { ScriptItem } from "../scripts/_components/script-item";
|
import { ScriptItem } from "../scripts/_components/script-item";
|
||||||
import { useTheme } from "next-themes";
|
|
||||||
|
|
||||||
const initialScript: Script = {
|
const initialScript: Script = {
|
||||||
name: "",
|
name: "",
|
||||||
@@ -59,7 +58,6 @@ const initialScript: Script = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function JSONGenerator() {
|
export default function JSONGenerator() {
|
||||||
const { theme } = useTheme();
|
|
||||||
const [script, setScript] = useState<Script>(initialScript);
|
const [script, setScript] = useState<Script>(initialScript);
|
||||||
const [isCopied, setIsCopied] = useState(false);
|
const [isCopied, setIsCopied] = useState(false);
|
||||||
const [isValid, setIsValid] = useState(false);
|
const [isValid, setIsValid] = useState(false);
|
||||||
@@ -359,7 +357,7 @@ export default function JSONGenerator() {
|
|||||||
|
|
||||||
<SyntaxHighlighter
|
<SyntaxHighlighter
|
||||||
language="json"
|
language="json"
|
||||||
style={theme === "light" ? githubGist : nord}
|
style={nord}
|
||||||
className="mt-4 p-4 bg-secondary rounded shadow overflow-x-scroll"
|
className="mt-4 p-4 bg-secondary rounded shadow overflow-x-scroll"
|
||||||
>
|
>
|
||||||
{JSON.stringify(script, null, 2)}
|
{JSON.stringify(script, null, 2)}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ msg_ok "Installed Dependencies"
|
|||||||
PG_VERSION=17 setup_postgresql
|
PG_VERSION=17 setup_postgresql
|
||||||
NODE_VERSION="24" setup_nodejs
|
NODE_VERSION="24" setup_nodejs
|
||||||
PG_DB_NAME="scanopy_db" PG_DB_USER="scanopy" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db
|
PG_DB_NAME="scanopy_db" PG_DB_USER="scanopy" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db
|
||||||
fetch_and_deploy_gh_release "Scanopy" "scanopy/scanopy" "tarball" "latest" "/opt/scanopy"
|
fetch_and_deploy_gh_release "scanopy" "scanopy/scanopy" "tarball" "latest" "/opt/scanopy"
|
||||||
TOOLCHAIN="$(grep "channel" /opt/scanopy/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
|
TOOLCHAIN="$(grep "channel" /opt/scanopy/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
|
||||||
RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
|
RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
|
||||||
|
|
||||||
@@ -35,11 +35,11 @@ $STD npm ci --no-fund --no-audit
|
|||||||
$STD npm run build
|
$STD npm run build
|
||||||
msg_ok "Created frontend UI"
|
msg_ok "Created frontend UI"
|
||||||
|
|
||||||
msg_info "Building Scanopy Server (patience)"
|
msg_info "Building scanopy-server (patience)"
|
||||||
cd /opt/scanopy/backend
|
cd /opt/scanopy/backend
|
||||||
$STD cargo build --release --bin server
|
$STD cargo build --release --bin server
|
||||||
mv ./target/release/server /usr/bin/scanopy-server
|
mv ./target/release/server /usr/bin/scanopy-server
|
||||||
msg_ok "Built Scanopy Server"
|
msg_ok "Built scanopy-server"
|
||||||
|
|
||||||
msg_info "Configuring server for first-run"
|
msg_info "Configuring server for first-run"
|
||||||
cat <<EOF >/opt/scanopy/.env
|
cat <<EOF >/opt/scanopy/.env
|
||||||
|
|||||||
@@ -28,210 +28,13 @@
|
|||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# These can be overridden before sourcing this library
|
# These can be overridden before sourcing this library
|
||||||
|
|
||||||
# Disable 'unbound variable' errors for this library (restored at end)
|
|
||||||
_OLD_SET_STATE=$(set +o | grep -E 'set -(e|u|o)')
|
|
||||||
set +u
|
|
||||||
|
|
||||||
CLOUDINIT_DEFAULT_USER="${CLOUDINIT_DEFAULT_USER:-root}"
|
CLOUDINIT_DEFAULT_USER="${CLOUDINIT_DEFAULT_USER:-root}"
|
||||||
CLOUDINIT_DNS_SERVERS="${CLOUDINIT_DNS_SERVERS:-1.1.1.1 8.8.8.8}"
|
CLOUDINIT_DNS_SERVERS="${CLOUDINIT_DNS_SERVERS:-1.1.1.1 8.8.8.8}"
|
||||||
CLOUDINIT_SEARCH_DOMAIN="${CLOUDINIT_SEARCH_DOMAIN:-local}"
|
CLOUDINIT_SEARCH_DOMAIN="${CLOUDINIT_SEARCH_DOMAIN:-local}"
|
||||||
CLOUDINIT_SSH_KEYS="${CLOUDINIT_SSH_KEYS:-}" # Empty by default - user must explicitly provide keys
|
CLOUDINIT_SSH_KEYS="${CLOUDINIT_SSH_KEYS:-/root/.ssh/authorized_keys}"
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# SECTION 2: SSH KEY DISCOVERY AND SELECTION
|
# SECTION 2: HELPER FUNCTIONS
|
||||||
# ==============================================================================
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# _ci_ssh_extract_keys_from_file - Extracts valid SSH public keys from a file
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
function _ci_ssh_extract_keys_from_file() {
|
|
||||||
local file="$1"
|
|
||||||
[[ -f "$file" && -r "$file" ]] || return 0
|
|
||||||
grep -E '^(ssh-(rsa|ed25519|dss|ecdsa)|ecdsa-sha2-)' "$file" 2>/dev/null || true
|
|
||||||
}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# _ci_ssh_discover_files - Scans standard paths for SSH keys
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
function _ci_ssh_discover_files() {
|
|
||||||
local -a cand=()
|
|
||||||
shopt -s nullglob
|
|
||||||
cand+=(/root/.ssh/authorized_keys /root/.ssh/authorized_keys2)
|
|
||||||
cand+=(/root/.ssh/*.pub)
|
|
||||||
cand+=(/etc/ssh/authorized_keys /etc/ssh/authorized_keys.d/*)
|
|
||||||
shopt -u nullglob
|
|
||||||
printf '%s\0' "${cand[@]}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# _ci_ssh_build_choices - Builds whiptail checklist from SSH key files
|
|
||||||
#
|
|
||||||
# Sets: CI_SSH_CHOICES (array), CI_SSH_COUNT (int), CI_SSH_MAPFILE (path)
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
function _ci_ssh_build_choices() {
|
|
||||||
local -a files=("$@")
|
|
||||||
CI_SSH_CHOICES=()
|
|
||||||
CI_SSH_COUNT=0
|
|
||||||
CI_SSH_MAPFILE="$(mktemp)"
|
|
||||||
local id key typ fp cmt base
|
|
||||||
|
|
||||||
for f in "${files[@]}"; do
|
|
||||||
[[ -f "$f" && -r "$f" ]] || continue
|
|
||||||
base="$(basename -- "$f")"
|
|
||||||
# Skip known_hosts and private keys
|
|
||||||
case "$base" in
|
|
||||||
known_hosts | known_hosts.* | config) continue ;;
|
|
||||||
id_*) [[ "$f" != *.pub ]] && continue ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
while IFS= read -r key; do
|
|
||||||
[[ -n "$key" ]] || continue
|
|
||||||
|
|
||||||
typ=""
|
|
||||||
fp=""
|
|
||||||
cmt=""
|
|
||||||
read -r _typ _b64 _cmt <<<"$key"
|
|
||||||
typ="${_typ:-key}"
|
|
||||||
cmt="${_cmt:-}"
|
|
||||||
|
|
||||||
# Get fingerprint via ssh-keygen if available
|
|
||||||
if command -v ssh-keygen >/dev/null 2>&1; then
|
|
||||||
fp="$(printf '%s\n' "$key" | ssh-keygen -lf - 2>/dev/null | awk '{print $2}')"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Shorten long comments
|
|
||||||
[[ ${#cmt} -gt 40 ]] && cmt="${cmt:0:37}..."
|
|
||||||
|
|
||||||
CI_SSH_COUNT=$((CI_SSH_COUNT + 1))
|
|
||||||
id="K${CI_SSH_COUNT}"
|
|
||||||
echo "${id}|${key}" >>"$CI_SSH_MAPFILE"
|
|
||||||
CI_SSH_CHOICES+=("$id" "[$typ] ${fp:+$fp }${cmt:+$cmt }— ${base}" "OFF")
|
|
||||||
done < <(_ci_ssh_extract_keys_from_file "$f")
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# configure_cloudinit_ssh_keys - Interactive SSH key selection for Cloud-Init
|
|
||||||
#
|
|
||||||
# Usage: configure_cloudinit_ssh_keys
|
|
||||||
# Sets: CLOUDINIT_SSH_KEYS (path to temporary file with selected keys)
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
function configure_cloudinit_ssh_keys() {
|
|
||||||
local backtitle="Proxmox VE Helper Scripts"
|
|
||||||
local ssh_key_mode
|
|
||||||
|
|
||||||
# Create temp file for selected keys
|
|
||||||
CLOUDINIT_SSH_KEYS_TEMP="$(mktemp)"
|
|
||||||
: >"$CLOUDINIT_SSH_KEYS_TEMP"
|
|
||||||
|
|
||||||
# Discover keys and build choices
|
|
||||||
IFS=$'\0' read -r -d '' -a _def_files < <(_ci_ssh_discover_files && printf '\0')
|
|
||||||
_ci_ssh_build_choices "${_def_files[@]}"
|
|
||||||
local default_key_count="$CI_SSH_COUNT"
|
|
||||||
|
|
||||||
if [[ "$default_key_count" -gt 0 ]]; then
|
|
||||||
ssh_key_mode=$(whiptail --backtitle "$backtitle" --title "SSH KEY SOURCE" --menu \
|
|
||||||
"Provision SSH keys for Cloud-Init VM:" 14 72 4 \
|
|
||||||
"found" "Select from detected keys (${default_key_count})" \
|
|
||||||
"manual" "Paste a single public key" \
|
|
||||||
"folder" "Scan another folder (path or glob)" \
|
|
||||||
"none" "No SSH keys (password auth only)" 3>&1 1>&2 2>&3) || return 1
|
|
||||||
else
|
|
||||||
ssh_key_mode=$(whiptail --backtitle "$backtitle" --title "SSH KEY SOURCE" --menu \
|
|
||||||
"No host keys detected. Choose:" 12 72 3 \
|
|
||||||
"manual" "Paste a single public key" \
|
|
||||||
"folder" "Scan another folder (path or glob)" \
|
|
||||||
"none" "No SSH keys (password auth only)" 3>&1 1>&2 2>&3) || return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$ssh_key_mode" in
|
|
||||||
found)
|
|
||||||
# Show checklist with individual keys
|
|
||||||
local selection
|
|
||||||
selection=$(whiptail --backtitle "$backtitle" --title "SELECT SSH KEYS" \
|
|
||||||
--checklist "Select one or more keys to import:" 20 140 10 "${CI_SSH_CHOICES[@]}" 3>&1 1>&2 2>&3) || return 1
|
|
||||||
|
|
||||||
for tag in $selection; do
|
|
||||||
tag="${tag%\"}"
|
|
||||||
tag="${tag#\"}"
|
|
||||||
local line
|
|
||||||
line=$(grep -E "^${tag}\|" "$CI_SSH_MAPFILE" | head -n1 | cut -d'|' -f2-)
|
|
||||||
[[ -n "$line" ]] && printf '%s\n' "$line" >>"$CLOUDINIT_SSH_KEYS_TEMP"
|
|
||||||
done
|
|
||||||
local imported
|
|
||||||
imported=$(wc -l <"$CLOUDINIT_SSH_KEYS_TEMP")
|
|
||||||
echo -e "${ROOTSSH:- 🔑 }${BOLD}${DGN}SSH Keys: ${BGN}${imported} key(s) selected${CL}"
|
|
||||||
;;
|
|
||||||
manual)
|
|
||||||
local pubkey
|
|
||||||
pubkey=$(whiptail --backtitle "$backtitle" --title "PASTE SSH PUBLIC KEY" \
|
|
||||||
--inputbox "Paste your SSH public key (ssh-rsa, ssh-ed25519, etc.):" 10 76 3>&1 1>&2 2>&3) || return 1
|
|
||||||
if [[ -n "$pubkey" ]]; then
|
|
||||||
echo "$pubkey" >"$CLOUDINIT_SSH_KEYS_TEMP"
|
|
||||||
echo -e "${ROOTSSH:- 🔑 }${BOLD}${DGN}SSH Keys: ${BGN}1 key added manually${CL}"
|
|
||||||
else
|
|
||||||
echo -e "${ROOTSSH:- 🔑 }${BOLD}${DGN}SSH Keys: ${BGN}none (empty input)${CL}"
|
|
||||||
CLOUDINIT_SSH_KEYS=""
|
|
||||||
rm -f "$CLOUDINIT_SSH_KEYS_TEMP" "$CI_SSH_MAPFILE" 2>/dev/null
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
folder)
|
|
||||||
local glob_path
|
|
||||||
glob_path=$(whiptail --backtitle "$backtitle" --title "SCAN FOLDER/GLOB" \
|
|
||||||
--inputbox "Enter a folder or glob to scan (e.g. /root/.ssh/*.pub):" 10 72 3>&1 1>&2 2>&3) || return 1
|
|
||||||
if [[ -n "$glob_path" ]]; then
|
|
||||||
shopt -s nullglob
|
|
||||||
local -a _scan_files=($glob_path)
|
|
||||||
shopt -u nullglob
|
|
||||||
if [[ "${#_scan_files[@]}" -gt 0 ]]; then
|
|
||||||
_ci_ssh_build_choices "${_scan_files[@]}"
|
|
||||||
if [[ "$CI_SSH_COUNT" -gt 0 ]]; then
|
|
||||||
local folder_selection
|
|
||||||
folder_selection=$(whiptail --backtitle "$backtitle" --title "SELECT FOLDER KEYS" \
|
|
||||||
--checklist "Select key(s) to import:" 20 140 10 "${CI_SSH_CHOICES[@]}" 3>&1 1>&2 2>&3) || return 1
|
|
||||||
for tag in $folder_selection; do
|
|
||||||
tag="${tag%\"}"
|
|
||||||
tag="${tag#\"}"
|
|
||||||
local line
|
|
||||||
line=$(grep -E "^${tag}\|" "$CI_SSH_MAPFILE" | head -n1 | cut -d'|' -f2-)
|
|
||||||
[[ -n "$line" ]] && printf '%s\n' "$line" >>"$CLOUDINIT_SSH_KEYS_TEMP"
|
|
||||||
done
|
|
||||||
local imported
|
|
||||||
imported=$(wc -l <"$CLOUDINIT_SSH_KEYS_TEMP")
|
|
||||||
echo -e "${ROOTSSH:- 🔑 }${BOLD}${DGN}SSH Keys: ${BGN}${imported} key(s) from folder${CL}"
|
|
||||||
else
|
|
||||||
whiptail --backtitle "$backtitle" --msgbox "No keys found in: $glob_path" 8 60
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
whiptail --backtitle "$backtitle" --msgbox "Path/glob returned no files." 8 60
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
none | *)
|
|
||||||
echo -e "${ROOTSSH:- 🔑 }${BOLD}${DGN}SSH Keys: ${BGN}none (password auth only)${CL}"
|
|
||||||
CLOUDINIT_SSH_KEYS=""
|
|
||||||
rm -f "$CLOUDINIT_SSH_KEYS_TEMP" "$CI_SSH_MAPFILE" 2>/dev/null
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Cleanup mapfile
|
|
||||||
rm -f "$CI_SSH_MAPFILE" 2>/dev/null
|
|
||||||
|
|
||||||
# Set the variable for setup_cloud_init to use
|
|
||||||
if [[ -s "$CLOUDINIT_SSH_KEYS_TEMP" ]]; then
|
|
||||||
CLOUDINIT_SSH_KEYS="$CLOUDINIT_SSH_KEYS_TEMP"
|
|
||||||
else
|
|
||||||
CLOUDINIT_SSH_KEYS=""
|
|
||||||
rm -f "$CLOUDINIT_SSH_KEYS_TEMP"
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# SECTION 3: HELPER FUNCTIONS
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -341,10 +144,9 @@ function setup_cloud_init() {
|
|||||||
local cipassword=$(openssl rand -base64 16)
|
local cipassword=$(openssl rand -base64 16)
|
||||||
qm set "$vmid" --cipassword "$cipassword" >/dev/null
|
qm set "$vmid" --cipassword "$cipassword" >/dev/null
|
||||||
|
|
||||||
# Add SSH keys only if explicitly provided (not auto-imported from host)
|
# Add SSH keys if available
|
||||||
if [ -n "${CLOUDINIT_SSH_KEYS:-}" ] && [ -f "$CLOUDINIT_SSH_KEYS" ]; then
|
if [ -f "$CLOUDINIT_SSH_KEYS" ]; then
|
||||||
qm set "$vmid" --sshkeys "$CLOUDINIT_SSH_KEYS" >/dev/null 2>&1 || true
|
qm set "$vmid" --sshkeys "$CLOUDINIT_SSH_KEYS" >/dev/null 2>&1 || true
|
||||||
_ci_msg_info "SSH keys imported from: $CLOUDINIT_SSH_KEYS"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Configure network
|
# Configure network
|
||||||
@@ -657,11 +459,6 @@ export -f wait_for_cloud_init 2>/dev/null || true
|
|||||||
export -f validate_ip_cidr 2>/dev/null || true
|
export -f validate_ip_cidr 2>/dev/null || true
|
||||||
export -f validate_ip 2>/dev/null || true
|
export -f validate_ip 2>/dev/null || true
|
||||||
|
|
||||||
# Restore previous shell options if they were saved
|
|
||||||
if [ -n "${_OLD_SET_STATE:-}" ]; then
|
|
||||||
eval "$_OLD_SET_STATE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# SECTION 7: EXAMPLES & DOCUMENTATION
|
# SECTION 7: EXAMPLES & DOCUMENTATION
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
____ _ __ ____ __ ___ ____
|
|
||||||
/ _/___ ___ ____ ___ (_)____/ /_ / __ \__ __/ /_ / (_)____ / __ \_________ _ ____ __
|
|
||||||
/ // __ `__ \/ __ `__ \/ / ___/ __ \ / /_/ / / / / __ \/ / / ___/ / /_/ / ___/ __ \| |/_/ / / /
|
|
||||||
_/ // / / / / / / / / / / / /__/ / / / / ____/ /_/ / /_/ / / / /__ / ____/ / / /_/ /> </ /_/ /
|
|
||||||
/___/_/ /_/ /_/_/ /_/ /_/_/\___/_/ /_/ /_/ \__,_/_.___/_/_/\___/ /_/ /_/ \____/_/|_|\__, /
|
|
||||||
/____/
|
|
||||||
726
vm/docker-vm.sh
726
vm/docker-vm.sh
@@ -1,45 +1,71 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
# Author: thost96 (thost96) | michelroegl-brunner | MickLesk
|
# Author: thost96 (thost96) | Co-Author: michelroegl-brunner
|
||||||
# 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 <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
|
||||||
# Docker VM - Creates a Docker-ready Virtual Machine
|
|
||||||
# ==============================================================================
|
|
||||||
|
|
||||||
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVE/raw/branch/main/misc/api.func) 2>/dev/null
|
function header_info() {
|
||||||
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVE/raw/branch/main/misc/vm-core.func) 2>/dev/null
|
clear
|
||||||
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVE/raw/branch/main/misc/cloud-init.func) 2>/dev/null || true
|
cat <<"EOF"
|
||||||
load_functions
|
____ __ _ ____ ___
|
||||||
|
/ __ \____ _____/ /_____ _____ | | / / |/ /
|
||||||
# ==============================================================================
|
/ / / / __ \/ ___/ //_/ _ \/ ___/ | | / / /|_/ /
|
||||||
# SCRIPT VARIABLES
|
/ /_/ / /_/ / /__/ ,< / __/ / | |/ / / / /
|
||||||
# ==============================================================================
|
/_____/\____/\___/_/|_|\___/_/ |___/_/ /_/
|
||||||
APP="Docker"
|
|
||||||
APP_TYPE="vm"
|
|
||||||
NSAPP="docker-vm"
|
|
||||||
var_os="debian"
|
|
||||||
var_version="13"
|
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "\n Loading..."
|
||||||
GEN_MAC=02:$(openssl rand -hex 5 | awk '{print toupper($0)}' | sed 's/\(..\)/\1:/g; s/.$//')
|
GEN_MAC=02:$(openssl rand -hex 5 | awk '{print toupper($0)}' | sed 's/\(..\)/\1:/g; s/.$//')
|
||||||
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)"
|
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)"
|
||||||
METHOD=""
|
METHOD=""
|
||||||
|
NSAPP="docker-vm"
|
||||||
|
var_os="debian"
|
||||||
|
var_version="12"
|
||||||
DISK_SIZE="10G"
|
DISK_SIZE="10G"
|
||||||
USE_CLOUD_INIT="no"
|
|
||||||
OS_TYPE=""
|
|
||||||
OS_VERSION=""
|
|
||||||
THIN="discard=on,ssd=1,"
|
|
||||||
|
|
||||||
# ==============================================================================
|
YW=$(echo "\033[33m")
|
||||||
# ERROR HANDLING & CLEANUP
|
BL=$(echo "\033[36m")
|
||||||
# ==============================================================================
|
RD=$(echo "\033[01;31m")
|
||||||
|
BGN=$(echo "\033[4;92m")
|
||||||
|
GN=$(echo "\033[1;92m")
|
||||||
|
DGN=$(echo "\033[32m")
|
||||||
|
CL=$(echo "\033[m")
|
||||||
|
|
||||||
|
CL=$(echo "\033[m")
|
||||||
|
BOLD=$(echo "\033[1m")
|
||||||
|
BFR="\\r\\033[K"
|
||||||
|
HOLD=" "
|
||||||
|
TAB=" "
|
||||||
|
|
||||||
|
CM="${TAB}✔️${TAB}${CL}"
|
||||||
|
CROSS="${TAB}✖️${TAB}${CL}"
|
||||||
|
INFO="${TAB}💡${TAB}${CL}"
|
||||||
|
OS="${TAB}🖥️${TAB}${CL}"
|
||||||
|
CONTAINERTYPE="${TAB}📦${TAB}${CL}"
|
||||||
|
DISKSIZE="${TAB}💾${TAB}${CL}"
|
||||||
|
CPUCORE="${TAB}🧠${TAB}${CL}"
|
||||||
|
RAMSIZE="${TAB}🛠️${TAB}${CL}"
|
||||||
|
CONTAINERID="${TAB}🆔${TAB}${CL}"
|
||||||
|
HOSTNAME="${TAB}🏠${TAB}${CL}"
|
||||||
|
BRIDGE="${TAB}🌉${TAB}${CL}"
|
||||||
|
GATEWAY="${TAB}🌐${TAB}${CL}"
|
||||||
|
DEFAULT="${TAB}⚙️${TAB}${CL}"
|
||||||
|
MACADDRESS="${TAB}🔗${TAB}${CL}"
|
||||||
|
VLANTAG="${TAB}🏷️${TAB}${CL}"
|
||||||
|
CREATING="${TAB}🚀${TAB}${CL}"
|
||||||
|
ADVANCED="${TAB}🧩${TAB}${CL}"
|
||||||
|
CLOUD="${TAB}☁️${TAB}${CL}"
|
||||||
|
|
||||||
|
THIN="discard=on,ssd=1,"
|
||||||
set -e
|
set -e
|
||||||
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
||||||
trap cleanup EXIT
|
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"
|
||||||
@@ -50,96 +76,140 @@ function error_handler() {
|
|||||||
cleanup_vmid
|
cleanup_vmid
|
||||||
}
|
}
|
||||||
|
|
||||||
# ==============================================================================
|
function get_valid_nextid() {
|
||||||
# OS SELECTION FUNCTIONS
|
local try_id
|
||||||
# ==============================================================================
|
try_id=$(pvesh get /cluster/nextid)
|
||||||
function select_os() {
|
while true; do
|
||||||
if OS_CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SELECT OS" --radiolist \
|
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
|
||||||
"Choose Operating System for Docker VM" 14 68 4 \
|
try_id=$((try_id + 1))
|
||||||
"debian13" "Debian 13 (Trixie) - Latest" ON \
|
continue
|
||||||
"debian12" "Debian 12 (Bookworm) - Stable" OFF \
|
fi
|
||||||
"ubuntu2404" "Ubuntu 24.04 LTS (Noble)" OFF \
|
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
|
||||||
"ubuntu2204" "Ubuntu 22.04 LTS (Jammy)" OFF \
|
try_id=$((try_id + 1))
|
||||||
3>&1 1>&2 2>&3); then
|
continue
|
||||||
case $OS_CHOICE in
|
fi
|
||||||
debian13)
|
break
|
||||||
OS_TYPE="debian"
|
done
|
||||||
OS_VERSION="13"
|
echo "$try_id"
|
||||||
OS_CODENAME="trixie"
|
}
|
||||||
OS_DISPLAY="Debian 13 (Trixie)"
|
|
||||||
;;
|
function cleanup_vmid() {
|
||||||
debian12)
|
if qm status $VMID &>/dev/null; then
|
||||||
OS_TYPE="debian"
|
qm stop $VMID &>/dev/null
|
||||||
OS_VERSION="12"
|
qm destroy $VMID &>/dev/null
|
||||||
OS_CODENAME="bookworm"
|
|
||||||
OS_DISPLAY="Debian 12 (Bookworm)"
|
|
||||||
;;
|
|
||||||
ubuntu2404)
|
|
||||||
OS_TYPE="ubuntu"
|
|
||||||
OS_VERSION="24.04"
|
|
||||||
OS_CODENAME="noble"
|
|
||||||
OS_DISPLAY="Ubuntu 24.04 LTS"
|
|
||||||
;;
|
|
||||||
ubuntu2204)
|
|
||||||
OS_TYPE="ubuntu"
|
|
||||||
OS_VERSION="22.04"
|
|
||||||
OS_CODENAME="jammy"
|
|
||||||
OS_DISPLAY="Ubuntu 22.04 LTS"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}${OS_DISPLAY}${CL}"
|
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function select_cloud_init() {
|
function cleanup() {
|
||||||
if [ "$OS_TYPE" = "ubuntu" ]; then
|
popd >/dev/null
|
||||||
USE_CLOUD_INIT="yes"
|
post_update_to_api "done" "none"
|
||||||
echo -e "${CLOUD:-${TAB}☁️${TAB}${CL}}${BOLD}${DGN}Cloud-Init: ${BGN}yes (Ubuntu requires Cloud-Init)${CL}"
|
rm -rf $TEMP_DIR
|
||||||
return
|
}
|
||||||
|
|
||||||
|
TEMP_DIR=$(mktemp -d)
|
||||||
|
pushd $TEMP_DIR >/dev/null
|
||||||
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Docker VM" --yesno "This will create a New Docker VM. Proceed?" 10 58; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "CLOUD-INIT" \
|
function msg_info() {
|
||||||
--yesno "Enable Cloud-Init for VM configuration?\n\nCloud-Init allows automatic configuration of:\n- User accounts and passwords\n- SSH keys\n- Network settings (DHCP/Static)\n- DNS configuration\n\nYou can also configure these settings later in Proxmox UI.\n\nNote: Debian without Cloud-Init will use nocloud image with console auto-login." 18 68); then
|
local msg="$1"
|
||||||
USE_CLOUD_INIT="yes"
|
echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
|
||||||
echo -e "${CLOUD:-${TAB}☁️${TAB}${CL}}${BOLD}${DGN}Cloud-Init: ${BGN}yes${CL}"
|
}
|
||||||
else
|
|
||||||
USE_CLOUD_INIT="no"
|
function msg_ok() {
|
||||||
echo -e "${CLOUD:-${TAB}☁️${TAB}${CL}}${BOLD}${DGN}Cloud-Init: ${BGN}no${CL}"
|
local msg="$1"
|
||||||
|
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function msg_error() {
|
||||||
|
local msg="$1"
|
||||||
|
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_root() {
|
||||||
|
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
|
||||||
|
clear
|
||||||
|
msg_error "Please run this script as root."
|
||||||
|
echo -e "\nExiting..."
|
||||||
|
sleep 2
|
||||||
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_image_url() {
|
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
|
||||||
local arch=$(dpkg --print-architecture)
|
# Supported: Proxmox VE 8.0.x – 8.9.x, 9.0 and 9.1
|
||||||
case $OS_TYPE in
|
pve_check() {
|
||||||
debian)
|
local PVE_VER
|
||||||
if [ "$USE_CLOUD_INIT" = "yes" ]; then
|
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
|
||||||
echo "https://cloud.debian.org/images/cloud/${OS_CODENAME}/latest/debian-${OS_VERSION}-generic-${arch}.qcow2"
|
|
||||||
else
|
# Check for Proxmox VE 8.x: allow 8.0–8.9
|
||||||
echo "https://cloud.debian.org/images/cloud/${OS_CODENAME}/latest/debian-${OS_VERSION}-nocloud-${arch}.qcow2"
|
if [[ "$PVE_VER" =~ ^8\.([0-9]+) ]]; then
|
||||||
|
local MINOR="${BASH_REMATCH[1]}"
|
||||||
|
if ((MINOR < 0 || MINOR > 9)); then
|
||||||
|
msg_error "This version of Proxmox VE is not supported."
|
||||||
|
msg_error "Supported: Proxmox VE version 8.0 – 8.9"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
;;
|
return 0
|
||||||
ubuntu)
|
fi
|
||||||
echo "https://cloud-images.ubuntu.com/${OS_CODENAME}/current/${OS_CODENAME}-server-cloudimg-${arch}.img"
|
|
||||||
;;
|
# Check for Proxmox VE 9.x: allow 9.0 and 9.1
|
||||||
esac
|
if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
|
||||||
|
local MINOR="${BASH_REMATCH[1]}"
|
||||||
|
if ((MINOR < 0 || MINOR > 1)); then
|
||||||
|
msg_error "This version of Proxmox VE is not supported."
|
||||||
|
msg_error "Supported: Proxmox VE version 9.0 – 9.1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# All other unsupported versions
|
||||||
|
msg_error "This version of Proxmox VE is not supported."
|
||||||
|
msg_error "Supported versions: Proxmox VE 8.0 – 8.x or 9.0 – 9.1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function arch_check() {
|
||||||
|
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
|
||||||
|
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 "Exiting..."
|
||||||
|
sleep 2
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function ssh_check() {
|
||||||
|
if command -v pveversion >/dev/null 2>&1; 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
|
||||||
|
echo "you've been warned"
|
||||||
|
else
|
||||||
|
clear
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function exit-script() {
|
||||||
|
clear
|
||||||
|
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
|
||||||
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# SETTINGS FUNCTIONS
|
|
||||||
# ==============================================================================
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
select_os
|
|
||||||
select_cloud_init
|
|
||||||
|
|
||||||
VMID=$(get_valid_nextid)
|
VMID=$(get_valid_nextid)
|
||||||
FORMAT=""
|
FORMAT=",efitype=4m"
|
||||||
MACHINE=" -machine q35"
|
MACHINE=""
|
||||||
DISK_CACHE=""
|
DISK_CACHE=""
|
||||||
DISK_SIZE="10G"
|
DISK_SIZE="10G"
|
||||||
HN="docker"
|
HN="docker"
|
||||||
CPU_TYPE=" -cpu host"
|
CPU_TYPE=""
|
||||||
CORE_COUNT="2"
|
CORE_COUNT="2"
|
||||||
RAM_SIZE="4096"
|
RAM_SIZE="4096"
|
||||||
BRG="vmbr0"
|
BRG="vmbr0"
|
||||||
@@ -148,13 +218,12 @@ function default_settings() {
|
|||||||
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}Q35 (Modern)${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}Host${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}"
|
||||||
@@ -162,22 +231,12 @@ function default_settings() {
|
|||||||
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 Docker VM using the above settings${CL}"
|
echo -e "${CREATING}${BOLD}${DGN}Creating a Docker VM using the above default settings${CL}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function advanced_settings() {
|
function advanced_settings() {
|
||||||
select_os
|
|
||||||
select_cloud_init
|
|
||||||
|
|
||||||
# SSH Key selection for Cloud-Init VMs
|
|
||||||
if [ "$USE_CLOUD_INIT" = "yes" ]; then
|
|
||||||
configure_cloudinit_ssh_keys || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
METHOD="advanced"
|
METHOD="advanced"
|
||||||
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
||||||
|
|
||||||
# VM ID
|
|
||||||
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
|
||||||
@@ -191,29 +250,27 @@ function advanced_settings() {
|
|||||||
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
|
else
|
||||||
exit_script
|
exit-script
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Machine Type
|
|
||||||
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
|
||||||
"q35" "Q35 (Modern, PCIe)" ON \
|
"i440fx" "Machine i440fx" ON \
|
||||||
"i440fx" "i440fx (Legacy, PCI)" OFF \
|
"q35" "Machine q35" OFF \
|
||||||
3>&1 1>&2 2>&3); then
|
3>&1 1>&2 2>&3); then
|
||||||
if [ $MACH = q35 ]; then
|
if [ $MACH = q35 ]; then
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}Q35 (Modern)${CL}"
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
||||||
FORMAT=""
|
FORMAT=""
|
||||||
MACHINE=" -machine q35"
|
MACHINE=" -machine q35"
|
||||||
else
|
else
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx (Legacy)${CL}"
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
|
||||||
FORMAT=",efitype=4m"
|
FORMAT=",efitype=4m"
|
||||||
MACHINE=""
|
MACHINE=""
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
exit_script
|
exit-script
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Disk Size
|
|
||||||
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_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
|
||||||
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
|
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
|
||||||
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
|
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
|
||||||
@@ -223,13 +280,12 @@ function advanced_settings() {
|
|||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
|
||||||
else
|
else
|
||||||
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
|
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
|
else
|
||||||
exit_script
|
exit-script
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Disk Cache
|
|
||||||
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
"0" "None (Default)" ON \
|
"0" "None (Default)" ON \
|
||||||
"1" "Write Through" OFF \
|
"1" "Write Through" OFF \
|
||||||
@@ -242,25 +298,24 @@ function advanced_settings() {
|
|||||||
DISK_CACHE=""
|
DISK_CACHE=""
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
exit_script
|
exit-script
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Hostname
|
|
||||||
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 docker --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 docker --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
||||||
if [ -z $VM_NAME ]; then
|
if [ -z $VM_NAME ]; then
|
||||||
HN="docker"
|
HN="docker"
|
||||||
else
|
|
||||||
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
|
||||||
fi
|
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
else
|
else
|
||||||
exit_script
|
HN=$(echo ${VM_NAME,,} | tr -d ' ')
|
||||||
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# CPU Model
|
|
||||||
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
|
||||||
"1" "Host (Recommended)" ON \
|
"0" "KVM64 (Default)" ON \
|
||||||
"0" "KVM64" OFF \
|
"1" "Host" OFF \
|
||||||
3>&1 1>&2 2>&3); then
|
3>&1 1>&2 2>&3); then
|
||||||
if [ $CPU_TYPE1 = "1" ]; then
|
if [ $CPU_TYPE1 = "1" ]; then
|
||||||
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
|
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
|
||||||
@@ -270,78 +325,80 @@ function advanced_settings() {
|
|||||||
CPU_TYPE=""
|
CPU_TYPE=""
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
exit_script
|
exit-script
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# CPU Cores
|
|
||||||
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 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 [ -z $CORE_COUNT ]; then
|
if [ -z $CORE_COUNT ]; then
|
||||||
CORE_COUNT="2"
|
CORE_COUNT="2"
|
||||||
fi
|
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
else
|
else
|
||||||
exit_script
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# RAM Size
|
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 RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 4096 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
|
|
||||||
if [ -z $RAM_SIZE ]; then
|
if [ -z $RAM_SIZE ]; then
|
||||||
RAM_SIZE="4096"
|
RAM_SIZE="2048"
|
||||||
fi
|
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
||||||
else
|
else
|
||||||
exit_script
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Bridge
|
|
||||||
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 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
|
if [ -z $BRG ]; then
|
||||||
BRG="vmbr0"
|
BRG="vmbr0"
|
||||||
fi
|
|
||||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||||
else
|
else
|
||||||
exit_script
|
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# MAC Address
|
|
||||||
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 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 $MAC1 ]; then
|
if [ -z $MAC1 ]; then
|
||||||
MAC="$GEN_MAC"
|
MAC="$GEN_MAC"
|
||||||
else
|
|
||||||
MAC="$MAC1"
|
|
||||||
fi
|
|
||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
|
||||||
else
|
else
|
||||||
exit_script
|
MAC="$MAC1"
|
||||||
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# VLAN
|
|
||||||
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 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 $VLAN1 ]; then
|
if [ -z $VLAN1 ]; then
|
||||||
VLAN1="Default"
|
VLAN1="Default"
|
||||||
VLAN=""
|
VLAN=""
|
||||||
else
|
|
||||||
VLAN=",tag=$VLAN1"
|
|
||||||
fi
|
|
||||||
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
||||||
else
|
else
|
||||||
exit_script
|
VLAN=",tag=$VLAN1"
|
||||||
|
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# MTU
|
|
||||||
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 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
|
if [ -z $MTU1 ]; then
|
||||||
MTU1="Default"
|
MTU1="Default"
|
||||||
MTU=""
|
MTU=""
|
||||||
else
|
|
||||||
MTU=",mtu=$MTU1"
|
|
||||||
fi
|
|
||||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
else
|
else
|
||||||
exit_script
|
MTU=",mtu=$MTU1"
|
||||||
|
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
exit-script
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Start VM
|
|
||||||
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 "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
|
||||||
START_VM="yes"
|
START_VM="yes"
|
||||||
@@ -350,7 +407,6 @@ function advanced_settings() {
|
|||||||
START_VM="no"
|
START_VM="no"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Confirm
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Docker VM?" --no-button Do-Over 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Docker VM?" --no-button Do-Over 10 58); then
|
||||||
echo -e "${CREATING}${BOLD}${DGN}Creating a Docker VM using the above advanced settings${CL}"
|
echo -e "${CREATING}${BOLD}${DGN}Creating a Docker VM using the above advanced settings${CL}"
|
||||||
else
|
else
|
||||||
@@ -371,28 +427,13 @@ function start_script() {
|
|||||||
advanced_settings
|
advanced_settings
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# MAIN EXECUTION
|
|
||||||
# ==============================================================================
|
|
||||||
header_info
|
|
||||||
|
|
||||||
check_root
|
check_root
|
||||||
arch_check
|
arch_check
|
||||||
pve_check
|
pve_check
|
||||||
|
ssh_check
|
||||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Docker VM" --yesno "This will create a New Docker VM. Proceed?" 10 58; then
|
|
||||||
:
|
|
||||||
else
|
|
||||||
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
start_script
|
start_script
|
||||||
post_to_api_vm
|
post_to_api_vm
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# STORAGE SELECTION
|
|
||||||
# ==============================================================================
|
|
||||||
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}')
|
||||||
@@ -405,7 +446,6 @@ while read -r line; do
|
|||||||
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."
|
||||||
@@ -413,8 +453,6 @@ if [ -z "$VALID" ]; then
|
|||||||
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
|
||||||
STORAGE=${STORAGE_MENU[0]}
|
STORAGE=${STORAGE_MENU[0]}
|
||||||
else
|
else
|
||||||
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
|
|
||||||
printf "\e[?25h"
|
|
||||||
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" \
|
||||||
@@ -424,288 +462,112 @@ else
|
|||||||
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}."
|
||||||
|
msg_info "Retrieving the URL for the Debian 12 Qcow2 Disk Image"
|
||||||
# ==============================================================================
|
URL="https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-$(dpkg --print-architecture).qcow2"
|
||||||
# PREREQUISITES
|
sleep 2
|
||||||
# ==============================================================================
|
|
||||||
if ! command -v virt-customize &>/dev/null; then
|
|
||||||
msg_info "Installing libguestfs-tools"
|
|
||||||
apt-get -qq update >/dev/null
|
|
||||||
apt-get -qq install libguestfs-tools lsb-release -y >/dev/null
|
|
||||||
apt-get -qq install dhcpcd-base -y >/dev/null 2>&1 || true
|
|
||||||
msg_ok "Installed libguestfs-tools"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# IMAGE DOWNLOAD
|
|
||||||
# ==============================================================================
|
|
||||||
msg_info "Retrieving the URL for the ${OS_DISPLAY} Qcow2 Disk Image"
|
|
||||||
URL=$(get_image_url)
|
|
||||||
CACHE_DIR="/var/lib/vz/template/cache"
|
|
||||||
CACHE_FILE="$CACHE_DIR/$(basename "$URL")"
|
|
||||||
mkdir -p "$CACHE_DIR"
|
|
||||||
msg_ok "${CL}${BL}${URL}${CL}"
|
msg_ok "${CL}${BL}${URL}${CL}"
|
||||||
|
curl -f#SL -o "$(basename "$URL")" "$URL"
|
||||||
if [[ ! -s "$CACHE_FILE" ]]; then
|
|
||||||
curl -f#SL -o "$CACHE_FILE" "$URL"
|
|
||||||
echo -en "\e[1A\e[0K"
|
echo -en "\e[1A\e[0K"
|
||||||
msg_ok "Downloaded ${CL}${BL}$(basename "$CACHE_FILE")${CL}"
|
FILE=$(basename $URL)
|
||||||
else
|
msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
|
||||||
msg_ok "Using cached image ${CL}${BL}$(basename "$CACHE_FILE")${CL}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# STORAGE TYPE DETECTION
|
|
||||||
# ==============================================================================
|
|
||||||
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=""
|
||||||
;;
|
;;
|
||||||
*)
|
|
||||||
DISK_EXT=""
|
|
||||||
DISK_REF=""
|
|
||||||
DISK_IMPORT="--format raw"
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
|
for i in {0,1}; do
|
||||||
# ==============================================================================
|
disk="DISK$i"
|
||||||
# IMAGE CUSTOMIZATION WITH DOCKER
|
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
|
||||||
# ==============================================================================
|
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
|
||||||
msg_info "Preparing ${OS_DISPLAY} image with Docker"
|
|
||||||
|
|
||||||
WORK_FILE=$(mktemp --suffix=.qcow2)
|
|
||||||
cp "$CACHE_FILE" "$WORK_FILE"
|
|
||||||
|
|
||||||
export LIBGUESTFS_BACKEND_SETTINGS=dns=8.8.8.8,1.1.1.1
|
|
||||||
|
|
||||||
DOCKER_PREINSTALLED="no"
|
|
||||||
|
|
||||||
# Install qemu-guest-agent and Docker during image customization
|
|
||||||
msg_info "Installing base packages in image"
|
|
||||||
if virt-customize -a "$WORK_FILE" --install qemu-guest-agent,curl,ca-certificates >/dev/null 2>&1; then
|
|
||||||
msg_ok "Installed base packages"
|
|
||||||
|
|
||||||
msg_info "Installing Docker (this may take 2-5 minutes)"
|
|
||||||
if virt-customize -q -a "$WORK_FILE" --run-command "curl -fsSL https://get.docker.com | sh" >/dev/null 2>&1 &&
|
|
||||||
virt-customize -q -a "$WORK_FILE" --run-command "systemctl enable docker" >/dev/null 2>&1; then
|
|
||||||
msg_ok "Installed Docker"
|
|
||||||
|
|
||||||
msg_info "Configuring Docker daemon"
|
|
||||||
# Optimize Docker daemon configuration
|
|
||||||
virt-customize -q -a "$WORK_FILE" --run-command "mkdir -p /etc/docker" >/dev/null 2>&1
|
|
||||||
virt-customize -q -a "$WORK_FILE" --run-command 'cat > /etc/docker/daemon.json << EOF
|
|
||||||
{
|
|
||||||
"storage-driver": "overlay2",
|
|
||||||
"log-driver": "json-file",
|
|
||||||
"log-opts": {
|
|
||||||
"max-size": "10m",
|
|
||||||
"max-file": "3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF' >/dev/null 2>&1
|
|
||||||
DOCKER_PREINSTALLED="yes"
|
|
||||||
msg_ok "Configured Docker daemon"
|
|
||||||
else
|
|
||||||
msg_ok "Docker will be installed on first boot"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
msg_ok "Packages will be installed on first boot"
|
|
||||||
fi
|
|
||||||
|
|
||||||
msg_info "Finalizing image (hostname, SSH config)"
|
|
||||||
# Set hostname and prepare for unique machine-id
|
|
||||||
virt-customize -q -a "$WORK_FILE" --hostname "${HN}" >/dev/null 2>&1
|
|
||||||
virt-customize -q -a "$WORK_FILE" --run-command "truncate -s 0 /etc/machine-id" >/dev/null 2>&1
|
|
||||||
virt-customize -q -a "$WORK_FILE" --run-command "rm -f /var/lib/dbus/machine-id" >/dev/null 2>&1
|
|
||||||
|
|
||||||
# Configure SSH for Cloud-Init
|
|
||||||
if [ "$USE_CLOUD_INIT" = "yes" ]; then
|
|
||||||
virt-customize -q -a "$WORK_FILE" --run-command "sed -i 's/^#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config" >/dev/null 2>&1 || true
|
|
||||||
virt-customize -q -a "$WORK_FILE" --run-command "sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config" >/dev/null 2>&1 || true
|
|
||||||
else
|
|
||||||
# Configure auto-login for nocloud images (no Cloud-Init)
|
|
||||||
virt-customize -q -a "$WORK_FILE" --run-command "mkdir -p /etc/systemd/system/serial-getty@ttyS0.service.d" >/dev/null 2>&1 || true
|
|
||||||
virt-customize -q -a "$WORK_FILE" --run-command 'cat > /etc/systemd/system/serial-getty@ttyS0.service.d/autologin.conf << EOF
|
|
||||||
[Service]
|
|
||||||
ExecStart=
|
|
||||||
ExecStart=-/sbin/agetty --autologin root --noclear %I \$TERM
|
|
||||||
EOF' >/dev/null 2>&1 || true
|
|
||||||
virt-customize -q -a "$WORK_FILE" --run-command "mkdir -p /etc/systemd/system/getty@tty1.service.d" >/dev/null 2>&1 || true
|
|
||||||
virt-customize -q -a "$WORK_FILE" --run-command 'cat > /etc/systemd/system/getty@tty1.service.d/autologin.conf << EOF
|
|
||||||
[Service]
|
|
||||||
ExecStart=
|
|
||||||
ExecStart=-/sbin/agetty --autologin root --noclear %I \$TERM
|
|
||||||
EOF' >/dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
msg_ok "Finalized image"
|
|
||||||
|
|
||||||
# Create first-boot Docker install script (fallback if virt-customize failed)
|
|
||||||
if [ "$DOCKER_PREINSTALLED" = "no" ]; then
|
|
||||||
virt-customize -q -a "$WORK_FILE" --run-command 'cat > /root/install-docker.sh << "DOCKERSCRIPT"
|
|
||||||
#!/bin/bash
|
|
||||||
exec > /var/log/install-docker.log 2>&1
|
|
||||||
echo "[$(date)] Starting Docker installation"
|
|
||||||
|
|
||||||
for i in {1..30}; do
|
|
||||||
ping -c 1 8.8.8.8 >/dev/null 2>&1 && break
|
|
||||||
sleep 2
|
|
||||||
done
|
done
|
||||||
|
|
||||||
apt-get update
|
if ! command -v virt-customize &>/dev/null; then
|
||||||
apt-get install -y qemu-guest-agent curl ca-certificates
|
msg_info "Installing Pre-Requisite libguestfs-tools onto Host"
|
||||||
curl -fsSL https://get.docker.com | sh
|
apt-get -qq update >/dev/null
|
||||||
systemctl enable docker
|
apt-get -qq install libguestfs-tools lsb-release -y >/dev/null
|
||||||
systemctl start docker
|
# Workaround for Proxmox VE 9.0 libguestfs issue
|
||||||
|
apt-get -qq install dhcpcd-base -y >/dev/null 2>&1 || true
|
||||||
mkdir -p /etc/docker
|
msg_ok "Installed libguestfs-tools successfully"
|
||||||
cat > /etc/docker/daemon.json << DAEMON
|
|
||||||
{
|
|
||||||
"storage-driver": "overlay2",
|
|
||||||
"log-driver": "json-file",
|
|
||||||
"log-opts": { "max-size": "10m", "max-file": "3" }
|
|
||||||
}
|
|
||||||
DAEMON
|
|
||||||
systemctl restart docker
|
|
||||||
|
|
||||||
touch /root/.docker-installed
|
|
||||||
echo "[$(date)] Docker installation completed"
|
|
||||||
DOCKERSCRIPT
|
|
||||||
chmod +x /root/install-docker.sh' >/dev/null 2>&1
|
|
||||||
|
|
||||||
virt-customize -q -a "$WORK_FILE" --run-command 'cat > /etc/systemd/system/install-docker.service << "DOCKERSERVICE"
|
|
||||||
[Unit]
|
|
||||||
Description=Install Docker on First Boot
|
|
||||||
After=network-online.target
|
|
||||||
Wants=network-online.target
|
|
||||||
ConditionPathExists=!/root/.docker-installed
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=oneshot
|
|
||||||
ExecStart=/root/install-docker.sh
|
|
||||||
RemainAfterExit=yes
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
DOCKERSERVICE
|
|
||||||
systemctl enable install-docker.service' >/dev/null 2>&1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Resize disk to target size
|
msg_info "Adding Docker and Docker Compose Plugin to Debian 12 Qcow2 Disk Image"
|
||||||
msg_info "Resizing disk image to ${DISK_SIZE}"
|
virt-customize -q -a "${FILE}" --install qemu-guest-agent,apt-transport-https,ca-certificates,curl,gnupg,software-properties-common,lsb-release >/dev/null &&
|
||||||
qemu-img resize "$WORK_FILE" "${DISK_SIZE}" >/dev/null 2>&1
|
virt-customize -q -a "${FILE}" --run-command "mkdir -p /etc/apt/keyrings && curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg" >/dev/null &&
|
||||||
msg_ok "Resized disk image"
|
virt-customize -q -a "${FILE}" --run-command "echo 'deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable' > /etc/apt/sources.list.d/docker.list" >/dev/null &&
|
||||||
|
virt-customize -q -a "${FILE}" --run-command "apt-get update -qq && apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin" >/dev/null &&
|
||||||
|
virt-customize -q -a "${FILE}" --run-command "systemctl enable docker" >/dev/null &&
|
||||||
|
virt-customize -q -a "${FILE}" --hostname "${HN}" >/dev/null &&
|
||||||
|
virt-customize -q -a "${FILE}" --run-command "echo -n > /etc/machine-id" >/dev/null
|
||||||
|
msg_ok "Added Docker and Docker Compose Plugin to Debian 12 Qcow2 Disk Image successfully"
|
||||||
|
|
||||||
# ==============================================================================
|
msg_info "Expanding root partition to use full disk space"
|
||||||
# VM CREATION
|
qemu-img create -f qcow2 expanded.qcow2 ${DISK_SIZE} >/dev/null 2>&1
|
||||||
# ==============================================================================
|
virt-resize --expand /dev/sda1 ${FILE} expanded.qcow2 >/dev/null 2>&1
|
||||||
msg_info "Creating Docker VM shell"
|
mv expanded.qcow2 ${FILE} >/dev/null 2>&1
|
||||||
|
msg_ok "Expanded image to full size"
|
||||||
|
|
||||||
|
msg_info "Creating a Docker 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
|
||||||
|
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
|
||||||
msg_ok "Created VM shell"
|
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
|
||||||
|
qm set $VMID \
|
||||||
# ==============================================================================
|
-efidisk0 ${DISK0_REF}${FORMAT} \
|
||||||
# DISK IMPORT
|
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
|
||||||
# ==============================================================================
|
-boot order=scsi0 \
|
||||||
msg_info "Importing disk into storage ($STORAGE)"
|
-serial0 socket >/dev/null
|
||||||
|
qm resize $VMID scsi0 8G >/dev/null
|
||||||
if qm disk import --help >/dev/null 2>&1; then
|
|
||||||
IMPORT_CMD=(qm disk import)
|
|
||||||
else
|
|
||||||
IMPORT_CMD=(qm importdisk)
|
|
||||||
fi
|
|
||||||
|
|
||||||
IMPORT_OUT="$("${IMPORT_CMD[@]}" "$VMID" "$WORK_FILE" "$STORAGE" ${DISK_IMPORT:-} 2>&1 || true)"
|
|
||||||
DISK_REF_IMPORTED="$(printf '%s\n' "$IMPORT_OUT" | sed -n "s/.*successfully imported disk '\([^']\+\)'.*/\1/p" | tr -d "\r\"'")"
|
|
||||||
[[ -z "$DISK_REF_IMPORTED" ]] && DISK_REF_IMPORTED="$(pvesm list "$STORAGE" | awk -v id="$VMID" '$5 ~ ("vm-"id"-disk-") {print $1":"$5}' | sort | tail -n1)"
|
|
||||||
[[ -z "$DISK_REF_IMPORTED" ]] && {
|
|
||||||
msg_error "Unable to determine imported disk reference."
|
|
||||||
echo "$IMPORT_OUT"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_ok "Imported disk (${CL}${BL}${DISK_REF_IMPORTED}${CL})"
|
|
||||||
|
|
||||||
# Clean up work file
|
|
||||||
rm -f "$WORK_FILE"
|
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# VM CONFIGURATION
|
|
||||||
# ==============================================================================
|
|
||||||
msg_info "Attaching EFI and root disk"
|
|
||||||
|
|
||||||
qm set "$VMID" \
|
|
||||||
--efidisk0 "${STORAGE}:0,efitype=4m" \
|
|
||||||
--scsi0 "${DISK_REF_IMPORTED},${DISK_CACHE}${THIN%,}" \
|
|
||||||
--boot order=scsi0 \
|
|
||||||
--serial0 socket >/dev/null
|
|
||||||
|
|
||||||
qm set $VMID --agent enabled=1 >/dev/null
|
qm set $VMID --agent enabled=1 >/dev/null
|
||||||
|
|
||||||
msg_ok "Attached EFI and root disk"
|
DESCRIPTION=$(
|
||||||
|
cat <<EOF
|
||||||
|
<div align='center'>
|
||||||
|
<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;'/>
|
||||||
|
</a>
|
||||||
|
|
||||||
# Set VM description
|
<h2 style='font-size: 24px; margin: 20px 0;'>Docker VM</h2>
|
||||||
set_description
|
|
||||||
|
|
||||||
# Cloud-Init configuration
|
<p style='margin: 16px 0;'>
|
||||||
if [ "$USE_CLOUD_INIT" = "yes" ]; then
|
<a href='https://ko-fi.com/community_scripts' target='_blank' rel='noopener noreferrer'>
|
||||||
msg_info "Configuring Cloud-Init"
|
<img src='https://img.shields.io/badge/☕-Buy us a coffee-blue' alt='spend Coffee' />
|
||||||
setup_cloud_init "$VMID" "$STORAGE" "$HN" "yes"
|
</a>
|
||||||
msg_ok "Cloud-Init configured"
|
</p>
|
||||||
fi
|
|
||||||
|
|
||||||
# Start VM
|
<span style='margin: 0 10px;'>
|
||||||
|
<i class="fa fa-github fa-fw" style="color: #f5f5f5;"></i>
|
||||||
|
<a href='https://github.com/community-scripts/ProxmoxVE' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>GitHub</a>
|
||||||
|
</span>
|
||||||
|
<span style='margin: 0 10px;'>
|
||||||
|
<i class="fa fa-comments fa-fw" style="color: #f5f5f5;"></i>
|
||||||
|
<a href='https://github.com/community-scripts/ProxmoxVE/discussions' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>Discussions</a>
|
||||||
|
</span>
|
||||||
|
<span style='margin: 0 10px;'>
|
||||||
|
<i class="fa fa-exclamation-circle fa-fw" style="color: #f5f5f5;"></i>
|
||||||
|
<a href='https://github.com/community-scripts/ProxmoxVE/issues' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>Issues</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
qm set $VMID -description "$DESCRIPTION" >/dev/null
|
||||||
|
|
||||||
|
msg_ok "Created a Docker VM ${CL}${BL}(${HN})"
|
||||||
if [ "$START_VM" == "yes" ]; then
|
if [ "$START_VM" == "yes" ]; then
|
||||||
msg_info "Starting Docker VM"
|
msg_info "Starting Docker VM"
|
||||||
qm start $VMID >/dev/null 2>&1
|
qm start $VMID
|
||||||
msg_ok "Started Docker VM"
|
msg_ok "Started Docker VM"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# FINAL OUTPUT
|
|
||||||
# ==============================================================================
|
|
||||||
VM_IP=""
|
|
||||||
if [ "$START_VM" == "yes" ]; then
|
|
||||||
set +e
|
|
||||||
for i in {1..10}; do
|
|
||||||
VM_IP=$(qm guest cmd "$VMID" network-get-interfaces 2>/dev/null |
|
|
||||||
jq -r '.[] | select(.name != "lo") | ."ip-addresses"[]? | select(."ip-address-type" == "ipv4") | ."ip-address"' 2>/dev/null |
|
|
||||||
grep -v "^127\." | head -1) || true
|
|
||||||
[ -n "$VM_IP" ] && break
|
|
||||||
sleep 3
|
|
||||||
done
|
|
||||||
set -e
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "\n${INFO}${BOLD}${GN}Docker VM Configuration Summary:${CL}"
|
|
||||||
echo -e "${TAB}${DGN}VM ID: ${BGN}${VMID}${CL}"
|
|
||||||
echo -e "${TAB}${DGN}Hostname: ${BGN}${HN}${CL}"
|
|
||||||
echo -e "${TAB}${DGN}OS: ${BGN}${OS_DISPLAY}${CL}"
|
|
||||||
[ -n "$VM_IP" ] && echo -e "${TAB}${DGN}IP Address: ${BGN}${VM_IP}${CL}"
|
|
||||||
|
|
||||||
if [ "$DOCKER_PREINSTALLED" = "yes" ]; then
|
|
||||||
echo -e "${TAB}${DGN}Docker: ${BGN}Pre-installed (via get.docker.com)${CL}"
|
|
||||||
else
|
|
||||||
echo -e "${TAB}${DGN}Docker: ${BGN}Installing on first boot${CL}"
|
|
||||||
echo -e "${TAB}${YW}⚠️ Wait 2-3 minutes for installation to complete${CL}"
|
|
||||||
echo -e "${TAB}${YW}⚠️ Check progress: ${BL}cat /var/log/install-docker.log${CL}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$USE_CLOUD_INIT" = "yes" ]; then
|
|
||||||
display_cloud_init_info "$VMID" "$HN" 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
post_update_to_api "done" "none"
|
post_update_to_api "done" "none"
|
||||||
msg_ok "Completed successfully!\n"
|
msg_ok "Completed successfully!\n"
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
____ __
|
|
||||||
/ __ \____ _____/ /_____ _____
|
|
||||||
/ / / / __ \/ ___/ //_/ _ \/ ___/
|
|
||||||
/ /_/ / /_/ / /__/ ,< / __/ /
|
|
||||||
/_____/\____/\___/_/|_|\___/_/
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user