Compare commits

..

22 Commits

Author SHA1 Message Date
7289c68399 Update CHANGELOG.md (#5478)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-26 01:16:06 +01:00
4a5ddc8410 Update versions.json (#5477)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-26 02:15:17 +02:00
93808fbd75 Update CHANGELOG.md (#5471)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-25 19:42:32 +01:00
24394a0947 Update CHANGELOG.md (#5470)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-25 19:40:52 +01:00
4676eb616c Website: mark VM's and "OS"-LXC's as updatable (#5453) 2025-06-25 20:40:33 +02:00
e9ae558c25 Update CHANGELOG.md (#5469)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-25 19:39:54 +01:00
afee37794b Update CHANGELOG.md (#5468)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-25 19:39:39 +01:00
72e7bda418 Enhance InstallCommand component to support Gitea as an alternative source for installation scripts. Added informational alert for Gitea usage and refactored command generation logic to accommodate the new option. (#5464) 2025-06-25 20:39:26 +02:00
69e14c8fca Update Tooltips component to conditionally display updateable status based on item type (#5461) 2025-06-25 20:39:02 +02:00
6394c0cf17 Update CHANGELOG.md (#5467)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-25 19:35:45 +01:00
d1deffb235 Refactor CommandMenu to prevent duplicate scripts across categories (#5463) 2025-06-25 20:35:17 +02:00
ac885f8adb Update CHANGELOG.md (#5466)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-25 17:04:25 +01:00
8d91a5df5f Fix Apt-Cacher Issue with CAT 2025-06-25 18:03:54 +02:00
5ad9323944 Docmost: Increase resources (#5458)
* Update docmost.sh

* Update docmost.json
2025-06-25 14:25:17 +02:00
559bf61c31 Update versions.json (#5459)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-25 14:07:52 +02:00
3a391c34fc Update CHANGELOG.md (#5457)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-25 11:39:00 +01:00
332a96ea03 Update CHANGELOG.md (#5456)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-25 11:38:10 +01:00
454c574d38 tools.func: new helper for imagemagick (#5452) 2025-06-25 12:37:15 +02:00
2512c828e7 Update CHANGELOG.md (#5455)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-25 11:37:04 +01:00
a99ecb60ef refactor tailscale script & remove debian 12 note (#5454) 2025-06-25 12:36:15 +02:00
24f22dfecc Update CHANGELOG.md (#5451)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-25 10:01:49 +01:00
8521e2389b YunoHost: add Update-Funtion (#5450) 2025-06-25 11:01:11 +02:00
13 changed files with 431 additions and 235 deletions

View File

@ -14,8 +14,40 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
All LXC instances created using this repository come pre-installed with Midnight Commander, which is a command-line tool (`mc`) that offers a user-friendly file and directory management interface for the terminal environment.
## 2025-06-26
## 2025-06-25
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Docmost: Increase resources [@tremor021](https://github.com/tremor021) ([#5458](https://github.com/community-scripts/ProxmoxVE/pull/5458))
- #### ✨ New Features
- tools.func: new helper for imagemagick [@MickLesk](https://github.com/MickLesk) ([#5452](https://github.com/community-scripts/ProxmoxVE/pull/5452))
- YunoHost: add Update-Function [@MickLesk](https://github.com/MickLesk) ([#5450](https://github.com/community-scripts/ProxmoxVE/pull/5450))
- #### 🔧 Refactor
- Refactor: Tailscale [@MickLesk](https://github.com/MickLesk) ([#5454](https://github.com/community-scripts/ProxmoxVE/pull/5454))
### 🌐 Website
- #### 🐞 Bug Fixes
- Update Tooltips component to conditionally display updateable status based on item type [@BramSuurdje](https://github.com/BramSuurdje) ([#5461](https://github.com/community-scripts/ProxmoxVE/pull/5461))
- Refactor CommandMenu to prevent duplicate scripts across categories [@BramSuurdje](https://github.com/BramSuurdje) ([#5463](https://github.com/community-scripts/ProxmoxVE/pull/5463))
- #### ✨ New Features
- Enhance InstallCommand component to support Gitea as an alternative source for installation scripts. [@BramSuurdje](https://github.com/BramSuurdje) ([#5464](https://github.com/community-scripts/ProxmoxVE/pull/5464))
- #### 📝 Script Information
- Website: mark VM's and "OS"-LXC's as updatable [@MickLesk](https://github.com/MickLesk) ([#5453](https://github.com/community-scripts/ProxmoxVE/pull/5453))
## 2025-06-24
### 🆕 New Scripts

View File

@ -8,8 +8,8 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
APP="Docmost"
var_tags="${var_tags:-documents}"
var_cpu="${var_cpu:-3}"
var_ram="${var_ram:-3072}"
var_disk="${var_disk:-7}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"

View File

@ -20,18 +20,24 @@ color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/apt/trusted.gpg.d/php.gpg ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating $APP LXC"
$STD apt-get update
$STD apt-get -y upgrade
msg_ok "Updated $APP LXC"
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/apt/trusted.gpg.d/php.gpg ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating OS"
$STD apt-get update
$STD apt-get -y upgrade
msg_ok "Updated OS"
msg_info "Updating $APP LXC"
$STD yunohost tools update
$STD yunohost tools upgrade system
$STD yunohost tools upgrade apps
msg_ok "Updated $APP LXC"
exit
}
start
@ -41,4 +47,4 @@ 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}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"

View File

@ -32,10 +32,6 @@
"password": null
},
"notes": [
{
"text": "Only supported on Debian 12 LXCs",
"type": "warning"
},
{
"text": "After the script finishes, reboot the LXC then run `tailscale up` in the LXC console",
"type": "info"

View File

@ -20,8 +20,8 @@
"script": "ct/docmost.sh",
"resources": {
"cpu": 3,
"ram": 3072,
"hdd": 7,
"ram": 4096,
"hdd": 8,
"os": "debian",
"version": "12"
}

View File

@ -1,18 +1,108 @@
[
{
"name": "mongodb/mongo",
"version": "r8.1.2-rc1",
"date": "2025-06-25T22:42:04Z"
},
{
"name": "rcourtman/Pulse",
"version": "v3.32.0",
"date": "2025-06-25T22:27:01Z"
},
{
"name": "gristlabs/grist-core",
"version": "v1.6.1",
"date": "2025-06-25T21:19:25Z"
},
{
"name": "coder/code-server",
"version": "v4.101.2",
"date": "2025-06-25T21:18:52Z"
},
{
"name": "msgbyte/tianji",
"version": "v1.22.4",
"date": "2025-06-25T20:46:20Z"
},
{
"name": "meilisearch/meilisearch",
"version": "prototype-tmp-failing-upgrade-0",
"date": "2025-06-25T19:51:55Z"
},
{
"name": "home-assistant/core",
"version": "2025.6.3",
"date": "2025-06-24T13:00:12Z"
},
{
"name": "firefly-iii/firefly-iii",
"version": "v6.2.18",
"date": "2025-06-20T04:45:37Z"
},
{
"name": "ollama/ollama",
"version": "v0.9.4-citest0",
"date": "2025-06-25T17:44:00Z"
},
{
"name": "influxdata/influxdb",
"version": "v3.2.0",
"date": "2025-06-25T17:31:48Z"
},
{
"name": "wavelog/wavelog",
"version": "2.0.5",
"date": "2025-06-25T14:53:31Z"
},
{
"name": "jenkinsci/jenkins",
"version": "jenkins-2.504.3",
"date": "2025-06-25T14:43:01Z"
},
{
"name": "bunkerity/bunkerweb",
"version": "testing",
"date": "2025-06-16T18:10:42Z"
},
{
"name": "cockpit-project/cockpit",
"version": "341",
"date": "2025-06-25T11:49:28Z"
},
{
"name": "nzbgetcom/nzbget",
"version": "v25.0",
"date": "2025-05-12T09:12:04Z"
},
{
"name": "mattermost/mattermost",
"version": "v9.11.17",
"date": "2025-06-18T08:12:05Z"
},
{
"name": "n8n-io/n8n",
"version": "n8n@1.100.0",
"date": "2025-06-23T12:48:35Z"
},
{
"name": "Jackett/Jackett",
"version": "v0.22.2054",
"date": "2025-06-25T05:54:03Z"
},
{
"name": "moghtech/komodo",
"version": "v1.18.4",
"date": "2025-06-25T00:06:56Z"
},
{
"name": "duplicati/duplicati",
"version": "v2.1.0.120-2.1.0.120_canary_2025-06-24",
"date": "2025-06-24T22:39:50Z"
},
{
"name": "jenkinsci/jenkins",
"version": "jenkins-2.516",
"date": "2025-06-24T21:06:15Z"
},
{
"name": "ollama/ollama",
"version": "v0.9.3-rc1",
"date": "2025-06-24T20:26:55Z"
"name": "keycloak/keycloak",
"version": "26.2.5",
"date": "2025-05-28T06:49:43Z"
},
{
"name": "evcc-io/evcc",
@ -39,56 +129,26 @@
"version": "v2.37.3",
"date": "2025-06-24T14:05:33Z"
},
{
"name": "influxdata/influxdb",
"version": "v3.2.0",
"date": "2025-06-24T13:20:53Z"
},
{
"name": "Checkmk/checkmk",
"version": "v2.4.0p5",
"date": "2025-06-24T13:06:53Z"
},
{
"name": "home-assistant/core",
"version": "2025.6.3",
"date": "2025-06-24T13:00:12Z"
},
{
"name": "rcourtman/Pulse",
"version": "v3.31.2",
"date": "2025-06-24T09:45:34Z"
},
{
"name": "fallenbagel/jellyseerr",
"version": "preview-fix-proxy-axios",
"date": "2025-06-24T08:50:22Z"
},
{
"name": "Jackett/Jackett",
"version": "v0.22.2052",
"date": "2025-06-24T05:59:30Z"
},
{
"name": "wazuh/wazuh",
"version": "coverity-w26-4.13.0",
"date": "2025-06-24T02:02:34Z"
},
{
"name": "meilisearch/meilisearch",
"version": "prototype-incremental-vector-store-1",
"date": "2025-06-23T21:37:47Z"
},
{
"name": "minio/minio",
"version": "RELEASE.2025-06-13T11-33-47Z",
"date": "2025-06-23T20:58:42Z"
},
{
"name": "keycloak/keycloak",
"version": "26.2.5",
"date": "2025-05-28T06:49:43Z"
},
{
"name": "esphome/esphome",
"version": "2025.6.1",
@ -104,26 +164,11 @@
"version": "pmm-6401-v1.120.0",
"date": "2025-06-23T15:12:12Z"
},
{
"name": "n8n-io/n8n",
"version": "n8n@1.98.2",
"date": "2025-06-18T18:20:16Z"
},
{
"name": "Graylog2/graylog2-server",
"version": "6.3.0-rc.2",
"date": "2025-06-23T11:31:38Z"
},
{
"name": "mattermost/mattermost",
"version": "v9.11.17",
"date": "2025-06-18T08:12:05Z"
},
{
"name": "firefly-iii/firefly-iii",
"version": "v6.2.18",
"date": "2025-06-20T04:45:37Z"
},
{
"name": "gotson/komga",
"version": "1.22.0",
@ -149,11 +194,6 @@
"version": "v1.4.1",
"date": "2025-06-22T19:38:08Z"
},
{
"name": "msgbyte/tianji",
"version": "v1.22.3",
"date": "2025-06-22T18:29:00Z"
},
{
"name": "clusterzx/paperless-ai",
"version": "v3.0.7",
@ -204,11 +244,6 @@
"version": "0.50.4",
"date": "2025-06-21T07:47:02Z"
},
{
"name": "coder/code-server",
"version": "v4.101.1",
"date": "2025-06-21T02:47:08Z"
},
{
"name": "go-gitea/gitea",
"version": "v1.24.2",
@ -229,26 +264,11 @@
"version": "v1.25.0",
"date": "2025-06-20T19:15:43Z"
},
{
"name": "mongodb/mongo",
"version": "r8.1.2-rc0",
"date": "2025-06-20T17:35:38Z"
},
{
"name": "nzbgetcom/nzbget",
"version": "v25.0",
"date": "2025-05-12T09:12:04Z"
},
{
"name": "Sonarr/Sonarr",
"version": "v4.0.15.2941",
"date": "2025-06-20T17:20:54Z"
},
{
"name": "bunkerity/bunkerweb",
"version": "testing",
"date": "2025-06-16T18:10:42Z"
},
{
"name": "zabbix/zabbix",
"version": "7.2.9",
@ -424,11 +444,6 @@
"version": "15.2",
"date": "2025-04-14T15:37:12Z"
},
{
"name": "moghtech/komodo",
"version": "v1.18.3",
"date": "2025-06-16T07:03:46Z"
},
{
"name": "jellyfin/jellyfin",
"version": "v10.10.7",
@ -649,11 +664,6 @@
"version": "v4.1.1",
"date": "2025-06-04T19:10:05Z"
},
{
"name": "cockpit-project/cockpit",
"version": "340",
"date": "2025-06-04T16:41:44Z"
},
{
"name": "intri-in/manage-my-damn-life-nextjs",
"version": "v0.7.1",
@ -714,11 +724,6 @@
"version": "0.26.3",
"date": "2025-05-29T21:18:15Z"
},
{
"name": "gristlabs/grist-core",
"version": "v1.6.0",
"date": "2025-05-29T19:11:21Z"
},
{
"name": "navidrome/navidrome",
"version": "v0.56.1",
@ -824,11 +829,6 @@
"version": "v1.1.1",
"date": "2025-05-17T10:10:36Z"
},
{
"name": "wavelog/wavelog",
"version": "2.0.4",
"date": "2025-05-16T15:09:53Z"
},
{
"name": "Dolibarr/dolibarr",
"version": "18.0.7",

View File

@ -1,40 +1,40 @@
{
"name": "YunoHost",
"slug": "yunohost",
"categories": [
2
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": false,
"privileged": false,
"interface_port": 80,
"documentation": null,
"website": "https://yunohost.org/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/yunohost.webp",
"config_path": "",
"description": "YunoHost is an operating system aiming for the simplest administration of a server, and therefore democratize self-hosting, while making sure it stays reliable, secure, ethical and lightweight.",
"install_methods": [
{
"type": "default",
"script": "ct/yunohost.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 20,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "WARNING: Installation sources scripts outside of Community Scripts repo. Please check the source before installing.",
"type": "warning"
}
]
"name": "YunoHost",
"slug": "yunohost",
"categories": [
2
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 80,
"documentation": null,
"website": "https://yunohost.org/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/yunohost.webp",
"config_path": "",
"description": "YunoHost is an operating system aiming for the simplest administration of a server, and therefore democratize self-hosting, while making sure it stays reliable, secure, ethical and lightweight.",
"install_methods": [
{
"type": "default",
"script": "ct/yunohost.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 20,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "WARNING: Installation sources scripts outside of Community Scripts repo. Please check the source before installing.",
"type": "warning"
}
]
}

View File

@ -1,17 +1,20 @@
import CodeCopyButton from "@/components/ui/code-copy-button";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Info } from "lucide-react";
import { basePath } from "@/config/siteConfig";
import { Script } from "@/lib/types";
import { getDisplayValueFromType } from "../ScriptInfoBlocks";
const getInstallCommand = (scriptPath = "", isAlpine = false) => {
const url = `https://raw.githubusercontent.com/community-scripts/${basePath}/main/${scriptPath}`;
return isAlpine ? `bash -c "$(curl -fsSL ${url})"` : `bash -c "$(curl -fsSL ${url})"`;
const getInstallCommand = (scriptPath = "", isAlpine = false, useGitea = false) => {
const githubUrl = `https://raw.githubusercontent.com/community-scripts/${basePath}/main/${scriptPath}`;
const giteaUrl = `https://git.community-scripts.org/community-scripts/${basePath}/raw/branch/main/${scriptPath}`;
const url = useGitea ? giteaUrl : githubUrl;
return `bash -c "$(curl -fsSL ${url})"`;
};
export default function InstallCommand({ item }: { item: Script }) {
const alpineScript = item.install_methods.find((method) => method.type === "alpine");
const defaultScript = item.install_methods.find((method) => method.type === "default");
const renderInstructions = (isAlpine = false) => (
@ -49,9 +52,20 @@ export default function InstallCommand({ item }: { item: Script }) {
</>
);
return (
<div className="p-4">
{alpineScript ? (
const renderGiteaInfo = () => (
<Alert className="mt-3 mb-3">
<Info className="h-4 w-4" />
<AlertDescription className="text-sm">
<strong>When to use Gitea:</strong> GitHub may have issues including slow connections, delayed updates after bug
fixes, no IPv6 support, API rate limits (60/hour). Use our Gitea mirror as a reliable alternative when
experiencing these issues.
</AlertDescription>
</Alert>
);
const renderScriptTabs = (useGitea = false) => {
if (alpineScript) {
return (
<Tabs defaultValue="default" className="mt-2 w-full max-w-4xl">
<TabsList>
<TabsTrigger value="default">Default</TabsTrigger>
@ -59,19 +73,40 @@ export default function InstallCommand({ item }: { item: Script }) {
</TabsList>
<TabsContent value="default">
{renderInstructions()}
<CodeCopyButton>{getInstallCommand(defaultScript?.script)}</CodeCopyButton>
<CodeCopyButton>{getInstallCommand(defaultScript?.script, false, useGitea)}</CodeCopyButton>
</TabsContent>
<TabsContent value="alpine">
{renderInstructions(true)}
<CodeCopyButton>{getInstallCommand(alpineScript.script, true)}</CodeCopyButton>
<CodeCopyButton>{getInstallCommand(alpineScript.script, true, useGitea)}</CodeCopyButton>
</TabsContent>
</Tabs>
) : defaultScript?.script ? (
);
} else if (defaultScript?.script) {
return (
<>
{renderInstructions()}
<CodeCopyButton>{getInstallCommand(defaultScript.script)}</CodeCopyButton>
<CodeCopyButton>{getInstallCommand(defaultScript.script, false, useGitea)}</CodeCopyButton>
</>
) : null}
);
}
return null;
};
return (
<div className="p-4">
<Tabs defaultValue="github" className="w-full max-w-4xl">
<TabsList>
<TabsTrigger value="github">GitHub</TabsTrigger>
<TabsTrigger value="gitea">Gitea</TabsTrigger>
</TabsList>
<TabsContent value="github">
{renderScriptTabs(false)}
</TabsContent>
<TabsContent value="gitea">
{renderGiteaInfo()}
{renderScriptTabs(true)}
</TabsContent>
</Tabs>
</div>
);
}
}

View File

@ -34,14 +34,14 @@ export default function Tooltips({ item }: { item: Script }) {
{item.privileged && (
<TooltipBadge variant="warning" label="Privileged" content="This script will be run in a privileged LXC" />
)}
{item.updateable && (
{(item.updateable || item.type !== "pve") && (
<TooltipBadge
variant="success"
label="Updateable"
content={`To Update ${item.name}, run the command below (or type update) in the LXC Console.`}
/>
)}
{!item.updateable && <TooltipBadge variant="failure" label="Not Updateable" />}
{!item.updateable && item.type !== "pve" && <TooltipBadge variant="failure" label="Not Updateable" />}
</div>
);
}

View File

@ -134,34 +134,54 @@ export default function CommandMenu() {
<CommandInput placeholder="Search for a script..." />
<CommandList>
<CommandEmpty>{isLoading ? "Loading..." : "No scripts found."}</CommandEmpty>
{links.map((category) => (
<CommandGroup key={`category:${category.name}`} heading={category.name}>
{category.scripts.map((script) => (
<CommandItem
key={`script:${script.slug}`}
value={`${script.slug}-${script.name}`}
onSelect={() => {
setOpen(false);
router.push(`/scripts?id=${script.slug}`);
}}
>
<div className="flex gap-2" onClick={() => setOpen(false)}>
<Image
src={script.logo || `/${basePath}/logo.png`}
onError={(e) => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)}
unoptimized
width={16}
height={16}
alt=""
className="h-5 w-5"
/>
<span>{script.name}</span>
<span>{formattedBadge(script.type)}</span>
</div>
</CommandItem>
))}
</CommandGroup>
))}
{(() => {
// Track seen scripts globally to avoid duplicates across all categories
const globalSeenScripts = new Set<string>();
return links.map((category) => {
const uniqueScripts = category.scripts.filter((script) => {
if (globalSeenScripts.has(script.slug)) {
return false;
}
globalSeenScripts.add(script.slug);
return true;
});
// Only render category if it has unique scripts
if (uniqueScripts.length === 0) {
return null;
}
return (
<CommandGroup key={`category:${category.name}`} heading={category.name}>
{uniqueScripts.map((script) => (
<CommandItem
key={`script:${script.slug}`}
value={`${script.slug}-${script.name}`}
onSelect={() => {
setOpen(false);
router.push(`/scripts?id=${script.slug}`);
}}
>
<div className="flex gap-2" onClick={() => setOpen(false)}>
<Image
src={script.logo || `/${basePath}/logo.png`}
onError={(e) => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)}
unoptimized
width={16}
height={16}
alt=""
className="h-5 w-5"
/>
<span>{script.name}</span>
<span>{formattedBadge(script.type)}</span>
</div>
</CommandItem>
))}
</CommandGroup>
);
});
})()}
</CommandList>
</CommandDialog>
</>

View File

@ -128,7 +128,7 @@ update_os() {
msg_info "Updating Container OS"
if [[ "$CACHER" == "yes" ]]; then
echo "Acquire::http::Proxy-Auto-Detect \"/usr/local/bin/apt-proxy-detect.sh\";" >/etc/apt/apt.conf.d/00aptproxy
cat <<EOF >/usr/local/bin/apt-proxy-detect.sh
cat <<'EOF' >/usr/local/bin/apt-proxy-detect.sh
#!/bin/bash
if nc -w1 -z "${CACHER_IP}" 3142; then
echo -n "http://${CACHER_IP}:3142"

View File

@ -1538,3 +1538,73 @@ function setup_yq() {
msg_error "yq installation incomplete or version mismatch"
fi
}
# ------------------------------------------------------------------------------
# Installs ImageMagick 7 from source (Debian/Ubuntu only).
#
# Description:
# - Downloads the latest ImageMagick source tarball
# - Builds and installs ImageMagick to /usr/local
# - Configures dynamic linker (ldconfig)
#
# Notes:
# - Requires: build-essential, libtool, libjpeg-dev, libpng-dev, etc.
# ------------------------------------------------------------------------------
function setup_imagemagick() {
local TMP_DIR
TMP_DIR=$(mktemp -d)
local VERSION=""
local BINARY_PATH="/usr/local/bin/magick"
if command -v magick &>/dev/null; then
VERSION=$(magick -version | awk '/^Version/ {print $3}')
msg_ok "ImageMagick already installed ($VERSION)"
return 0
fi
msg_info "Setup ImageMagick (Patience)"
$STD apt-get update
$STD apt-get install -y \
build-essential \
libtool \
libjpeg-dev \
libpng-dev \
libtiff-dev \
libwebp-dev \
libheif-dev \
libde265-dev \
libopenjp2-7-dev \
libxml2-dev \
liblcms2-dev \
libfreetype6-dev \
libraw-dev \
libfftw3-dev \
liblqr-1-0-dev \
libgsl-dev \
pkg-config \
ghostscript
curl -fsSL https://imagemagick.org/archive/ImageMagick.tar.gz -o "$TMP_DIR/ImageMagick.tar.gz"
tar -xzf "$TMP_DIR/ImageMagick.tar.gz" -C "$TMP_DIR"
cd "$TMP_DIR"/ImageMagick-* || {
msg_error "Source extraction failed"
rm -rf "$TMP_DIR"
return 1
}
./configure --disable-static >/dev/null
$STD make
$STD make install
$STD ldconfig /usr/local/lib
if [[ ! -x "$BINARY_PATH" ]]; then
msg_error "ImageMagick installation failed"
rm -rf "$TMP_DIR"
return 1
fi
VERSION=$("$BINARY_PATH" -version | awk '/^Version/ {print $3}')
rm -rf "$TMP_DIR"
ensure_usr_local_bin_persist
msg_ok "Setup ImageMagick $VERSION"
}

View File

@ -2,10 +2,12 @@
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
function header_info {
set -Eeuo pipefail
trap 'echo -e "\n[ERROR] in line $LINENO: exit code $?"' ERR
function header_info() {
clear
cat <<"EOF"
______ _ __ __
@ -16,60 +18,95 @@ function header_info {
EOF
}
function msg_info() { echo -e " \e[1;36m➤\e[0m $1"; }
function msg_ok() { echo -e " \e[1;32m✔\e[0m $1"; }
function msg_error() { echo -e " \e[1;31m✖\e[0m $1"; }
header_info
set -e
if ! command -v pveversion &>/dev/null; then
msg_error "This script must be run on the Proxmox VE host (not inside an LXC container)"
exit 1
fi
while true; do
read -p "This will add Tailscale to an existing LXC Container ONLY. Proceed(y/n)?" yn
case $yn in
read -rp "This will add Tailscale to an existing LXC Container ONLY. Proceed (y/n)? " yn
case "$yn" in
[Yy]*) break ;;
[Nn]*) exit ;;
[Nn]*) exit 0 ;;
*) echo "Please answer yes or no." ;;
esac
done
header_info
echo "Loading..."
function msg() {
local TEXT="$1"
echo -e "$TEXT"
}
msg_info "Loading container list..."
NODE=$(hostname)
MSG_MAX_LENGTH=0
CTID_MENU=()
while read -r line; do
TAG=$(echo "$line" | awk '{print $1}')
ITEM=$(echo "$line" | awk '{print substr($0,36)}')
OFFSET=2
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
fi
CTID_MENU+=("$TAG" "$ITEM " "OFF")
((${#ITEM} + OFFSET > MSG_MAX_LENGTH)) && MSG_MAX_LENGTH=$((${#ITEM} + OFFSET))
CTID_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pct list | awk 'NR>1')
while [ -z "${CTID:+x}" ]; do
CTID=""
while [[ -z "${CTID}" ]]; do
CTID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Containers on $NODE" --radiolist \
"\nSelect a container to add Tailscale to:\n" \
16 $(($MSG_MAX_LENGTH + 23)) 6 \
"${CTID_MENU[@]}" 3>&1 1>&2 2>&3)
16 $((MSG_MAX_LENGTH + 23)) 6 \
"${CTID_MENU[@]}" 3>&1 1>&2 2>&3) || exit 1
done
CTID_CONFIG_PATH=/etc/pve/lxc/${CTID}.conf
cat <<EOF >>$CTID_CONFIG_PATH
lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
EOF
CTID_CONFIG_PATH="/etc/pve/lxc/${CTID}.conf"
# Skip if already configured
grep -q "lxc.cgroup2.devices.allow: c 10:200 rwm" "$CTID_CONFIG_PATH" || echo "lxc.cgroup2.devices.allow: c 10:200 rwm" >>"$CTID_CONFIG_PATH"
grep -q "lxc.mount.entry: /dev/net/tun" "$CTID_CONFIG_PATH" || echo "lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file" >>"$CTID_CONFIG_PATH"
header_info
msg "Installing Tailscale..."
msg_info "Installing Tailscale in CT $CTID"
pct exec "$CTID" -- bash -c '
set -e
export DEBIAN_FRONTEND=noninteractive
ID=$(grep "^ID=" /etc/os-release | cut -d"=" -f2)
VER=$(grep "^VERSION_CODENAME=" /etc/os-release | cut -d"=" -f2)
curl -fsSL https://pkgs.tailscale.com/stable/$ID/$VER.noarmor.gpg | tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/tailscale-archive-keyring.gpg] https://pkgs.tailscale.com/stable/$ID $VER main" >/etc/apt/sources.list.d/tailscale.list
apt-get update &>/dev/null
apt-get install -y tailscale &>/dev/null
'
TAGS=$(awk -F': ' '/^tags:/ {print $2}' /etc/pve/lxc/${CTID}.conf)
TAGS="${TAGS:+$TAGS; }tailscale"
pct set "$CTID" -tags "${TAGS}"
msg "\e[1;32m ✔ Installed Tailscale\e[0m"
msg "\e[1;31m Reboot ${CTID} LXC to apply the changes, then run tailscale up in the LXC console\e[0m"
# fallback if DNS is poisoned or blocked
ORIG_RESOLV="/etc/resolv.conf"
BACKUP_RESOLV="/tmp/resolv.conf.backup"
if ! dig +short pkgs.tailscale.com | grep -qvE "^127\.|^0\.0\.0\.0$"; then
echo "[INFO] DNS resolution for pkgs.tailscale.com failed (blocked or redirected)."
echo "[INFO] Temporarily overriding /etc/resolv.conf with Cloudflare DNS (1.1.1.1)"
cp "$ORIG_RESOLV" "$BACKUP_RESOLV"
echo "nameserver 1.1.1.1" >"$ORIG_RESOLV"
fi
curl -fsSL https://pkgs.tailscale.com/stable/${ID}/${VER}.noarmor.gpg \
| tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/tailscale-archive-keyring.gpg] https://pkgs.tailscale.com/stable/${ID} ${VER} main" \
>/etc/apt/sources.list.d/tailscale.list
apt-get update -qq
apt-get install -y tailscale >/dev/null
if [[ -f /tmp/resolv.conf.backup ]]; then
echo "[INFO] Restoring original /etc/resolv.conf"
mv /tmp/resolv.conf.backup /etc/resolv.conf
fi
'
TAGS=$(awk -F': ' '/^tags:/ {print $2}' "$CTID_CONFIG_PATH")
TAGS="${TAGS:+$TAGS; }tailscale"
pct set "$CTID" -tags "$TAGS"
msg_ok "Tailscale installed on CT $CTID"
msg_info "Reboot the container, then run 'tailscale up' inside the container to activate."