Compare commits

..

20 Commits

Author SHA1 Message Date
fc303669e3 update build.func 2025-02-07 08:56:21 +01:00
7974bfdddb update build.func 2025-02-03 11:56:30 +01:00
47ac39423c update build.func 2025-02-03 11:55:31 +01:00
3e189531c6 update build.func 2025-02-03 11:51:49 +01:00
451e6e31e2 update build.func 2025-02-03 11:51:26 +01:00
f6c263b703 update build.func 2025-02-03 11:44:37 +01:00
73e814101f update build.func 2025-02-03 11:42:01 +01:00
82c4c2cca7 update build.func 2025-02-03 11:28:36 +01:00
a4d4e99505 Update build.func 2025-02-03 11:00:34 +01:00
3277749f82 Update build.func 2025-02-03 10:33:44 +01:00
50a7fe1021 update build.func 2025-01-21 15:47:17 +01:00
78d92e980e update build.func 2025-01-21 15:42:34 +01:00
6e233c6c70 update build.func 2025-01-21 15:40:17 +01:00
75c5eeba44 Add input sanity checking 2025-01-21 13:47:20 +01:00
dffa262b88 Add input sanity checking 2025-01-21 13:46:29 +01:00
d1ff5356ad update build.func 2025-01-21 13:42:26 +01:00
ba9d392a88 update build.func 2025-01-21 13:34:54 +01:00
cb06a58b18 Update build.func 2025-01-21 13:05:00 +01:00
986c6810de Update build.func 2025-01-21 13:04:42 +01:00
af41a3bebd Feat: Config File 2025-01-21 13:02:23 +01:00
1584 changed files with 17955 additions and 48713 deletions

BIN
.gitattributes vendored

Binary file not shown.

View File

@ -2,7 +2,6 @@
# Community Scripts Contribution Guide
## **Welcome to the communty-scripts Repository!**
📜 These documents outline the essential coding standards for all our scripts and JSON files. Adhering to these standards ensures that our codebase remains consistent, readable, and maintainable. By following these guidelines, we can improve collaboration, reduce errors, and enhance the overall quality of our project.
### Why Coding Standards Matter
@ -20,7 +19,7 @@ These documents cover the coding standards for the following types of files in o
- **`install/$AppName-install.sh` Scripts**: These scripts are responsible for the installation of applications.
- **`ct/$AppName.sh` Scripts**: These scripts handle the creation and updating of containers.
- **`frontend/public/json/$AppName.json`**: These files store structured data and are used for the website.
- **`json/$AppName.json`**: These files store structured data and are used for the website.
Each section provides detailed guidelines on various aspects of coding, including shebang usage, comments, variable naming, function naming, indentation, error handling, command substitution, quoting, script structure, and logging. Additionally, examples are provided to illustrate the application of these standards.
@ -40,38 +39,32 @@ Before contributing, please ensure that you have the following setup:
- [Shell Format](https://marketplace.visualstudio.com/items?itemName=foxundermoon.shell-format)
### Important Notes
- Use [AppName.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh) and [AppName-install.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh) as templates when creating new scripts. Final version of the script (the one you will push for review), must have all comments removed, except the ones in the file header.
- Use [AppName.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/ct/AppName.sh) and [AppName-install.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/install/AppName-install.sh) as templates when creating new scripts.
---
# 🚀 The Application Script (ct/AppName.sh)
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md).
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/ct/AppName.md).
- These scripts are responsible for container creation, setting the necessary variables and handling the update of the application once installed.
---
# 🛠 The Installation Script (install/AppName-install.sh)
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.md).
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/install/AppName-install.md).
- These scripts are responsible for the installation of the application.
---
## 🚀 Building Your Own Scripts
Start with the [template script](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh)
Start with the [template script](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/install/AppName-install.sh)
---
## 🤝 Contribution Process
All PR's related to new scripts should be made against our Dev repository first, where we can test the scripts before they are pushed and merged in the official repository.
**Our Dev repo is `http://www.github.com/community-scripts/ProxmoxVED`**
You will need to adjust paths mentioned further down this document to match the repo you're pushing the scripts to.
### 1. Fork the repository
Fork to your GitHub account
@ -86,24 +79,7 @@ git switch -c your-feature-branch
```
### 4. Change paths in build.func install.func and AppName.sh
To be able to develop from your own branch you need to change:\
`https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main`\
to\
`https://raw.githubusercontent.com/[USER]/[REPOSITORY]/refs/heads/[BRANCH]`\
in following files:
`misc/build.func`\
`misc/install.func`\
`ct/AppName.sh`
Example: `https://raw.githubusercontent.com/tremor021/PromoxVE/refs/heads/testbranch`
Also you need to change:\
`https://raw.githubusercontent.com/community-scripts/ProxmoxVE/raw/main`\
to\
`https://raw.githubusercontent.com/[USER]/[REPOSITORY]/raw/[BRANCH]`\
in `misc/install.func` in order for `update` shell command to work.\
These changes are only while writing and testing your scripts. Before opening a Pull Request, you should change all above mentioned paths in `misc/build.func`, `misc/install.func` and `ct/AppName.sh` to point to the original paths.
To be able to develop from your own branch you need to change `https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file` to `https://raw.githubusercontent.com/[USER]/[REPOSITORY]/refs/head/[BRANCH]`. You need to make this change atleast in misc/build.func misc/install.func and in your ct/AppName.sh. This change is only for testing. Before opening a Pull Request you should change this line change all this back to point to `https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file`.
### 4. Commit changes (without build.func and install.func!)
```bash
@ -116,14 +92,14 @@ git push origin your-feature-branch
```
### 6. Create a Pull Request
Open a Pull Request from your feature branch to the main branch on the Dev repository. You must only include your **$AppName.sh**, **$AppName-install.sh** and **$AppName.json** files in the pull request.
Open a Pull Request from your feature branch to the main repository branch. You must only include your **$AppName.sh**, **$AppName-install.sh** and **$AppName.json** files in the pull request.
---
## 📚 Pages
- [CT Template: AppName.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh)
- [Install Template: AppName-install.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh)
- [JSON Template: AppName.json](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/json/AppName.json)
- [CT Template: AppName.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/ct/AppName.sh)
- [Install Template: AppName-install.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/install/AppName-install.sh)
- [JSON Template: AppName.json](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/json/AppName.json)

View File

@ -40,8 +40,8 @@
- Import the build.func file.
- When developing your own script, change the URL to your own repository.
> [!IMPORTANT]
> You also need to change all apperances of this URL in `misc/build.func` and `misc/install.func`
> [!CAUTION]
> Before opening a Pull Request, change the URL to point to the community-scripts repo.
Example for development:
@ -52,12 +52,9 @@ source <(curl -s https://raw.githubusercontent.com/[USER]/[REPO]/refs/heads/[BRA
Final script:
```bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
```
> [!CAUTION]
> Before opening a Pull Request, change the URLs to point to the community-scripts repo.
### 1.3 **Metadata**
- Add clear comments for script metadata, including author, copyright, and license information.
@ -75,7 +72,6 @@ Example:
>
> - Add your username and source URL
> - For existing scripts, add "| Co-Author [YourUserName]" after the current author
> - Source is a URL of github repo containting source files of the application you're installing (not URL of your homepage or a blog)
---
@ -96,7 +92,7 @@ Example:
>| Variable | Description | Notes |
>|----------|-------------|-------|
>| `APP` | Application name | Must match ct\AppName.sh |
>| `var_tags` | Proxmox display tags without Spaces, only ; | Limit the number to 2 |
>| `TAGS` | Proxmox display tags without Spaces, only ; | Limit the number |
>| `var_cpu` | CPU cores | Number of cores |
>| `var_ram` | RAM | In MB |
>| `var_disk` | Disk capacity | In GB |
@ -120,13 +116,18 @@ var_unprivileged="1"
## 2.2 **📋 App output & base settings**
```bash
# App Output & Base Settings
header_info "$APP"
base_settings
```
- `header_info`: Generates ASCII header for APP
- `base_settings`: Allows overwriting variable values
## 2.3 **🛠 Core functions**
```bash
# Core
variables
color
catch_errors
@ -167,7 +168,7 @@ if [[ ! -d /opt/snipe-it ]]; then
### 3.3 **Check version**
- Before updating, check if a new version exists.
- Befoer updating, check if a new version exists.
- We use the `${APPLICATION}_version.txt` file created in `/opt` during the install to compare new versions against the currently installed version.
Example with a Github Release:
@ -194,13 +195,13 @@ wget -q
unzip -q
```
- If a command does not come with this functionality use `$STD` to suppress it's output.
- If a command does not come with this functionality use `&>/dev/null` to suppress it's output.
Example:
```bash
$STD php artisan migrate --force
$STD php artisan config:clear
php artisan migrate --force &>/dev/null
php artisan config:clear &>/dev/null
```
### 3.5 **Backups**
@ -237,7 +238,7 @@ Example:
### 3.7 **No update function**
- In case you can not provide an update function use the following code to provide user feedback.
- In case you can not provide a update function use the following code to provide user feedback.
```bash
function update_script() {
@ -248,7 +249,7 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "Currently we don't provide an update function for this ${APP}."
msg_error "Ther is currently no automatic update function for ${APP}."
exit
}
```
@ -282,6 +283,6 @@ echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
- [ ] Metadata (author, license) is included at the top.
- [ ] Variables follow naming conventions.
- [ ] Update function exists.
- [ ] Update functions checks if app is installed and for new version.
- [ ] Update function cleans up temporary files.
- [ ] Update functions checks if app is installed an for new version.
- [ ] Update function up temporary files.
- [ ] Script ends with a helpful message for the user to reach the application.

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2024 community-scripts ORG
# Author: [YourUserName]
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: [SOURCE_URL]
@ -8,8 +8,8 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# App Default Values
APP="[APP_NAME]"
# Name of the app (e.g. Google, Adventurelog, Apache-Guacamole"
var_tags="[TAGS]"
# Tags for Proxmox VE, maximum 2 pcs., no spaces allowed, separated by a semicolon ; (e.g. database | adblock;dhcp)
TAGS="[TAGS]"
# Tags for Proxmox VE, maximum 2 pcs., no spaces allowed, separated by a semicolon ; (e.g. database | adblock;dhcp)
var_cpu="[CPU]"
# Number of cores (1-X) (e.g. 4) - default are 2
var_ram="[RAM]"
@ -23,7 +23,11 @@ var_version="[VERSION]"
var_unprivileged="[UNPRIVILEGED]"
# 1 = unprivileged container, 0 = privileged container
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -42,6 +46,8 @@ function update_script() {
# Crawling the new version and checking whether an update is required
RELEASE=$(curl -fsSL [RELEASE_URL] | [PARSE_RELEASE_COMMAND])
if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
msg_info "Updating $APP"
# Stopping Services
msg_info "Stopping $APP"
systemctl stop [SERVICE_NAME]
@ -60,6 +66,7 @@ function update_script() {
# Starting Services
msg_info "Starting $APP"
systemctl start [SERVICE_NAME]
sleep 2
msg_ok "Started $APP"
# Cleaning up
@ -83,4 +90,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}:[PORT]${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:[PORT]${CL}"

View File

@ -67,7 +67,6 @@ Example:
>
> - Add your username
> - When updating/reworking scripts, add "| Co-Author [YourUserName]"
> - Source is a URL of github repo containting source files of the application you're installing (not URL of your homepage or a blog)
### 1.3 **Variables and function import**
@ -111,8 +110,11 @@ Example:
```bash
$STD apt-get install -y \
curl \
composer \
git \
sudo \
mc \
nginx
```
@ -175,7 +177,6 @@ echo "${RELEASE}" >"/opt/AppName_version.txt"
- Use standard functions like `msg_info`, `msg_ok` or `msg_error` to print status messages.
- Each `msg_info` must be followed with a `msg_ok` before any other output is made.
- Display meaningful progress messages at key stages.
- Taking user input with `read -p` must be outside of `msg_info`...`msg_ok` code block
Example:
@ -183,8 +184,6 @@ Example:
msg_info "Installing Dependencies"
$STD apt-get install -y ...
msg_ok "Installed Dependencies"
read -p "${TAB3}Do you wish to enable HTTPS mode? (y/N): " httpschoice
```
### 6.2 **Verbosity**

View File

@ -1,8 +1,8 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Copyright (c) 2021-2024 community-scripts ORG
# Author: [YourUserName]
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# License: MIT
# Source: [SOURCE_URL]
# Import Functions und Setup
@ -14,9 +14,12 @@ setting_up_container
network_check
update_os
# Installing Dependencies
# Installing Dependencies with the 3 core dependencies (curl;sudo;mc)
msg_info "Installing Dependencies"
$STD apt-get install -y \
curl \
sudo \
mc \
[PACKAGE_1] \
[PACKAGE_2] \
[PACKAGE_3]
@ -42,10 +45,10 @@ msg_ok "Set up Database"
# Setup App
msg_info "Setup ${APPLICATION}"
RELEASE=$(curl -fsSL https://api.github.com/repos/[REPO]/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
curl -fsSL -o "${RELEASE}.zip" "https://github.com/[REPO]/archive/refs/tags/${RELEASE}.zip"
unzip -q "${RELEASE}.zip"
mv "${APPLICATION}-${RELEASE}/" "/opt/${APPLICATION}"
RELEASE=$(curl -s https://api.github.com/repos/[REPO]/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
wget -q "https://github.com/[REPO]/archive/refs/tags/${RELEASE}.zip"
unzip -q ${RELEASE}.zip
mv ${APPLICATION}-${RELEASE}/ /opt/${APPLICATION}
#
#
#
@ -66,7 +69,7 @@ Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now ${APPLICATION}
systemctl enable -q --now ${APPLICATION}.service
msg_ok "Created Service"
motd_ssh
@ -77,4 +80,7 @@ msg_info "Cleaning up"
rm -f ${RELEASE}.zip
$STD apt-get -y autoremove
$STD apt-get -y autoclean
msg_ok "Cleaned"
msg_ok "Cleaned"
motd_ssh
customize

View File

@ -12,7 +12,7 @@
"documentation": null,
"website": "LINK TO WEBSITE",
"logo": "LINK TO LOGO",
"description": "Description of the app",
"description": "Deescription of the app",
"install_methods": [
{
"type": "default",

View File

@ -1,4 +1,4 @@
title: "[Script request]: "
title: "[Script request] "
labels: ["enhancement"]
body:
- type: input
@ -30,6 +30,8 @@ body:
required: true
- label: "I have searched existing [discussions](https://github.com/community-scripts/ProxmoxVE/discussions?discussions_q=) and found no duplicate requests."
required: true
- label: "This is not a game-related request."
required: true
- type: markdown
attributes:
value: "Thanks for submitting your request! The team will review it and reach out if we need more information."

1
.github/FUNDING.yml vendored
View File

@ -1,2 +1 @@
ko_fi: community_scripts
github: community_scripts

View File

@ -1,19 +1,20 @@
name: "🐞 Script Issue Report"
description: Report a specific issue with a script. For other inquiries, please use the Discussions section.
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
# 🐞 **Script Issue Report**
Thank you for taking the time to report an issue! Please provide as much detail as possible to help us address the problem efficiently.
## ⚠️ **IMPORTANT - READ FIRST**
- 🔍 **Search first:** Before submitting, check if the issue has already been reported or resolved in [closed issues](https://github.com/community-scripts/ProxmoxVE/issues?q=is%3Aissue+is%3Aclosed). If found, comment on that issue instead of creating a new one.
Alternatively, check the **[Discussions](https://github.com/community-scripts/ProxmoxVE/discussions)** under the *"Announcement"* or *"Guide"* categories for relevant information.
- 🛠️ **Supported environments only:** Ensure you are using a default Linux distribution. Custom setups may not be supported.
- 🔎 If you encounter `[ERROR] in line 23: exit code *: while executing command "$@" > /dev/null 2>&1`, rerun the script with verbose mode before submitting the issue.
- 📜 **Read the script:** Familiarize yourself with the script's content and its purpose. This will help you understand the issue better and provide more relevant information
Thank you for taking the time to report an issue! Please provide as much detail as possible to help us address the problem efficiently.
- 💡 For general questions, feature requests, or suggestions, use the [Discussions section](https://github.com/community-scripts/ProxmoxVE/discussions).
- type: input
id: guidelines
attributes:
@ -34,7 +35,14 @@ body:
id: script_command
attributes:
label: 📂 What was the exact command used to execute the script?
placeholder: "e.g., bash -c \"$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/zigbee2mqtt.sh)\" or \"update\""
placeholder: "e.g., bash -c \"$(wget -qLO - https://github.com/community-scripts/ProxmoxVE/raw/main/ct/zigbee2mqtt.sh)\" or \"update\""
validations:
required: true
- type: textarea
id: issue_description
attributes:
label: 📝 Provide a clear and concise description of the issue.
validations:
required: true
@ -67,13 +75,6 @@ body:
validations:
required: true
- type: textarea
id: issue_description
attributes:
label: 📝 Provide a clear and concise description of the issue.
validations:
required: true
- type: textarea
id: steps_to_reproduce
attributes:

View File

@ -1,11 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: 🌟 new Script request
url: https://github.com/community-scripts/ProxmoxVE/discussions/new?category=request-script
about: For feature/script requests, please use the Discussions section.
- name: 🤔 Questions and Help
url: https://github.com/community-scripts/ProxmoxVE/discussions
about: For suggestions or questions, please use the Discussions section.
- name: 🌟 Feature request
url: https://github.com/community-scripts/ProxmoxVE/discussions/new?category=request-script
about: For feature/script requests, please use the Discussions section.
- name: 💻 Discord
url: https://discord.gg/jsYVk5JBxq
url: https://discord.gg/UHrpNWGwkH
about: Join our Discord server to chat with other users in the Proxmox Helper Scripts community.

View File

@ -1,33 +0,0 @@
name: "✨ Feature Request"
description: "Suggest a new feature or enhancement. (not for script requests)"
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
# ✨ **Feature Request**
Have an idea for a new feature? Share your thoughts below!
- type: input
id: feature_summary
attributes:
label: "🌟 Briefly describe the feature"
placeholder: "e.g., Add support for XYZ"
validations:
required: true
- type: textarea
id: feature_description
attributes:
label: "📝 Detailed description"
placeholder: "Explain the feature in detail"
validations:
required: true
- type: textarea
id: use_case
attributes:
label: "💡 Why is this useful?"
placeholder: "Describe the benefit of this feature"
validations:
required: true

View File

@ -1,25 +0,0 @@
name: "🛠️ Task / General Request"
description: "Request a general task, improvement, or refactor."
labels: ["task"]
body:
- type: markdown
attributes:
value: |
# 🛠️ **Task / General Request**
Request a task that isn't a bug or feature request.
- type: input
id: task_summary
attributes:
label: "📌 Task summary"
placeholder: "e.g., Refactor XYZ"
validations:
required: true
- type: textarea
id: task_details
attributes:
label: "📋 Task details"
placeholder: "Explain what needs to be done"
validations:
required: true

View File

@ -1,4 +1,17 @@
{
"breaking change": [
{
"fileStatus": "renamed",
"includeGlobs": ["ct/**", "install/**", "misc/**", "turnkey/**", "vm/**"],
"excludeGlobs": []
},
{
"fileStatus": "removed",
"includeGlobs": ["ct/**", "install/**", "misc/**", "turnkey/**", "vm/**"],
"excludeGlobs": []
}
],
"new script": [
{
"fileStatus": "added",
@ -10,80 +23,41 @@
{
"fileStatus": "modified",
"includeGlobs": ["ct/**", "install/**", "misc/**", "turnkey/**", "vm/**"],
"excludeGlobs": ["misc/build.func", "misc/install.func", "misc/api.func"]
"excludeGlobs": ["misc/build.func", "misc/install.func"]
}
],
"delete script": [
{
"fileStatus": "removed",
"fileStatus": "removed",
"includeGlobs": ["ct/**", "install/**", "misc/**", "turnkey/**", "vm/**"],
"excludeGlobs": []
}
],
"maintenance": [
"rename script": [
{
"fileStatus": null,
"includeGlobs": [
"*.md",
".github/**",
"misc/*.func",
"ct/create_lxc.sh",
"api/**"
],
"excludeGlobs": []
}
],
"core": [
{
"fileStatus": null,
"includeGlobs": ["misc/*.func", "ct/create_lxc.sh"],
"fileStatus": "renamed",
"includeGlobs": ["ct/**", "install/**", "misc/**", "turnkey/**", "vm/**"],
"excludeGlobs": []
}
],
"website": [
{
"fileStatus": null,
"includeGlobs": ["frontend/**"],
"includeGlobs": ["frontend/**", "json/**"],
"excludeGlobs": []
}
],
"api": [
"maintenance": [
{
"fileStatus": null,
"includeGlobs": ["api/**", "misc/api.func"],
"includeGlobs": ["*.md", ".github/**", "misc/*.func", "ct/create_lxc.sh"],
"excludeGlobs": []
}
],
"github": [
{
"fileStatus": null,
"includeGlobs": [".github/**"],
"excludeGlobs": []
}
],
"json": [
{
"fileStatus": "modified",
"includeGlobs": ["frontend/public/json/**"],
"excludeGlobs": []
}
],
"high risk": [
{
"fileStatus": null,
"includeGlobs": [
"misc/build.func",
"misc/install.func",
"ct/create_lxc.sh"
],
"excludeGlobs": []
}
],
"documentation": [
{
"fileStatus": null,
"includeGlobs": ["*.md"],
"includeGlobs": ["misc/build.func", "misc/install.func"],
"excludeGlobs": []
}
]

View File

@ -1,112 +1,30 @@
[
{
"title": "🆕 New Scripts",
"labels": ["new script"]
},
{
"title": "🚀 Updated Scripts",
"labels": ["update script"],
"subCategories": [
{
"title": "🐞 Bug Fixes",
"labels": ["bugfix"],
"notes" : []
},
{
"title": "✨ New Features",
"labels": ["feature"],
"notes" : []
},
{
{
"title": "💥 Breaking Changes",
"labels": ["breaking change"],
"notes" : []
},
{
"title": "🔧 Refactor",
"labels": ["refactor"],
"notes" : []
}
]
},
{
"title": "🧰 Maintenance",
"labels": ["maintenance"],
"subCategories": [
{
"labels": ["breaking change"]
},
{
"title": "✨ New Scripts",
"labels": ["new script"]
},
{
"title": "🚀 Updated Scripts",
"labels": ["update script"]
},
{
"title": "🌐 Website",
"labels": ["website"]
},
{
"title": "🐞 Bug Fixes",
"labels": ["bugfix"],
"notes" : []
},
{
"title": "✨ New Features",
"labels": ["feature"],
"notes" : []
},
{
"title": "💥 Breaking Changes",
"labels": ["breaking change"],
"notes" : []
},
{
"title": "📡 API",
"labels": ["api"],
"notes" : []
},
{
"title": "💾 Core",
"labels": ["core"],
"notes" : []
},
{
"title": "📂 Github",
"labels": ["github"],
"notes" : []
},
{
"title" :"📝 Documentation",
"labels": ["documentation"],
"notes" : []
},
{
"title" :"🔧 Refactor",
"labels": ["refactor"],
"notes" : []
}
]
},
{
"title": "🌐 Website",
"labels": ["website"],
"subCategories": [
{
"title": "🐞 Bug Fixes",
"labels": ["bugfix"],
"notes" : []
},
{
"title": "✨ New Features",
"labels": ["feature"],
"notes" : []
},
{
"title": "💥 Breaking Changes",
"labels": ["breaking change"],
"notes" : []
},
{
"title": "📝 Script Information",
"labels": ["json"],
"notes" : []
}
]
},
{
"title": "❔ Unlabelled",
"labels": []
},
{
"title": "💥 Breaking Changes",
"labels": ["breaking change"]
}
"labels": ["bug fix"]
},
{
"title": "🧰 Maintenance",
"labels": ["maintenance"]
},
{
"title": "❔ Unlabelled",
"labels": []
}
]

View File

@ -1,27 +1,28 @@
<!--🛑 New scripts must be submitted to [ProxmoxVED](https://github.com/community-scripts/ProxmoxVED) for testing.
PRs without prior testing will be closed. -->
## ✍️ Description
## ✍️ Description
## 🔗 Related PR / Issue
Link: #
- - -
- Related Issue: #
- Related PR: #
- Related Discussion: #
- - -
## ✅ Prerequisites (**X** in brackets)
## ✅ Prerequisites
The following steps must be completed for the pull request to be considered:
- [] Self-review performed (I have reviewed my code to ensure it follows established patterns and conventions.)
- [] Testing performed (I have thoroughly tested my changes and verified expected functionality.)
- [ ] **Self-review completed** Code follows project standards.
- [ ] **Tested thoroughly** Changes work as expected.
- [ ] **No security risks** No hardcoded secrets, unnecessary privilege escalations, or permission issues.
## 🛠️ Type of Change
Please check the relevant options:
- [] Bug fix (non-breaking change that resolves an issue)
- [] New feature (non-breaking change that adds functionality)
- [] Breaking change (fix or feature that would cause existing functionality to change unexpectedly)
- [] New script (a fully functional and thoroughly tested script or set of scripts)
---
## 📋 Additional Information (optional)
Provide any extra context or screenshots about the feature or fix here.
## 🛠️ Type of Change (**X** in brackets)
- [ ] 🐞 **Bug fix** Resolves an issue without breaking functionality.
- [ ]**New feature** Adds new, non-breaking functionality.
- [ ] 💥 **Breaking change** Alters existing functionality in a way that may require updates.
- [ ] 🆕 **New script** A fully functional and tested script or script set.
- [ ] 🌍 **Website update** Changes to website-related JSON files or metadata.
- [ ] 🔧 **Refactoring / Code Cleanup** Improves readability or maintainability without changing functionality.
- [ ] 📝 **Documentation update** Changes to `README`, `AppName.md`, `CONTRIBUTING.md`, or other docs.

View File

@ -1,68 +0,0 @@
FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-jammy as build
ARG TARGETOS
ARG TARGETARCH
ARG DOCKER_VERSION=27.5.1
ARG BUILDX_VERSION=0.20.1
ARG RUNNER_ARCH="x64"
RUN apt update -y && apt install sudo curl unzip -y
WORKDIR /actions-runner
RUN RUNNER_VERSION=$(curl -s https://api.github.com/repos/actions/runner/releases/latest | grep "tag_name" | head -n 1 | awk '{print substr($2, 3, length($2)-4)}') \
&& curl -f -L -o runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-${RUNNER_ARCH}-${RUNNER_VERSION}.tar.gz \
&& tar xzf ./runner.tar.gz \
&& rm runner.tar.gz
RUN RUNNER_CONTAINER_HOOKS_VERSION=$(curl -s https://api.github.com/repos/actions/runner-container-hooks/releases/latest | grep "tag_name" | head -n 1 | awk '{print substr($2, 3, length($2)-4)}') \
&& curl -f -L -o runner-container-hooks.zip https://github.com/actions/runner-container-hooks/releases/download/v${RUNNER_CONTAINER_HOOKS_VERSION}/actions-runner-hooks-k8s-${RUNNER_CONTAINER_HOOKS_VERSION}.zip \
&& unzip ./runner-container-hooks.zip -d ./k8s \
&& rm runner-container-hooks.zip
RUN export RUNNER_ARCH=${TARGETARCH} \
&& if [ "$RUNNER_ARCH" = "amd64" ]; then export DOCKER_ARCH=x86_64 ; fi \
&& if [ "$RUNNER_ARCH" = "arm64" ]; then export DOCKER_ARCH=aarch64 ; fi \
&& curl -fLo docker.tgz https://download.docker.com/${TARGETOS}/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz \
&& tar zxvf docker.tgz \
&& rm -rf docker.tgz \
&& mkdir -p /usr/local/lib/docker/cli-plugins \
&& curl -fLo /usr/local/lib/docker/cli-plugins/docker-buildx \
"https://github.com/docker/buildx/releases/download/v${BUILDX_VERSION}/buildx-v${BUILDX_VERSION}.linux-${TARGETARCH}" \
&& chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx
FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-jammy
ENV DEBIAN_FRONTEND=noninteractive
ENV RUNNER_MANUALLY_TRAP_SIG=1
ENV ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT=1
ENV ImageOS=ubuntu22
RUN apt update -y \
&& apt install -y --no-install-recommends sudo lsb-release gpg-agent software-properties-common curl jq unzip \
&& rm -rf /var/lib/apt/lists/*
RUN add-apt-repository ppa:git-core/ppa \
&& apt update -y \
&& apt install -y git \
&& rm -rf /var/lib/apt/lists/*
RUN adduser --disabled-password --gecos "" --uid 1001 runner \
&& groupadd docker --gid 123 \
&& usermod -aG sudo runner \
&& usermod -aG docker runner \
&& echo "%sudo ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers \
&& echo "Defaults env_keep += \"DEBIAN_FRONTEND\"" >> /etc/sudoers
# Install own dependencies in final image
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
&& apt-get install -y nodejs \
&& apt-get install -y gh jq git
WORKDIR /home/runner
COPY --chown=runner:docker --from=build /actions-runner .
COPY --from=build /usr/local/lib/docker/cli-plugins/docker-buildx /usr/local/lib/docker/cli-plugins/docker-buildx
RUN install -o root -g root -m 755 docker/* /usr/bin/ && rm -rf docker
USER runner

View File

@ -1,117 +1,82 @@
name: Auto Update .app-files
name: Auto Update .app-headers
on:
push:
branches:
- main
paths:
- "ct/**.sh"
workflow_dispatch:
- 'ct/**.sh'
workflow_dispatch: # Ermöglicht das manuelle Ausführen der Action
jobs:
update-app-files:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: runner-cluster-htl-set
update-app-headers:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Generate a token for PR approval and merge
id: generate-token-merge
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.APP_ID_APPROVE_AND_MERGE }}
private-key: ${{ secrets.APP_KEY_APPROVE_AND_MERGE }}
# Step 1: Checkout repository
- name: Checkout repository
uses: actions/checkout@v2
# Step 2: Disable file mode changes detection
- name: Disable file mode changes
run: git config core.fileMode false
# Step 3: Set up Git user for committing changes
# Step 2: Set up Git user for committing changes
- name: Set up Git
run: |
git config --global user.name "GitHub Actions"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.email "actions@github.com"
# Step 4: Install figlet
# Step 3: Install figlet
- name: Install figlet
run: sudo apt-get install -y figlet
# Step 5: Run the updated generate-app-files.sh script
- name: Run generate-app-files.sh
# Step 4: Run the generate-app-headers.sh script to update .app-headers
- name: Run generate-app-headers.sh to update .app-headers
run: |
chmod +x .github/workflows/scripts/generate-app-headers.sh
.github/workflows/scripts/generate-app-headers.sh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Step 6: Check if there are any changes
# Step 5: Check if there are any changes
- name: Check if there are any changes
id: verify-diff
run: |
echo "Checking for changes..."
git add -A # Untracked Dateien aufnehmen
git status
if git diff --cached --quiet; then
echo "No changes detected."
echo "changed=false" >> "$GITHUB_ENV"
else
echo "Changes detected:"
git diff --stat --cached
echo "changed=true" >> "$GITHUB_ENV"
fi
git diff --quiet . || echo "changed=true" >> $GITHUB_OUTPUT
# Step 7: Commit and create PR if changes exist
# Step 6: Commit changes (if any) and create a PR
- name: Commit and create PR if changes exist
if: env.changed == 'true'
if: steps.verify-diff.outputs.changed == 'true'
run: |
git commit -m "Update .app files"
git checkout -b pr-update-app-files
git push origin pr-update-app-files --force
gh pr create --title "[core] update .app files" \
--body "This PR is auto-generated by a GitHub Action to update the .app files." \
--head pr-update-app-files \
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git add ./misc/.app-headers
git commit -m "Update .app-headers file"
# Create a temporary branch for the PR
git checkout -b pr-update-app-headers
git push origin pr-update-app-headers --force
# Create PR against main
gh pr create --title "[core] update .app-headers file" \
--body "This PR is auto-generated by a Github Action to update the .app-headers file." \
--head pr-update-app-headers \
--base main \
--label "automated pr"
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Approve pull request
if: env.changed == 'true'
- name: Re-approve pull request after update
if: steps.verify-diff.outputs.changed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER=$(gh pr list --head "pr-update-app-files" --json number --jq '.[].number')
if [ -n "$PR_NUMBER" ]; then
gh pr review $PR_NUMBER --approve
PR_NUMBER=$(gh pr list --head "pr-update-app-headers" --json number --jq '.[].number')
# Check if the PR was created by the bot (skip review if so)
PR_AUTHOR=$(gh pr view "$PR_NUMBER" --json author --jq '.author.login')
if [ "$PR_AUTHOR" != "github-actions[bot]" ]; then
gh pr review "$PR_NUMBER" --approve
else
echo "PR was created by the bot, skipping review."
fi
- name: Approve pull request and merge
if: env.changed == 'true'
env:
GH_TOKEN: ${{ steps.generate-token-merge.outputs.token }}
run: |
git config --global user.name "github-actions-automege[bot]"
git config --global user.email "github-actions-automege[bot]@users.noreply.github.com"
PR_NUMBER=$(gh pr list --head "${BRANCH_NAME}" --json number --jq '.[].number')
if [ -n "$PR_NUMBER" ]; then
gh pr review $PR_NUMBER --approve
gh pr merge $PR_NUMBER --squash --admin
fi
# Step 8: Output success message when no changes
- name: No changes detected
if: env.changed == 'false'
run: echo "No changes to commit. Workflow completed successfully."

View File

@ -7,8 +7,7 @@ on:
jobs:
autolabeler:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: runner-cluster-htl-set
runs-on: ubuntu-latest
permissions:
pull-requests: write
env:
@ -17,10 +16,10 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
- name: Install minimatch
run: npm install minimatch
- name: Label PR based on file changes and PR template
- name: Label PR based on config rules
uses: actions/github-script@v7
with:
script: |
@ -31,67 +30,33 @@ jobs:
const configPath = path.resolve(process.env.CONFIG_PATH);
const fileContent = await fs.readFile(configPath, 'utf-8');
const autolabelerConfig = JSON.parse(fileContent);
const prNumber = context.payload.pull_request.number;
const prBody = context.payload.pull_request.body.toLowerCase();
let labelsToAdd = new Set();
const prListFilesResponse = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
});
const prFiles = prListFilesResponse.data;
// Apply labels based on file changes
for (const [label, rules] of Object.entries(autolabelerConfig)) {
const shouldAddLabel = prFiles.some((prFile) => {
return rules.some((rule) => {
const isFileStatusMatch = rule.fileStatus ? rule.fileStatus === prFile.status : true;
const isIncludeGlobMatch = rule.includeGlobs.some((glob) => minimatch(prFile.filename, glob));
const isExcludeGlobMatch = rule.excludeGlobs.some((glob) => minimatch(prFile.filename, glob));
return isFileStatusMatch && isIncludeGlobMatch && !isExcludeGlobMatch;
});
});
if (shouldAddLabel) {
labelsToAdd.add(label);
console.log(`Adding label ${label} to PR ${prNumber}`);
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
labels: [label],
});
}
}
//if two labels or more are added, return
if (labelsToAdd.size < 2) {
const templateLabelMappings = {
"🐞 **Bug fix**": "bugfix",
"✨ **New feature**": "feature",
"💥 **Breaking change**": "breaking change",
"🔧 **Refactoring / Code Cleanup**": "refactor",
};
for (const [checkbox, label] of Object.entries(templateLabelMappings)) {
const escapedCheckbox = checkbox.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
const regex = new RegExp(`- \\[(x|X)\\]\\s*.*${escapedCheckbox}`, "i");
const match = prBody.match(regex);
if (match) {
console.log(`Match: ${match}`);
labelsToAdd.add(label);
}
}
}
console.log(`Labels to add: ${Array.from(labelsToAdd).join(", ")}`);
if (labelsToAdd.size > 0) {
console.log(`Adding labels ${Array.from(labelsToAdd).join(", ")} to PR ${prNumber}`);
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
labels: Array.from(labelsToAdd),
});
}

View File

@ -0,0 +1,60 @@
name: Update date_created in JSON files
on:
# Dieser Trigger wird für das Öffnen von PRs sowie für das Aktualisieren von offenen PRs verwendet
pull_request:
types: [opened, synchronize]
schedule:
# Dieser Trigger wird 4x am Tag ausgelöst, um sicherzustellen, dass das Datum aktualisiert wird
- cron: "0 0,6,12,18 * * *" # Führt alle 6 Stunden aus
workflow_dispatch: # Manuelle Ausführung des Workflows möglich
jobs:
update-date:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install yq
run: |
sudo apt-get update
sudo apt-get install -y yq
- name: Set the current date
id: set_date
run: echo "TODAY=$(date -u +%Y-%m-%d)" >> $GITHUB_ENV
- name: Check for changes in PR
run: |
# Hole den PR-Branch
PR_BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
git fetch origin $PR_BRANCH
# Liste alle JSON-Dateien im PR auf, die geändert wurden
CHANGED_JSON_FILES=$(git diff --name-only origin/main...$PR_BRANCH | grep '.json')
if [ -z "$CHANGED_JSON_FILES" ]; then
echo "No JSON files changed in this PR."
exit 0
fi
# Gehe alle geänderten JSON-Dateien durch und aktualisiere das Datum
for file in $CHANGED_JSON_FILES; do
echo "Updating date_created in $file"
# Setze das aktuelle Datum
yq eval ".date_created = \"${{ env.TODAY }}\"" -i "$file"
git add "$file"
done
- name: Commit and push changes
run: |
# Prüfe, ob es Änderungen gibt und committe sie
git config user.name "json-updater-bot"
git config user.email "github-actions[bot]@users.noreply.github.com"
git commit -m "Update date_created to ${{ env.TODAY }}" || echo "No changes to commit"
# Push zurück in den PR-Branch
git push origin $PR_BRANCH

60
.github/workflows/backup/shellcheck.yml vendored Normal file
View File

@ -0,0 +1,60 @@
name: Shellcheck
on:
push:
branches:
- main
pull_request:
workflow_dispatch:
schedule:
- cron: "5 1 * * *"
jobs:
shellcheck:
name: Shellcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v45
with:
files: |
**.sh
- name: Download ShellCheck
shell: bash
env:
INPUT_VERSION: "v0.10.0"
run: |
set -euo pipefail
if [[ "${{ runner.os }}" == "macOS" ]]; then
osvariant="darwin"
else
osvariant="linux"
fi
baseurl="https://github.com/koalaman/shellcheck/releases/download"
curl -Lso "${{ github.workspace }}/sc.tar.xz" \
"${baseurl}/${INPUT_VERSION}/shellcheck-${INPUT_VERSION}.${osvariant}.x86_64.tar.xz"
tar -xf "${{ github.workspace }}/sc.tar.xz" -C "${{ github.workspace }}"
mv "${{ github.workspace }}/shellcheck-${INPUT_VERSION}/shellcheck" \
"${{ github.workspace }}/shellcheck"
- name: Verify ShellCheck binary
run: |
ls -l "${{ github.workspace }}/shellcheck"
- name: Display ShellCheck version
run: |
"${{ github.workspace }}/shellcheck" --version
- name: Run ShellCheck
if: steps.changed-files.outputs.any_changed == 'true'
env:
ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
run: |
echo "${ALL_CHANGED_FILES}" | xargs "${{ github.workspace }}/shellcheck"

View File

@ -0,0 +1,133 @@
name: Validate script formatting
on:
push:
branches:
- main
pull_request_target:
paths:
- "**/*.sh"
- "**/*.func"
jobs:
shfmt:
name: Check changed files
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Get pull request information
if: github.event_name == 'pull_request_target'
uses: actions/github-script@v7
id: pr
with:
script: |
const { data: pullRequest } = await github.rest.pulls.get({
...context.repo,
pull_number: context.payload.pull_request.number,
});
return pullRequest;
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Ensure the full history is fetched for accurate diffing
ref: ${{ github.event_name == 'pull_request_target' && fromJSON(steps.pr.outputs.result).merge_commit_sha || '' }}
- name: Get changed files
id: changed-files
run: |
if ${{ github.event_name == 'pull_request_target' }}; then
echo "files=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ steps.pr.outputs.result && fromJSON(steps.pr.outputs.result).merge_commit_sha }} | grep -E '\.(sh|func)$' | xargs)" >> $GITHUB_OUTPUT
else
echo "files=$(git diff --name-only ${{ github.event.before }} ${{ github.event.after }} | grep -E '\.(sh|func)$' | xargs)" >> $GITHUB_OUTPUT
fi
- name: Set up Go
if: steps.changed-files.outputs.files != ''
uses: actions/setup-go@v5
- name: Install shfmt
if: steps.changed-files.outputs.files != ''
run: |
go install mvdan.cc/sh/v3/cmd/shfmt@latest
echo "$GOPATH/bin" >> $GITHUB_PATH
- name: Run shfmt
if: steps.changed-files.outputs.files != ''
id: shfmt
run: |
set +e
shfmt_output=$(shfmt -d ${{ steps.changed-files.outputs.files }})
if [[ $? -eq 0 ]]; then
exit 0
else
echo "diff=\"$(echo -n "$shfmt_output" | base64 -w 0)\"" >> $GITHUB_OUTPUT
printf "%s" "$shfmt_output"
exit 1
fi
- name: Post comment with results
if: always() && steps.changed-files.outputs.files != '' && github.event_name == 'pull_request_target'
uses: actions/github-script@v7
with:
script: |
const result = "${{ job.status }}" === "success" ? "success" : "failure";
const diff = Buffer.from(
${{ steps.shfmt.outputs.diff }},
"base64",
).toString();
const issueNumber = context.payload.pull_request
? context.payload.pull_request.number
: null;
const commentIdentifier = "validate-formatting";
let newCommentBody = `<!-- ${commentIdentifier}-start -->\n### Script formatting\n\n`;
if (result === "failure") {
newCommentBody +=
`:x: We found issues in the formatting of the following changed files:\n\n\`\`\`diff\n${diff}\n\`\`\`\n`;
} else {
newCommentBody += `:rocket: All changed shell scripts are formatted correctly!\n`;
}
newCommentBody += `\n\n<!-- ${commentIdentifier}-end -->`;
if (issueNumber) {
const { data: comments } = await github.rest.issues.listComments({
...context.repo,
issue_number: issueNumber,
});
const existingComment = comments.find(
(comment) => comment.user.login === "github-actions[bot]",
);
if (existingComment) {
if (existingComment.body.includes(commentIdentifier)) {
const re = new RegExp(
String.raw`<!-- ${commentIdentifier}-start -->[\s\S]*?<!-- ${commentIdentifier}-end -->`,
"",
);
newCommentBody = existingComment.body.replace(re, newCommentBody);
} else {
newCommentBody = existingComment.body + "\n\n---\n\n" + newCommentBody;
}
await github.rest.issues.updateComment({
...context.repo,
comment_id: existingComment.id,
body: newCommentBody,
});
} else {
await github.rest.issues.createComment({
...context.repo,
issue_number: issueNumber,
body: newCommentBody,
});
}
}

View File

@ -0,0 +1,234 @@
name: Validate scripts
on:
push:
branches:
- main
pull_request_target:
paths:
- "ct/*.sh"
- "install/*.sh"
jobs:
check-scripts:
name: Check changed files
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Debug event payload
run: |
echo "Event name: ${{ github.event_name }}"
echo "Payload: $(cat $GITHUB_EVENT_PATH)"
- name: Get pull request information
if: github.event_name == 'pull_request_target'
uses: actions/github-script@v7
id: pr
with:
script: |
const { data: pullRequest } = await github.rest.pulls.get({
...context.repo,
pull_number: context.payload.pull_request.number,
});
return pullRequest;
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event_name == 'pull_request_target' && fromJSON(steps.pr.outputs.result).merge_commit_sha || '' }}
- name: Get changed files
id: changed-files
run: |
if [ "${{ github.event_name }}" == "pull_request_target" ]; then
echo "files=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ steps.pr.outputs.result && fromJSON(steps.pr.outputs.result).merge_commit_sha }} | grep -E '\.(sh|func)$' | xargs)" >> $GITHUB_OUTPUT
else
echo "files=$(git diff --name-only ${{ github.event.before }} ${{ github.event.after }} | grep -E '\.(sh|func)$' | xargs)" >> $GITHUB_OUTPUT
fi
- name: Check build.func line
if: always() && steps.changed-files.outputs.files != ''
id: build-func
run: |
NON_COMPLIANT_FILES=""
for FILE in ${{ steps.changed-files.outputs.files }}; do
if [[ "$FILE" == ct/* ]] && [[ $(sed -n '2p' "$FILE") != "source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)" ]]; then
NON_COMPLIANT_FILES="$NON_COMPLIANT_FILES $FILE"
fi
done
if [ -n "$NON_COMPLIANT_FILES" ]; then
echo "files=$NON_COMPLIANT_FILES" >> $GITHUB_OUTPUT
echo "Build.func line missing or incorrect in files:"
for FILE in $NON_COMPLIANT_FILES; do
echo "$FILE"
done
exit 1
fi
- name: Check executable permissions
if: always() && steps.changed-files.outputs.files != ''
id: check-executable
run: |
NON_COMPLIANT_FILES=""
for FILE in ${{ steps.changed-files.outputs.files }}; do
if [[ ! -x "$FILE" ]]; then
NON_COMPLIANT_FILES="$NON_COMPLIANT_FILES $FILE"
fi
done
if [ -n "$NON_COMPLIANT_FILES" ]; then
echo "files=$NON_COMPLIANT_FILES" >> $GITHUB_OUTPUT
echo "Files not executable:"
for FILE in $NON_COMPLIANT_FILES; do
echo "$FILE"
done
exit 1
fi
- name: Check copyright
if: always() && steps.changed-files.outputs.files != ''
id: check-copyright
run: |
NON_COMPLIANT_FILES=""
for FILE in ${{ steps.changed-files.outputs.files }}; do
if ! sed -n '3p' "$FILE" | grep -qE "^# Copyright \(c\) [0-9]{4}(-[0-9]{4})? (tteck \| community-scripts ORG|community-scripts ORG|tteck)$"; then
NON_COMPLIANT_FILES="$NON_COMPLIANT_FILES $FILE"
fi
done
if [ -n "$NON_COMPLIANT_FILES" ]; then
echo "files=$NON_COMPLIANT_FILES" >> $GITHUB_OUTPUT
echo "Copyright header missing or not on line 3 in files:"
for FILE in $NON_COMPLIANT_FILES; do
echo "$FILE"
done
exit 1
fi
- name: Check author
if: always() && steps.changed-files.outputs.files != ''
id: check-author
run: |
NON_COMPLIANT_FILES=""
for FILE in ${{ steps.changed-files.outputs.files }}; do
if ! sed -n '4p' "$FILE" | grep -qE "^# Author: .+"; then
NON_COMPLIANT_FILES="$NON_COMPLIANT_FILES $FILE"
fi
done
if [ -n "$NON_COMPLIANT_FILES" ]; then
echo "files=$NON_COMPLIANT_FILES" >> $GITHUB_OUTPUT
echo "Author header missing or invalid on line 4 in files:"
for FILE in $NON_COMPLIANT_FILES; do
echo "$FILE"
done
exit 1
fi
- name: Check license
if: always() && steps.changed-files.outputs.files != ''
id: check-license
run: |
NON_COMPLIANT_FILES=""
for FILE in ${{ steps.changed-files.outputs.files }}; do
if [[ "$(sed -n '5p' "$FILE")" != "# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE" ]]; then
NON_COMPLIANT_FILES="$NON_COMPLIANT_FILES $FILE"
fi
done
if [ -n "$NON_COMPLIANT_FILES" ]; then
echo "files=$NON_COMPLIANT_FILES" >> $GITHUB_OUTPUT
echo "License header missing or not on line 5 in files:"
for FILE in $NON_COMPLIANT_FILES; do
echo "$FILE"
done
exit 1
fi
- name: Check source
if: always() && steps.changed-files.outputs.files != ''
id: check-source
run: |
NON_COMPLIANT_FILES=""
for FILE in ${{ steps.changed-files.outputs.files }}; do
if ! sed -n '6p' "$FILE" | grep -qE "^# Source: .+"; then
NON_COMPLIANT_FILES="$NON_COMPLIANT_FILES $FILE"
fi
done
if [ -n "$NON_COMPLIANT_FILES" ]; then
echo "files=$NON_COMPLIANT_FILES" >> $GITHUB_OUTPUT
echo "Source header missing or not on line 6 in files:"
for FILE in $NON_COMPLIANT_FILES; do
echo "$FILE"
done
exit 1
fi
- name: Post results and comment
if: always() && steps.changed-files.outputs.files != '' && github.event_name == 'pull_request_target'
uses: actions/github-script@v7
with:
script: |
const result = '${{ job.status }}' === 'success' ? 'success' : 'failure';
const nonCompliantFiles = {
'Invalid build.func source': "${{ steps.build-func.outputs.files || '' }}",
'Not executable': "${{ steps.check-executable.outputs.files || '' }}",
'Copyright header line missing or invalid': "${{ steps.check-copyright.outputs.files || '' }}",
'Author header line missing or invalid': "${{ steps.check-author.outputs.files || '' }}",
'License header line missing or invalid': "${{ steps.check-license.outputs.files || '' }}",
'Source header line missing or invalid': "${{ steps.check-source.outputs.files || '' }}"
};
const issueNumber = context.payload.pull_request ? context.payload.pull_request.number : null;
const commentIdentifier = 'validate-scripts';
let newCommentBody = `<!-- ${commentIdentifier}-start -->\n### Script validation\n\n`;
if (result === 'failure') {
newCommentBody += ':x: We found issues in the following changed files:\n\n';
for (const [check, files] of Object.entries(nonCompliantFiles)) {
if (files) {
newCommentBody += `**${check}:**\n`;
files.trim().split(' ').forEach(file => {
newCommentBody += `- ${file}: ${check}\n`;
});
newCommentBody += `\n`;
}
}
} else {
newCommentBody += `:rocket: All changed shell scripts passed validation!\n`;
}
newCommentBody += `\n\n<!-- ${commentIdentifier}-end -->`;
if (issueNumber) {
const { data: comments } = await github.rest.issues.listComments({
...context.repo,
issue_number: issueNumber
});
const existingComment = comments.find(comment =>
comment.body.includes(`<!-- ${commentIdentifier}-start -->`) &&
comment.user.login === 'github-actions[bot]'
);
if (existingComment) {
const re = new RegExp(String.raw`<!-- ${commentIdentifier}-start -->[\\s\\S]*?<!-- ${commentIdentifier}-end -->`, "m");
newCommentBody = existingComment.body.replace(re, newCommentBody);
await github.rest.issues.updateComment({
...context.repo,
comment_id: existingComment.id,
body: newCommentBody
});
} else {
await github.rest.issues.createComment({
...context.repo,
issue_number: issueNumber,
body: newCommentBody
});
}
}

View File

@ -7,8 +7,7 @@ on:
jobs:
update-changelog-pull-request:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: runner-cluster-htl-set
runs-on: ubuntu-latest
env:
CONFIG_PATH: .github/changelog-pr-config.json
BRANCH_NAME: github-action-update-changelog
@ -24,13 +23,6 @@ jobs:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Generate a token for PR approval and merge
id: generate-token-merge
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.APP_ID_APPROVE_AND_MERGE }}
private-key: ${{ secrets.APP_KEY_APPROVE_AND_MERGE }}
- name: Checkout code
uses: actions/checkout@v4
with:
@ -38,14 +30,15 @@ jobs:
- name: Get latest dates in changelog
run: |
DATES=$(grep -E '^## [0-9]{4}-[0-9]{2}-[0-9]{2}' CHANGELOG.md | head -n 2 | awk '{print $2}')
# Extract the latest and second latest dates from changelog
DATES=$(grep '^## [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}' CHANGELOG.md | head -n 2 | awk '{print $2}')
LATEST_DATE=$(echo "$DATES" | sed -n '1p')
SECOND_LATEST_DATE=$(echo "$DATES" | sed -n '2p')
TODAY=$(date -u +%Y-%m-%d)
echo "TODAY=$TODAY" >> $GITHUB_ENV
if [[ "$LATEST_DATE" == "$TODAY" ]]; then
if [ "$LATEST_DATE" == "$TODAY" ]; then
echo "LATEST_DATE=$SECOND_LATEST_DATE" >> $GITHUB_ENV
else
echo "LATEST_DATE=$LATEST_DATE" >> $GITHUB_ENV
@ -56,134 +49,46 @@ jobs:
uses: actions/github-script@v7
with:
script: |
async function main() {
const fs = require('fs').promises;
const path = require('path');
const fs = require('fs').promises;
const path = require('path');
const configPath = path.resolve(process.env.CONFIG_PATH);
const fileContent = await fs.readFile(configPath, 'utf-8');
const changelogConfig = JSON.parse(fileContent);
const configPath = path.resolve(process.env.CONFIG_PATH);
const fileContent = await fs.readFile(configPath, 'utf-8');
const changelogConfig = JSON.parse(fileContent);
const categorizedPRs = changelogConfig.map((obj) => ({ ...obj, notes: [] }));
const categorizedPRs = changelogConfig.map(obj => ({
...obj,
notes: [],
subCategories: obj.subCategories ?? (
obj.labels.includes("update script") ? [
{ title: "🐞 Bug Fixes", labels: ["bugfix"], notes: [] },
{ title: "✨ New Features", labels: ["feature"], notes: [] },
{ title: "💥 Breaking Changes", labels: ["breaking change"], notes: [] },
{ title: "🔧 Refactor", labels: ["refactor"], notes: [] },
] :
obj.labels.includes("maintenance") ? [
{ title: "🐞 Bug Fixes", labels: ["bugfix"], notes: [] },
{ title: "✨ New Features", labels: ["feature"], notes: [] },
{ title: "💥 Breaking Changes", labels: ["breaking change"], notes: [] },
{ title: "📡 API", labels: ["api"], notes: [] },
{ title: "Github", labels: ["github"], notes: [] },
{ title: "📝 Documentation", labels: ["documentation"], notes: [] },
{ title: "🔧 Refactor", labels: ["refactor"], notes: [] }
] :
obj.labels.includes("website") ? [
{ title: "🐞 Bug Fixes", labels: ["bugfix"], notes: [] },
{ title: "✨ New Features", labels: ["feature"], notes: [] },
{ title: "💥 Breaking Changes", labels: ["breaking change"], notes: [] },
{ title: "Script Information", labels: ["json"], notes: [] }
] : []
)
}));
const latestDateInChangelog = new Date(process.env.LATEST_DATE);
latestDateInChangelog.setUTCHours(23,59,59,999);
const latestDateInChangelog = new Date(process.env.LATEST_DATE);
latestDateInChangelog.setUTCHours(23, 59, 59, 999);
const { data: pulls } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
base: "main",
state: "closed",
sort: "updated",
direction: "desc",
per_page: 100,
});
const { data: pulls } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: "ProxmoxVE",
base: "main",
state: "closed",
sort: "updated",
direction: "desc",
per_page: 100,
});
pulls.filter((pr) =>
pr.merged_at &&
new Date(pr.merged_at) > latestDateInChangelog &&
!pr.labels.some((label) => ["invalid", "wontdo", process.env.AUTOMATED_PR_LABEL].includes(label.name.toLowerCase()))
).forEach((pr) => {
const prLabels = pr.labels.map((label) => label.name.toLowerCase());
const prNote = `- ${pr.title} [@${pr.user.login}](https://github.com/${pr.user.login}) ([#${pr.number}](${pr.html_url}))`;
const filteredPRs = pulls.filter(pr =>
pr.merged_at &&
new Date(pr.merged_at) > latestDateInChangelog &&
!pr.labels.some(label =>
["invalid", "wontdo", process.env.AUTOMATED_PR_LABEL].includes(label.name.toLowerCase())
)
);
for (const pr of filteredPRs) {
const prLabels = pr.labels.map(label => label.name.toLowerCase());
if (pr.user.login.includes("push-app-to-main[bot]")) {
const scriptName = pr.title;
try {
const { data: relatedIssues } = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: "ProxmoxVED",
state: "all",
labels: ["Started Migration To ProxmoxVE"]
});
const matchingIssue = relatedIssues.find(issue =>
issue.title.toLowerCase().includes(scriptName.toLowerCase())
);
if (matchingIssue) {
const issueAuthor = matchingIssue.user.login;
const issueAuthorUrl = `https://github.com/${issueAuthor}`;
prNote = `- ${pr.title} [@${issueAuthor}](${issueAuthorUrl}) ([#${pr.number}](${pr.html_url}))`;
}
else {
prNote = `- ${pr.title} ([#${pr.number}](${pr.html_url}))`;
}
} catch (error) {
console.error(`Error fetching related issues: ${error}`);
prNote = `- ${pr.title} ([#${pr.number}](${pr.html_url}))`;
}
}else{
prNote = `- ${pr.title} [@${pr.user.login}](https://github.com/${pr.user.login}) ([#${pr.number}](${pr.html_url}))`;
for (const { labels, notes } of categorizedPRs) {
const prHasCategoryLabel = labels.some((label) => prLabels.includes(label));
const isUnlabelledCategory = labels.length === 0;
if (prHasCategoryLabel || isUnlabelledCategory) {
notes.push(prNote);
break;
}
if (prLabels.includes("new script")) {
const newScriptCategory = categorizedPRs.find(category =>
category.title === "New Scripts" || category.labels.includes("new script"));
if (newScriptCategory) {
newScriptCategory.notes.push(prNote);
}
} else {
let categorized = false;
const priorityCategories = categorizedPRs.slice();
for (const category of priorityCategories) {
if (categorized) break;
if (category.labels.some(label => prLabels.includes(label))) {
if (category.subCategories && category.subCategories.length > 0) {
const subCategory = category.subCategories.find(sub =>
sub.labels.some(label => prLabels.includes(label))
);
if (subCategory) {
subCategory.notes.push(prNote);
} else {
category.notes.push(prNote);
}
} else {
category.notes.push(prNote);
}
categorized = true;
}
}
}
}
});
return categorizedPRs;
}
return await main();
return categorizedPRs;
- name: Update CHANGELOG.md
uses: actions/github-script@v7
@ -197,48 +102,31 @@ jobs:
const changelogPath = path.resolve('CHANGELOG.md');
const categorizedPRs = ${{ steps.get-categorized-prs.outputs.result }};
console.log(JSON.stringify(categorizedPRs, null, 2));
let newReleaseNotes = `## ${today}\n\n`;
for (const { title, notes, subCategories } of categorizedPRs) {
const hasSubcategories = subCategories && subCategories.length > 0;
const hasMainNotes = notes.length > 0;
const hasSubNotes = hasSubcategories && subCategories.some(sub => sub.notes && sub.notes.length > 0);
if (hasMainNotes || hasSubNotes) {
newReleaseNotes += `### ${title}\n\n`;
let newReleaseNotes = `## ${today}\n\n### Changed\n\n`;
for (const { title, notes } of categorizedPRs) {
if (notes.length > 0) {
newReleaseNotes += `### ${title}\n\n${notes.join("\n")}\n\n`;
}
}
if (hasMainNotes) {
newReleaseNotes += ` ${notes.join("\n")}\n\n`;
}
if (hasSubcategories) {
for (const { title: subTitle, notes: subNotes } of subCategories) {
if (subNotes && subNotes.length > 0) {
newReleaseNotes += ` - #### ${subTitle}\n\n`;
newReleaseNotes += ` ${subNotes.join("\n ")}\n\n`;
}
}
}
}
const changelogContent = await fs.readFile(changelogPath, 'utf-8');
const changelogIncludesTodaysReleaseNotes = changelogContent.includes(`\n## ${today}`);
const regex = changelogIncludesTodaysReleaseNotes
? new RegExp(`## ${today}.*(?=## ${latestDateInChangelog})`, "gs")
: new RegExp(`(?=## ${latestDateInChangelog})`, "gs");
// Replace todays release notes or insert release notes above previous release notes
const regex = changelogIncludesTodaysReleaseNotes ?
new RegExp(`## ${today}.*(?=## ${latestDateInChangelog})`, "gs") :
new RegExp(`(?=## ${latestDateInChangelog})`, "gs");
const newChangelogContent = changelogContent.replace(regex, newReleaseNotes);
const newChangelogContent = changelogContent.replace(regex, newReleaseNotes)
await fs.writeFile(changelogPath, newChangelogContent);
- name: Check for changes
- name: Check if there are any changes
id: verify-diff
run: |
git diff --quiet . || echo "changed=true" >> $GITHUB_ENV
git diff --quiet . || echo "changed=true" >> $GITHUB_OUTPUT
- name: Commit and push changes
if: env.changed == 'true'
- name: Commit and push changes to separate branch
if: steps.verify-diff.outputs.changed == 'true'
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
@ -248,7 +136,7 @@ jobs:
git push origin $BRANCH_NAME --force
- name: Create pull request if not exists
if: env.changed == 'true'
if: steps.verify-diff.outputs.changed == 'true'
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
run: |
@ -262,7 +150,7 @@ jobs:
fi
- name: Approve pull request
if: env.changed == 'true'
if: steps.verify-diff.outputs.changed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
@ -270,16 +158,13 @@ jobs:
if [ -n "$PR_NUMBER" ]; then
gh pr review $PR_NUMBER --approve
fi
- name: Approve pull request and merge
if: env.changed == 'true'
- name: Re-approve pull request after update
if: steps.verify-diff.outputs.changed == 'true'
env:
GH_TOKEN: ${{ steps.generate-token-merge.outputs.token }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config --global user.name "github-actions-automege[bot]"
git config --global user.email "github-actions-automege[bot]@users.noreply.github.com"
PR_NUMBER=$(gh pr list --head "${BRANCH_NAME}" --json number --jq '.[].number')
if [ -n "$PR_NUMBER" ]; then
gh pr review $PR_NUMBER --approve
gh pr merge $PR_NUMBER --squash --admin
fi

View File

@ -1,164 +0,0 @@
name: Close Discussion on PR Merge
on:
push:
branches:
- main
permissions:
contents: read
discussions: write
jobs:
close-discussion:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: runner-cluster-htl-set
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set Up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install Dependencies
run: npm install zx @octokit/graphql
- name: Close Discussion
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_SHA: ${{ github.sha }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: |
npx zx << 'EOF'
import { graphql } from "@octokit/graphql";
(async function () {
try {
const token = process.env.GITHUB_TOKEN;
const commitSha = process.env.GITHUB_SHA;
const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
if (!token || !commitSha || !owner || !repo) {
console.log("Missing required environment variables.");
process.exit(1);
}
const graphqlWithAuth = graphql.defaults({
headers: { authorization: `Bearer ${token}` },
});
// Find PR from commit SHA
const searchQuery = `
query($owner: String!, $repo: String!, $sha: GitObjectID!) {
repository(owner: $owner, name: $repo) {
object(oid: $sha) {
... on Commit {
associatedPullRequests(first: 1) {
nodes {
number
body
}
}
}
}
}
}
`;
const prResult = await graphqlWithAuth(searchQuery, {
owner,
repo,
sha: commitSha,
});
const pr = prResult.repository.object.associatedPullRequests.nodes[0];
if (!pr) {
console.log("No PR found for this commit.");
return;
}
const prNumber = pr.number;
const prBody = pr.body;
const match = prBody.match(/#(\d+)/);
if (!match) {
console.log("No discussion ID found in PR body.");
return;
}
const discussionNumber = match[1];
console.log(`Extracted Discussion Number: ${discussionNumber}`);
// Fetch GraphQL discussion ID
const discussionQuery = `
query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
discussion(number: $number) {
id
}
}
}
`;
//
try {
const discussionResponse = await graphqlWithAuth(discussionQuery, {
owner,
repo,
number: parseInt(discussionNumber, 10),
});
const discussionQLId = discussionResponse.repository.discussion.id;
if (!discussionQLId) {
console.log("Failed to fetch discussion GraphQL ID.");
return;
}
} catch (error) {
console.error("Discussion not found or error occurred while fetching discussion:", error);
return;
}
// Post comment
const commentMutation = `
mutation($discussionId: ID!, $body: String!) {
addDiscussionComment(input: { discussionId: $discussionId, body: $body }) {
comment { id body }
}
}
`;
const commentResponse = await graphqlWithAuth(commentMutation, {
discussionId: discussionQLId,
body: `Merged with PR #${prNumber}`,
});
const commentId = commentResponse.addDiscussionComment.comment.id;
if (!commentId) {
console.log("Failed to post the comment.");
return;
}
console.log(`Comment Posted Successfully! Comment ID: ${commentId}`);
// Mark comment as answer
const markAnswerMutation = `
mutation($id: ID!) {
markDiscussionCommentAsAnswer(input: { id: $id }) {
discussion { id title }
}
}
`;
await graphqlWithAuth(markAnswerMutation, { id: commentId });
console.log("Comment marked as answer successfully!");
} catch (error) {
console.error("Error:", error);
process.exit(1);
}
})();
EOF

View File

@ -1,52 +0,0 @@
name: Auto-Close tteck Issues
on:
issues:
types: [opened]
jobs:
close_tteck_issues:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: ubuntu-latest
steps:
- name: Auto-close if tteck script detected
uses: actions/github-script@v7
with:
script: |
const issue = context.payload.issue;
const content = `${issue.title}\n${issue.body}`;
const issueNumber = issue.number;
// Check for tteck script mention
if (content.includes("tteck") || content.includes("tteck/Proxmox")) {
const message = `Hello, it looks like you are referencing the **old tteck repo**.
This repository is no longer used for active scripts.
**Please update your bookmarks** and use: [https://helper-scripts.com](https://helper-scripts.com)
Also make sure your Bash command starts with:
\`\`\`bash
bash <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/...)
\`\`\`
This issue is being closed automatically.`;
await github.rest.issues.createComment({
...context.repo,
issue_number: issueNumber,
body: message
});
// Optionally apply a label like "not planned"
await github.rest.issues.addLabels({
...context.repo,
issue_number: issueNumber,
labels: ["not planned"]
});
// Close the issue
await github.rest.issues.update({
...context.repo,
issue_number: issueNumber,
state: "closed"
});
}

View File

@ -1,65 +0,0 @@
name: Close Matching Issue on PR Merge
on:
pull_request:
types:
- closed
jobs:
close_issue:
if: github.event.pull_request.merged == true && github.repository == 'community-scripts/ProxmoxVE'
runs-on: ubuntu-latest
steps:
- name: Checkout target repo (main)
uses: actions/checkout@v4
with:
repository: community-scripts/ProxmoxVE
ref: main
token: ${{ secrets.GITHUB_TOKEN }}
- name: Extract and Process PR Title
id: extract_title
run: |
title=$(echo "${{ github.event.pull_request.title }}" | sed 's/^New Script://g' | tr '[:upper:]' '[:lower:]' | sed 's/ //g' | sed 's/-//g')
echo "Processed Title: $title"
echo "title=$title" >> $GITHUB_ENV
- name: Search for Issues with Similar Titles
id: find_issue
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
issues=$(gh issue list --repo community-scripts/ProxmoxVED --json number,title --jq '.[] | {number, title}')
best_match_score=0
best_match_number=0
for issue in $(echo "$issues" | jq -r '. | @base64'); do
_jq() {
echo ${issue} | base64 --decode | jq -r ${1}
}
issue_title=$(_jq '.title' | tr '[:upper:]' '[:lower:]' | sed 's/ //g' | sed 's/-//g')
issue_number=$(_jq '.number')
match_score=$(echo "$title" | grep -o "$issue_title" | wc -l)
if [ "$match_score" -gt "$best_match_score" ]; then
best_match_score=$match_score
best_match_number=$issue_number
fi
done
if [ "$best_match_number" != "0" ]; then
echo "issue_number=$best_match_number" >> $GITHUB_ENV
else
echo "No matching issue found."
exit 0
fi
- name: Comment on the Best-Matching Issue and Close It
if: env.issue_number != ''
env:
GH_TOKEN: ${{ secrets.PAT_MICHEL }}
run: |
gh issue comment $issue_number --repo community-scripts/ProxmoxVED --body "Merged with #${{ github.event.pull_request.number }} in ProxmoxVE"
gh issue close $issue_number --repo community-scripts/ProxmoxVED

View File

@ -1,126 +0,0 @@
name: Crawl Versions from newreleases.io
on:
workflow_dispatch:
schedule:
# Runs at 12:00 AM and 12:00 PM UTC
- cron: "0 0,12 * * *"
permissions:
contents: write
pull-requests: write
jobs:
crawl-versions:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: runner-cluster-htl-set
steps:
- name: Checkout Repository
uses: actions/checkout@v2
with:
repository: community-scripts/ProxmoxVE
ref: main
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Crawl from newreleases.io
env:
token: ${{ secrets.NEWRELEASES_TOKEN }}
run: |
page=1
projects_file="project_json"
output_file="frontend/public/json/versions.json"
echo "[]" > $output_file
while true; do
echo "Start loop on page: $page"
projects=$(curl -s -H "X-Key: $token" "https://api.newreleases.io/v1/projects?page=$page")
total_pages=$(echo "$projects" | jq -r '.total_pages')
if [ -z "$total_pages" ] || [ "$total_pages" -eq 0 ]; then
echo "No pages available. Exiting."
exit 1
fi
if [ $page == $total_pages ]; then
break
fi
if [ -z "$projects" ] || ! echo "$projects" | jq -e '.projects' > /dev/null; then
echo "No more projects or invalid response. Exiting."
break
fi
echo "$projects" > "$projects_file"
jq -r '.projects[] | "\(.id) \(.name)"' "$projects_file" | while read -r id name; do
version=$(curl -s -H "X-Key: $token" "https://api.newreleases.io/v1/projects/$id/latest-release")
version_data=$(echo "$version" | jq -r '.version // empty')
date=$(echo "$version" | jq -r '.date // empty')
if [ -n "$version_data" ]; then
jq --arg name "$name" --arg version "$version_data" --arg date "$date" \
'. += [{"name": $name, "version": $version, "date": $date}]' "$output_file" > "$output_file.tmp" && mv "$output_file.tmp" "$output_file"
fi
done
((page++))
done
- name: Commit JSON
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
run: |
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "GitHub Actions[bot]"
git checkout -b update_versions || git checkout update_versions
git add frontend/public/json/versions.json
if git diff --cached --quiet; then
echo "No changes detected."
echo "changed=false" >> "$GITHUB_ENV"
exit 0
else
echo "Changes detected:"
git diff --stat --cached
echo "changed=true" >> "$GITHUB_ENV"
fi
git commit -m "Update versions.json"
git push origin update_versions --force
gh pr create --title "[Github Action] Update versions.json" --body "Update versions.json, crawled from newreleases.io" --base main --head update_versions --label "automated pr"
- name: Approve pull request
if: env.changed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER=$(gh pr list --head "update_versions" --json number --jq '.[].number')
if [ -n "$PR_NUMBER" ]; then
gh pr review $PR_NUMBER --approve
fi
- name: Approve pull request and merge
if: env.changed == 'true'
env:
GH_TOKEN: ${{ secrets.PAT_AUTOMERGE }}
run: |
PR_NUMBER=$(gh pr list --head "update_versions" --json number --jq '.[].number')
if [ -n "$PR_NUMBER" ]; then
gh pr review $PR_NUMBER --approve
gh pr merge $PR_NUMBER --squash --admin
fi
- name: Re-approve pull request after update
if: env.changed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER=$(gh pr list --head "update_versions" --json number --jq '.[].number')
if [ -n "$PR_NUMBER" ]; then
gh pr review $PR_NUMBER --approve
fi

View File

@ -1,38 +0,0 @@
name: Build and Publish Docker Image
on:
push:
branches:
- main
paths:
- '.github/runner/docker/**'
schedule:
- cron: '0 0 * * *'
jobs:
build:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: ubuntu-latest #To ensure it always builds we use the github runner with all the right tooling
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Log in to GHCR
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build Docker image
run: |
repo_name=${{ github.repository }} # Get repository name
repo_name_lower=$(echo $repo_name | tr '[:upper:]' '[:lower:]') # Convert to lowercase
docker build -t ghcr.io/$repo_name_lower/gh-runner-self:latest -f .github/runner/docker/gh-runner-self.dockerfile .
- name: Push Docker image to GHCR
run: |
repo_name=${{ github.repository }} # Get repository name
repo_name_lower=$(echo $repo_name | tr '[:upper:]' '[:lower:]') # Convert to lowercase
docker push ghcr.io/$repo_name_lower/gh-runner-self:latest

View File

@ -1,29 +0,0 @@
name: Delete JSON date PR Branch
on:
pull_request:
types: [closed]
branches:
- main
jobs:
delete_branch:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: runner-cluster-htl-set
steps:
- name: Checkout the code
uses: actions/checkout@v3
- name: Delete PR Update Branch
if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'pr-update-json-')
run: |
PR_BRANCH="${{ github.event.pull_request.head.ref }}"
echo "Deleting branch $PR_BRANCH..."
# Avoid deleting the default branch (e.g., main)
if [[ "$PR_BRANCH" != "main" ]]; then
git push origin --delete "$PR_BRANCH"
else
echo "Skipping deletion of the main branch"
fi

View File

@ -7,12 +7,14 @@ on:
branches: ["main"]
paths:
- frontend/**
- json/**
pull_request:
branches: ["main"]
types: [opened, synchronize, reopened, edited]
paths:
- frontend/**
- json/**
workflow_dispatch:
@ -25,8 +27,7 @@ concurrency:
jobs:
build:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: runner-cluster-htl-set
runs-on: ubuntu-latest
defaults:
run:
working-directory: frontend # Set default working directory for all run steps
@ -64,7 +65,7 @@ jobs:
deploy:
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/main' && github.repository == 'community-scripts/ProxmoxVE'
if: github.ref == 'refs/heads/main'
permissions:
pages: write
id-token: write

View File

@ -1,47 +1,25 @@
name: Create Daily Release
name: Create new release
on:
schedule:
- cron: '1 0 * * *' # Runs daily at 00:01 UTC
workflow_dispatch:
# Runs "At 00:01 every night" (UTC)
- cron: '1 0 * * *'
jobs:
create-daily-release:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: runner-cluster-htl-set
create-new-release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout repository
- name: Checkout code
uses: actions/checkout@v4
- name: Clean CHANGELOG (remove HTML header)
run: sed -n '/^## /,$p' CHANGELOG.md > changelog_cleaned.md
- name: Extract relevant changelog section
run: |
YESTERDAY=$(date -u --date="yesterday" +%Y-%m-%d)
echo "Checking for changes on: $YESTERDAY"
# Extract the section from "## $YESTERDAY" until the next "## YYYY-MM-DD"
sed -n "/^## $YESTERDAY/,/^## [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}/p" changelog_cleaned.md | head -n -1 > changelog_tmp_full.md
# Truncate the extracted section to 5000 characters
head -c 5000 changelog_tmp_full.md > changelog_tmp.md
echo "=== Extracted Changelog ==="
cat changelog_tmp.md
echo "==========================="
# Abort if no content was found
if [ ! -s changelog_tmp.md ]; then
echo "No changes found for $YESTERDAY, skipping release."
exit 0
fi
- name: Create GitHub release
- name: Parse CHANGELOG.md for yesterday's entries and create a new release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
YESTERDAY=$(date -u --date="yesterday" +%Y-%m-%d)
gh release create "$YESTERDAY" -t "$YESTERDAY" -F changelog_tmp.md
YESTERDAY_CHANGELOG_NOTES=$(awk '/^## '"$YESTERDAY"'/ {f=1; next} f && /^## [0-9]{4}-[0-9]{2}-[0-9]{2}/ {f=0} f && !/^## / {print}' CHANGELOG.md)
if [ -n "$YESTERDAY_CHANGELOG_NOTES" ]; then
gh release create "$YESTERDAY" -t "$YESTERDAY" -n "$YESTERDAY_CHANGELOG_NOTES" --latest
fi

View File

@ -1,175 +0,0 @@
name: Run Scripts on PVE Node for testing
permissions:
pull-requests: write
on:
pull_request_target:
branches:
- main
paths:
- "install/**.sh"
- "ct/**.sh"
jobs:
run-install-script:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: pvenode
steps:
- name: Checkout PR branch
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
fetch-depth: 0
- name: Add Git safe directory
run: |
git config --global --add safe.directory /__w/ProxmoxVE/ProxmoxVE
- name: Set up GH_TOKEN
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "GH_TOKEN=${GH_TOKEN}" >> $GITHUB_ENV
- name: Get Changed Files
run: |
CHANGED_FILES=$(gh pr diff ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --name-only)
CHANGED_FILES=$(echo "$CHANGED_FILES" | tr '\n' ' ')
echo "Changed files: $CHANGED_FILES"
echo "SCRIPT=$CHANGED_FILES" >> $GITHUB_ENV
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get scripts
id: check-install-script
run: |
ALL_FILES=()
ADDED_FILES=()
for FILE in ${{ env.SCRIPT }}; do
if [[ $FILE =~ ^install/.*-install\.sh$ ]] || [[ $FILE =~ ^ct/.*\.sh$ ]]; then
STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
if [[ ! " ${ADDED_FILES[@]} " =~ " $STRIPPED_NAME " ]]; then
ALL_FILES+=("$FILE")
ADDED_FILES+=("$STRIPPED_NAME") # Mark this base file as added (without the path)
fi
fi
done
ALL_FILES=$(echo "${ALL_FILES[@]}" | xargs)
echo "$ALL_FILES"
echo "ALL_FILES=$ALL_FILES" >> $GITHUB_ENV
- name: Run scripts
id: run-install
continue-on-error: true
run: |
set +e
#run for each files in /ct
for FILE in ${{ env.ALL_FILES }}; do
STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
echo "Running Test for: $STRIPPED_NAME"
if grep -E -q 'read\s+-r\s+-p\s+".*"\s+\w+' "$FILE"; then
echo "The script contains an interactive prompt. Skipping execution."
continue
fi
if [[ $FILE =~ ^install/.*-install\.sh$ ]]; then
CT_SCRIPT="ct/$STRIPPED_NAME.sh"
if [[ ! -f $CT_SCRIPT ]]; then
echo "No CT script found for $STRIPPED_NAME"
ERROR_MSG="No CT script found for $FILE"
echo "$ERROR_MSG" > result_$STRIPPED_NAME.log
continue
fi
if grep -E -q 'read\s+-r\s+-p\s+".*"\s+\w+' "install/$STRIPPED_NAME-install.sh"; then
echo "The script contains an interactive prompt. Skipping execution."
continue
fi
echo "Found CT script for $STRIPPED_NAME"
chmod +x "$CT_SCRIPT"
RUNNING_FILE=$CT_SCRIPT
elif [[ $FILE =~ ^ct/.*\.sh$ ]]; then
INSTALL_SCRIPT="install/$STRIPPED_NAME-install.sh"
if [[ ! -f $INSTALL_SCRIPT ]]; then
echo "No install script found for $STRIPPED_NAME"
ERROR_MSG="No install script found for $FILE"
echo "$ERROR_MSG" > result_$STRIPPED_NAME.log
continue
fi
echo "Found install script for $STRIPPED_NAME"
chmod +x "$INSTALL_SCRIPT"
RUNNING_FILE=$FILE
if grep -E -q 'read\s+-r\s+-p\s+".*"\s+\w+' "ct/$STRIPPED_NAME.sh"; then
echo "The script contains an interactive prompt. Skipping execution."
continue
fi
fi
git remote add community-scripts https://github.com/community-scripts/ProxmoxVE.git
git fetch community-scripts
rm -f .github/workflows/scripts/app-test/pr-build.func || true
rm -f .github/workflows/scripts/app-test/pr-install.func || true
rm -f .github/workflows/scripts/app-test/pr-alpine-install.func || true
rm -f .github/workflows/scripts/app-test/pr-create-lxc.sh || true
git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-build.func
git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-install.func
git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-alpine-install.func
git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-create-lxc.sh
chmod +x $RUNNING_FILE
chmod +x .github/workflows/scripts/app-test/pr-create-lxc.sh
chmod +x .github/workflows/scripts/app-test/pr-install.func
chmod +x .github/workflows/scripts/app-test/pr-alpine-install.func
chmod +x .github/workflows/scripts/app-test/pr-build.func
sed -i 's|source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)|source .github/workflows/scripts/app-test/pr-build.func|g' "$RUNNING_FILE"
echo "Executing $RUNNING_FILE"
ERROR_MSG=$(./$RUNNING_FILE 2>&1 > /dev/null)
echo "Finished running $FILE"
if [ -n "$ERROR_MSG" ]; then
echo "ERROR in $STRIPPED_NAME: $ERROR_MSG"
echo "$ERROR_MSG" > result_$STRIPPED_NAME.log
fi
done
set -e # Restore exit-on-error
- name: Cleanup PVE Node
run: |
containers=$(pct list | tail -n +2 | awk '{print $0 " " $4}' | awk '{print $1}')
for container_id in $containers; do
status=$(pct status $container_id | awk '{print $2}')
if [[ $status == "running" ]]; then
pct stop $container_id
pct destroy $container_id
fi
done
- name: Post error comments
run: |
ERROR="false"
SEARCH_LINE=".github/workflows/scripts/app-test/pr-build.func: line 255:"
# Get all existing comments on the PR
EXISTING_COMMENTS=$(gh pr view ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --json comments --jq '.comments[].body')
for FILE in ${{ env.ALL_FILES }}; do
STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
if [[ ! -f result_$STRIPPED_NAME.log ]]; then
continue
fi
ERROR_MSG=$(cat result_$STRIPPED_NAME.log)
if [ -n "$ERROR_MSG" ]; then
CLEANED_ERROR_MSG=$(echo "$ERROR_MSG" | sed "s|$SEARCH_LINE.*||")
COMMENT_BODY=":warning: The script _**$FILE**_ failed with the following message: <br> <div><strong>${CLEANED_ERROR_MSG}</strong></div>"
# Check if the comment already exists
if echo "$EXISTING_COMMENTS" | grep -qF "$COMMENT_BODY"; then
echo "Skipping duplicate comment for $FILE"
else
echo "Posting error message for $FILE"
gh pr comment ${{ github.event.pull_request.number }} \
--repo ${{ github.repository }} \
--body "$COMMENT_BODY"
ERROR="true"
fi
fi
done
echo "ERROR=$ERROR" >> $GITHUB_ENV

View File

@ -1,243 +0,0 @@
name: Script Format Check
permissions:
pull-requests: write
on:
pull_request_target:
branches:
- main
paths:
- "install/*.sh"
- "ct/*.sh"
jobs:
run-install-script:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: pvenode
steps:
- name: Checkout PR branch (supports forks)
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
fetch-depth: 0
- name: Add Git safe directory
run: |
git config --global --add safe.directory /__w/ProxmoxVE/ProxmoxVE
- name: Set up GH_TOKEN
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "GH_TOKEN=${GH_TOKEN}" >> $GITHUB_ENV
- name: Get Changed Files
run: |
CHANGED_FILES=$(gh pr diff ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --name-only)
CHANGED_FILES=$(echo "$CHANGED_FILES" | tr '\n' ' ')
echo "Changed files: $CHANGED_FILES"
echo "SCRIPT=$CHANGED_FILES" >> $GITHUB_ENV
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check scripts
id: run-install
continue-on-error: true
run: |
for FILE in ${{ env.SCRIPT }}; do
STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
echo "Running Test for: $STRIPPED_NAME"
FILE_STRIPPED="${FILE##*/}"
LOG_FILE="result_$FILE_STRIPPED.log"
if [[ $FILE =~ ^ct/.*\.sh$ ]]; then
FIRST_LINE=$(sed -n '1p' "$FILE")
[[ "$FIRST_LINE" != "#!/usr/bin/env bash" ]] && echo "Line 1 was $FIRST_LINE | Should be: #!/usr/bin/env bash" >> "$LOG_FILE"
SECOND_LINE=$(sed -n '2p' "$FILE")
[[ "$SECOND_LINE" != "source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)" ]] &&
echo "Line 2 was $SECOND_LINE | Should be: source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)" >> "$LOG_FILE"
THIRD_LINE=$(sed -n '3p' "$FILE")
if ! [[ "$THIRD_LINE" =~ ^#\ Copyright\ \(c\)\ [0-9]{4}-[0-9]{4}\ community-scripts\ ORG$ || "$THIRD_LINE" =~ ^Copyright\ \(c\)\ [0-9]{4}-[0-9]{4}\ tteck$ ]]; then
echo "Line 3 was $THIRD_LINE | Should be: # Copyright (c) 2021-2025 community-scripts ORG" >> "$LOG_FILE"
fi
EXPECTED_AUTHOR="# Author:"
EXPECTED_LICENSE="# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE"
EXPECTED_SOURCE="# Source:"
EXPECTED_EMPTY=""
for i in {4..7}; do
LINE=$(sed -n "${i}p" "$FILE")
case $i in
4)
[[ $LINE == $EXPECTED_AUTHOR* ]] || printf "Line %d was: '%s' | Should start with: '%s'\n" "$i" "$LINE" "$EXPECTED_AUTHOR" >> $LOG_FILE
;;
5)
[[ "$LINE" == "$EXPECTED_LICENSE" ]] || printf "Line %d was: '%s' | Should be: '%s'\n" "$i" "$LINE" "$EXPECTED_LICENSE" >> $LOG_FILE
;;
6)
[[ $LINE == $EXPECTED_SOURCE* ]] || printf "Line %d was: '%s' | Should start with: '%s'\n" "$i" "$LINE" "$EXPECTED_SOURCE" >> $LOG_FILE
;;
7)
[[ -z $LINE ]] || printf "Line %d was: '%s' | Should be empty\n" "$i" "$LINE" >> $LOG_FILE
;;
esac
done
EXPECTED_PREFIXES=(
"APP="
"var_tags="
"var_cpu=" # Must be a number
"var_ram=" # Must be a number
"var_disk=" # Must be a number
"var_os=" # Must be debian, alpine, or ubuntu
"var_version="
"var_unprivileged=" # Must be 0 or 1
)
for i in {8..15}; do
LINE=$(sed -n "${i}p" "$FILE")
INDEX=$((i - 8))
case $INDEX in
2|3|4) # var_cpu, var_ram, var_disk (must be numbers)
if [[ "$LINE" =~ ^${EXPECTED_PREFIXES[$INDEX]}([0-9]+)$ ]]; then
continue # Valid
else
echo "Line $i was '$LINE' | Should be: '${EXPECTED_PREFIXES[$INDEX]}<NUMBER>'" >> "$LOG_FILE"
fi
;;
5) # var_os (must be debian, alpine, or ubuntu)
if [[ "$LINE" =~ ^var_os=(debian|alpine|ubuntu)$ ]]; then
continue # Valid
else
echo "Line $i was '$LINE' | Should be: 'var_os=[debian|alpine|ubuntu]'" >> "$LOG_FILE"
fi
;;
7) # var_unprivileged (must be 0 or 1)
if [[ "$LINE" =~ ^var_unprivileged=[01]$ ]]; then
continue # Valid
else
echo "Line $i was '$LINE' | Should be: 'var_unprivileged=[0|1]'" >> "$LOG_FILE"
fi
;;
*) # Other lines (must start with expected prefix)
if [[ "$LINE" == ${EXPECTED_PREFIXES[$INDEX]}* ]]; then
continue # Valid
else
echo "Line $i was '$LINE' | Should start with '${EXPECTED_PREFIXES[$INDEX]}'" >> "$LOG_FILE"
fi
;;
esac
done
for i in {16..20}; do
LINE=$(sed -n "${i}p" "$FILE")
EXPECTED=(
"header_info \"$APP\""
"variables"
"color"
"catch_errors"
"function update_script() {"
)
[[ "$LINE" != "${EXPECTED[$((i-16))]}" ]] && echo "Line $i was $LINE | Should be: ${EXPECTED[$((i-16))]}" >> "$LOG_FILE"
done
cat "$LOG_FILE"
elif [[ $FILE =~ ^install/.*-install\.sh$ ]]; then
FIRST_LINE=$(sed -n '1p' "$FILE")
[[ "$FIRST_LINE" != "#!/usr/bin/env bash" ]] && echo "Line 1 was $FIRST_LINE | Should be: #!/usr/bin/env bash" >> "$LOG_FILE"
SECOND_LINE=$(sed -n '2p' "$FILE")
[[ -n "$SECOND_LINE" ]] && echo "Line 2 should be empty" >> "$LOG_FILE"
THIRD_LINE=$(sed -n '3p' "$FILE")
if ! [[ "$THIRD_LINE" =~ ^#\ Copyright\ \(c\)\ [0-9]{4}-[0-9]{4}\ community-scripts\ ORG$ || "$THIRD_LINE" =~ ^Copyright\ \(c\)\ [0-9]{4}-[0-9]{4}\ tteck$ ]]; then
echo "Line 3 was $THIRD_LINE | Should be: # Copyright (c) 2021-2025 community-scripts ORG" >> "$LOG_FILE"
fi
EXPECTED_AUTHOR="# Author:"
EXPECTED_LICENSE="# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE"
EXPECTED_SOURCE="# Source:"
EXPECTED_EMPTY=""
for i in {4..7}; do
LINE=$(sed -n "${i}p" "$FILE")
case $i in
4)
[[ $LINE == $EXPECTED_AUTHOR* ]] || printf "Line %d was: '%s' | Should start with: '%s'\n" "$i" "$LINE" "$EXPECTED_AUTHOR" >> $LOG_FILE
;;
5)
[[ "$LINE" == "$EXPECTED_LICENSE" ]] || printf "Line %d was: '%s' | Should be: '%s'\n" "$i" "$LINE" "$EXPECTED_LICENSE" >> $LOG_FILE
;;
6)
[[ $LINE == $EXPECTED_SOURCE* ]] || printf "Line %d was: '%s' | Should start with: '%s'\n" "$i" "$LINE" "$EXPECTED_SOURCE" >> $LOG_FILE
;;
7)
[[ -z $LINE ]] || printf "Line %d was: '%s' | Should be empty\n" "$i" "$LINE" >> $LOG_FILE
;;
esac
done
[[ "$(sed -n '8p' "$FILE")" != 'source /dev/stdin <<< "$FUNCTIONS_FILE_PATH"' ]] && echo 'Line 8 should be: source /dev/stdin <<< "$FUNCTIONS_FILE_PATH"' >> "$LOG_FILE"
for i in {9..14}; do
LINE=$(sed -n "${i}p" "$FILE")
EXPECTED=(
"color"
"verb_ip6"
"catch_errors"
"setting_up_container"
"network_check"
"update_os"
)
[[ "$LINE" != "${EXPECTED[$((i-9))]}" ]] && echo "Line $i was $LINE | Should be: ${EXPECTED[$((i-9))]}" >> "$LOG_FILE"
done
[[ -n "$(sed -n '15p' "$FILE")" ]] && echo "Line 15 should be empty" >> "$LOG_FILE"
[[ "$(sed -n '16p' "$FILE")" != 'msg_info "Installing Dependencies"' ]] && echo 'Line 16 should be: msg_info "Installing Dependencies"' >> "$LOG_FILE"
LAST_3_LINES=$(tail -n 3 "$FILE")
[[ "$LAST_3_LINES" != *"$STD apt-get -y autoremove"* ]] && echo 'Third to last line should be: $STD apt-get -y autoremove' >> "$LOG_FILE"
[[ "$LAST_3_LINES" != *"$STD apt-get -y autoclean"* ]] && echo 'Second to last line should be: $STD apt-get -y clean' >> "$LOG_FILE"
[[ "$LAST_3_LINES" != *'msg_ok "Cleaned"'* ]] && echo 'Last line should be: msg_ok "Cleaned"' >> "$LOG_FILE"
cat "$LOG_FILE"
fi
done
- name: Post error comments
run: |
ERROR="false"
for FILE in ${{ env.SCRIPT }}; do
FILE_STRIPPED="${FILE##*/}"
LOG_FILE="result_$FILE_STRIPPED.log"
echo $LOG_FILE
if [[ ! -f $LOG_FILE ]]; then
continue
fi
ERROR_MSG=$(cat $LOG_FILE)
if [ -n "$ERROR_MSG" ]; then
echo "Posting error message for $FILE"
echo ${ERROR_MSG}
gh pr comment ${{ github.event.pull_request.number }} \
--repo ${{ github.repository }} \
--body ":warning: The script _**$FILE**_ has the following formatting errors: <br> <div><strong>${ERROR_MSG}</strong></div>"
ERROR="true"
fi
done
echo "ERROR=$ERROR" >> $GITHUB_ENV
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Fail if error
if: ${{ env.ERROR == 'true' }}
run: exit 1

View File

@ -1,85 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Michel Roegl-Brunner (michelroegl-brunner)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
color() {
return
}
catch_errors() {
set -Eeuo pipefail
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
}
# This function handles errors
error_handler() {
local line_number="$1"
local command="$2"
SCRIPT_NAME=$(basename "$0")
local error_message="$SCRIPT_NAME: Failure in line $line_number while executing command $command"
echo -e "\n$error_message"
exit 0
}
verb_ip6() {
STD=""
return
}
msg_info() {
local msg="$1"
echo -ne "${msg}\n"
}
msg_ok() {
local msg="$1"
echo -e "${msg}\n"
}
msg_error() {
local msg="$1"
echo -e "${msg}\n"
}
RETRY_NUM=10
RETRY_EVERY=3
i=$RETRY_NUM
setting_up_container() {
while [ $i -gt 0 ]; do
if [ "$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1)" != "" ]; then
break
fi
echo 1>&2 -en "No Network! "
sleep $RETRY_EVERY
i=$((i - 1))
done
if [ "$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1)" = "" ]; then
echo 1>&2 -e "\n No Network After $RETRY_NUM Tries"
echo -e "Check Network Settings"
exit 1
fi
msg_ok "Set up Container OS"
msg_ok "Network Connected: $(hostname -i)"
}
network_check() {
RESOLVEDIP=$(getent hosts github.com | awk '{ print $1 }')
if [[ -z "$RESOLVEDIP" ]]; then msg_error "DNS Lookup Failure"; else msg_ok "DNS Resolved github.com to $RESOLVEDIP"; fi
set -e
}
update_os() {
msg_info "Updating Container OS"
$STD apk -U upgrade
msg_ok "Updated Container OS"
}
motd_ssh() {
return
}
customize() {
return
}

View File

@ -1,260 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Michel Roegl-Brunner (michelroegl-brunner)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
variables() {
NSAPP=$(echo ${APP,,} | tr -d ' ') # This function sets the NSAPP variable by converting the value of the APP variable to lowercase and removing any spaces.
var_install="${NSAPP}-install" # sets the var_install variable by appending "-install" to the value of NSAPP.
}
NEXTID=$(pvesh get /cluster/nextid)
timezone=$(cat /etc/timezone)
header_info() {
return
}
base_settings() {
# Default Settings
CT_TYPE="1"
DISK_SIZE="4"
CORE_COUNT="1"
RAM_SIZE="1024"
VERBOSE="no"
PW=""
CT_ID=$NEXTID
HN=$NSAPP
BRG="vmbr0"
NET="dhcp"
GATE=""
APT_CACHER=""
APT_CACHER_IP=""
DISABLEIP6="no"
MTU=""
SD=""
NS=""
MAC=""
VLAN=""
SSH="no"
SSH_AUTHORIZED_KEY=""
TAGS="community-script;"
# Override default settings with variables from ct script
CT_TYPE=${var_unprivileged:-$CT_TYPE}
DISK_SIZE=${var_disk:-$DISK_SIZE}
CORE_COUNT=${var_cpu:-$CORE_COUNT}
RAM_SIZE=${var_ram:-$RAM_SIZE}
VERB=${var_verbose:-$VERBOSE}
TAGS="${TAGS}${var_tags:-}"
# Since these 2 are only defined outside of default_settings function, we add a temporary fallback. TODO: To align everything, we should add these as constant variables (e.g. OSTYPE and OSVERSION), but that would currently require updating the default_settings function for all existing scripts
if [ -z "$var_os" ]; then
var_os="debian"
fi
if [ -z "$var_version" ]; then
var_version="12"
fi
}
color() {
# Colors
YW=$(echo "\033[33m")
YWB=$(echo "\033[93m")
BL=$(echo "\033[36m")
RD=$(echo "\033[01;31m")
BGN=$(echo "\033[4;92m")
GN=$(echo "\033[1;92m")
DGN=$(echo "\033[32m")
# Formatting
CL=$(echo "\033[m")
UL=$(echo "\033[4m")
BOLD=$(echo "\033[1m")
BFR="\\r\\033[K"
HOLD=" "
TAB=" "
# Icons
CM="${TAB}✔️${TAB}${CL}"
CROSS="${TAB}✖️${TAB}${CL}"
INFO="${TAB}💡${TAB}${CL}"
OS="${TAB}🖥️${TAB}${CL}"
OSVERSION="${TAB}🌟${TAB}${CL}"
CONTAINERTYPE="${TAB}📦${TAB}${CL}"
DISKSIZE="${TAB}💾${TAB}${CL}"
CPUCORE="${TAB}🧠${TAB}${CL}"
RAMSIZE="${TAB}🛠️${TAB}${CL}"
SEARCH="${TAB}🔍${TAB}${CL}"
VERIFYPW="${TAB}🔐${TAB}${CL}"
CONTAINERID="${TAB}🆔${TAB}${CL}"
HOSTNAME="${TAB}🏠${TAB}${CL}"
BRIDGE="${TAB}🌉${TAB}${CL}"
NETWORK="${TAB}📡${TAB}${CL}"
GATEWAY="${TAB}🌐${TAB}${CL}"
DISABLEIPV6="${TAB}🚫${TAB}${CL}"
DEFAULT="${TAB}⚙️${TAB}${CL}"
MACADDRESS="${TAB}🔗${TAB}${CL}"
VLANTAG="${TAB}🏷️${TAB}${CL}"
ROOTSSH="${TAB}🔑${TAB}${CL}"
CREATING="${TAB}🚀${TAB}${CL}"
ADVANCED="${TAB}🧩${TAB}${CL}"
}
catch_errors() {
set -Eeuo pipefail
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
}
# This function handles errors
error_handler() {
local line_number="$1"
local command="$2"
SCRIPT_NAME=$(basename "$0")
local error_message="$SCRIPT_NAME: Failure in line $line_number while executing command $command"
echo -e "\n$error_message"
exit 100
}
msg_info() {
local msg="$1"
echo -ne "${msg}\n"
}
msg_ok() {
local msg="$1"
echo -e "${msg}\n"
}
msg_error() {
local msg="$1"
echo -e "${msg}\n"
}
start() {
base_settings
return
}
build_container() {
# if [ "$VERB" == "yes" ]; then set -x; fi
if [ "$CT_TYPE" == "1" ]; then
FEATURES="keyctl=1,nesting=1"
else
FEATURES="nesting=1"
fi
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if [ "$var_os" == "alpine" ]; then
export FUNCTIONS_FILE_PATH="$(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/.github/workflows/scripts/app-test/pr-alpine-install.func)"
else
export FUNCTIONS_FILE_PATH="$(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/.github/workflows/scripts/app-test/pr-install.func)"
fi
export CACHER="$APT_CACHER"
export CACHER_IP="$APT_CACHER_IP"
export tz=""
export DISABLEIPV6="$DISABLEIP6"
export APPLICATION="$APP"
export app="$NSAPP"
export PASSWORD="$PW"
export VERBOSE="$VERB"
export SSH_ROOT="${SSH}"
export SSH_AUTHORIZED_KEY
export CTID="$CT_ID"
export CTTYPE="$CT_TYPE"
export PCT_OSTYPE="$var_os"
export PCT_OSVERSION="$var_version"
export PCT_DISK_SIZE="$DISK_SIZE"
export tz="$timezone"
export PCT_OPTIONS="
-features $FEATURES
-hostname $HN
-tags $TAGS
$SD
$NS
-net0 name=eth0,bridge=$BRG$MAC,ip=$NET$GATE$VLAN$MTU
-onboot 1
-cores $CORE_COUNT
-memory $RAM_SIZE
-unprivileged $CT_TYPE
$PW
"
echo "Container ID: $CTID"
# This executes create_lxc.sh and creates the container and .conf file
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/.github/workflows/scripts/app-test/pr-create-lxc.sh)"
LXC_CONFIG=/etc/pve/lxc/${CTID}.conf
if [ "$CT_TYPE" == "0" ]; then
cat <<EOF >>$LXC_CONFIG
# USB passthrough
lxc.cgroup2.devices.allow: a
lxc.cap.drop:
lxc.cgroup2.devices.allow: c 188:* rwm
lxc.cgroup2.devices.allow: c 189:* rwm
lxc.mount.entry: /dev/serial/by-id dev/serial/by-id none bind,optional,create=dir
lxc.mount.entry: /dev/ttyUSB0 dev/ttyUSB0 none bind,optional,create=file
lxc.mount.entry: /dev/ttyUSB1 dev/ttyUSB1 none bind,optional,create=file
lxc.mount.entry: /dev/ttyACM0 dev/ttyACM0 none bind,optional,create=file
lxc.mount.entry: /dev/ttyACM1 dev/ttyACM1 none bind,optional,create=file
EOF
fi
if [ "$CT_TYPE" == "0" ]; then
if [[ "$APP" == "Channels" || "$APP" == "Emby" || "$APP" == "ErsatzTV" || "$APP" == "Frigate" || "$APP" == "Jellyfin" || "$APP" == "Plex" || "$APP" == "Scrypted" || "$APP" == "Tdarr" || "$APP" == "Unmanic" || "$APP" == "Ollama" ]]; then
cat <<EOF >>$LXC_CONFIG
# VAAPI hardware transcoding
lxc.cgroup2.devices.allow: c 226:0 rwm
lxc.cgroup2.devices.allow: c 226:128 rwm
lxc.cgroup2.devices.allow: c 29:0 rwm
lxc.mount.entry: /dev/fb0 dev/fb0 none bind,optional,create=file
lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file
EOF
fi
else
if [[ "$APP" == "Channels" || "$APP" == "Emby" || "$APP" == "ErsatzTV" || "$APP" == "Frigate" || "$APP" == "Jellyfin" || "$APP" == "Plex" || "$APP" == "Scrypted" || "$APP" == "Tdarr" || "$APP" == "Unmanic" || "$APP" == "Ollama" ]]; then
if [[ -e "/dev/dri/renderD128" ]]; then
if [[ -e "/dev/dri/card0" ]]; then
cat <<EOF >>$LXC_CONFIG
# VAAPI hardware transcoding
dev0: /dev/dri/card0,gid=44
dev1: /dev/dri/renderD128,gid=104
EOF
else
cat <<EOF >>$LXC_CONFIG
# VAAPI hardware transcoding
dev0: /dev/dri/card1,gid=44
dev1: /dev/dri/renderD128,gid=104
EOF
fi
fi
fi
fi
# This starts the container and executes <app>-install.sh
msg_info "Starting LXC Container"
pct start "$CTID"
msg_ok "Started LXC Container"
if [[ ! -f "/root/actions-runner/_work/ProxmoxVE/ProxmoxVE/install/$var_install.sh" ]]; then
msg_error "No install script found for $APP"
exit 1
fi
if [ "$var_os" == "alpine" ]; then
sleep 3
pct exec "$CTID" -- /bin/sh -c 'cat <<EOF >/etc/apk/repositories
http://dl-cdn.alpinelinux.org/alpine/latest-stable/main
http://dl-cdn.alpinelinux.org/alpine/latest-stable/community
EOF'
pct exec "$CTID" -- ash -c "apk add bash >/dev/null"
fi
lxc-attach -n "$CTID" -- bash -c "$(cat /root/actions-runner/_work/ProxmoxVE/ProxmoxVE/install/$var_install.sh)"
}
description() {
IP=$(pct exec "$CTID" ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1)
}

View File

@ -1,163 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Michel Roegl-Brunner (michelroegl-brunner)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
color() {
return
}
catch_errors() {
set -Eeuo pipefail
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
}
# This function handles errors
error_handler() {
local exit_code="$?"
local line_number="$1"
local command="$2"
local error_message="Failure in line $line_number: exit code $exit_code: while executing command $command"
echo -e "\n$error_message"
exit 100
}
verb_ip6() {
return
}
msg_info() {
local msg="$1"
echo -ne "${msg}\n"
}
msg_ok() {
local msg="$1"
echo -e "${msg}\n"
}
msg_error() {
local msg="$1"
echo -e "${msg}\n"
}
VALIDCT=$(pvesm status -content rootdir | awk 'NR>1')
if [ -z "$VALIDCT" ]; then
msg_error "Unable to detect a valid Container Storage location."
exit 1
fi
VALIDTMP=$(pvesm status -content vztmpl | awk 'NR>1')
if [ -z "$VALIDTMP" ]; then
msg_error "Unable to detect a valid Template Storage location."
exit 1
fi
function select_storage() {
local CLASS=$1
local CONTENT
local CONTENT_LABEL
case $CLASS in
container)
CONTENT='rootdir'
CONTENT_LABEL='Container'
;;
template)
CONTENT='vztmpl'
CONTENT_LABEL='Container template'
;;
*) false || {
msg_error "Invalid storage class."
exit 201
} ;;
esac
# This Queries all storage locations
local -a MENU
while read -r line; do
local TAG=$(echo $line | awk '{print $1}')
local TYPE=$(echo $line | awk '{printf "%-10s", $2}')
local FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
local ITEM="Type: $TYPE Free: $FREE "
local OFFSET=2
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
local MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
fi
MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content $CONTENT | awk 'NR>1')
# Select storage location
if [ $((${#MENU[@]} / 3)) -eq 1 ]; then
printf ${MENU[0]}
else
msg_error "STORAGE ISSUES!"
exit 202
fi
}
[[ "${CTID:-}" ]] || {
msg_error "You need to set 'CTID' variable."
exit 203
}
[[ "${PCT_OSTYPE:-}" ]] || {
msg_error "You need to set 'PCT_OSTYPE' variable."
exit 204
}
# Test if ID is valid
[ "$CTID" -ge "100" ] || {
msg_error "ID cannot be less than 100."
exit 205
}
# Test if ID is in use
if pct status $CTID &>/dev/null; then
echo -e "ID '$CTID' is already in use."
unset CTID
msg_error "Cannot use ID that is already in use."
exit 206
fi
TEMPLATE_STORAGE=$(select_storage template) || exit
CONTAINER_STORAGE=$(select_storage container) || exit
pveam update >/dev/null
TEMPLATE_SEARCH=${PCT_OSTYPE}-${PCT_OSVERSION:-}
mapfile -t TEMPLATES < <(pveam available -section system | sed -n "s/.*\($TEMPLATE_SEARCH.*\)/\1/p" | sort -t - -k 2 -V)
[ ${#TEMPLATES[@]} -gt 0 ] || {
msg_error "Unable to find a template when searching for '$TEMPLATE_SEARCH'."
exit 207
}
TEMPLATE="${TEMPLATES[-1]}"
TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
if ! pveam list "$TEMPLATE_STORAGE" | grep -q "$TEMPLATE"; then
[[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null ||
{
msg_error "A problem occurred while downloading the LXC template."
exit 208
}
fi
grep -q "root:100000:65536" /etc/subuid || echo "root:100000:65536" >>/etc/subuid
grep -q "root:100000:65536" /etc/subgid || echo "root:100000:65536" >>/etc/subgid
PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
[[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs "$CONTAINER_STORAGE:${PCT_DISK_SIZE:-8}")
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
[[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null ||
{
msg_error "A problem occurred while re-downloading the LXC template."
exit 208
}
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
msg_error "A problem occurred while trying to create container after re-downloading template."
exit 200
fi
fi

View File

@ -1,93 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Michel Roegl-Brunner (michelroegl-brunner)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
color() {
return
}
catch_errors() {
set -Euo pipefail
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
}
error_handler() {
local line_number="$1"
local command="$2"
local error_message="Failure in line $line_number while executing command '$command'"
echo -e "\n$error_message\n" >&2
exit 1
}
verb_ip6() {
STD="silent"
silent() {
"$@" >/dev/null 2>&1 || error_handler "${BASH_LINENO[0]}" "$*"
}
return
}
msg_info() {
local msg="$1"
echo -ne "${msg}\n"
}
msg_ok() {
local msg="$1"
echo -e "${msg}\n"
}
msg_error() {
local msg="$1"
echo -e "${msg}\n"
}
RETRY_NUM=10
RETRY_EVERY=3
setting_up_container() {
sed -i "/$LANG/ s/\(^# \)//" /etc/locale.gen
locale_line=$(grep -v '^#' /etc/locale.gen | grep -E '^[a-zA-Z]' | awk '{print $1}' | head -n 1)
echo "LANG=${locale_line}" >/etc/default/locale
locale-gen >/dev/null
export LANG=${locale_line}
echo $tz >/etc/timezone
ln -sf /usr/share/zoneinfo/$tz /etc/localtime
for ((i = RETRY_NUM; i > 0; i--)); do
if [ "$(hostname -I)" != "" ]; then
break
fi
sleep $RETRY_EVERY
done
if [ "$(hostname -I)" = "" ]; then
echo 1>&2 -e "\nNo Network After $RETRY_NUM Tries"
echo -e "Check Network Settings"
exit 101
fi
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
systemctl disable -q --now systemd-networkd-wait-online.service
}
network_check() {
RESOLVEDIP=$(getent hosts github.com | awk '{ print $1 }')
if [[ -z "$RESOLVEDIP" ]]; then msg_error "DNS Lookup Failure"; else msg_ok "DNS Resolved github.com to $RESOLVEDIP"; fi
set -e
}
update_os() {
export DEBIAN_FRONTEND=noninteractive
apt-get update >/dev/null 2>&1
apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade >/dev/null
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
}
motd_ssh() {
return
}
customize() {
return
}

37
.github/workflows/scripts/generate-app-headers.sh vendored Executable file → Normal file
View File

@ -1,34 +1,33 @@
#!/usr/bin/env bash
# Base directory for headers
headers_dir="./ct/headers"
output_file="./misc/.app-headers"
> "$output_file" # Clear or create the file
# Ensure the headers directory exists and clear it
mkdir -p "$headers_dir"
rm -f "$headers_dir"/*
current_date=$(date +"%m-%d-%Y")
# Header with date
{
echo "### Generated on $current_date"
echo "##################################################"
echo
} >> "$output_file"
# Find all .sh files in ./ct directory, sorted alphabetically
# Find only regular .sh files in ./ct, sort them alphabetically
find ./ct -type f -name "*.sh" | sort | while read -r script; do
# Extract the APP name from the APP line
app_name=$(grep -oP '^APP="\K[^"]+' "$script" 2>/dev/null)
if [[ -n "$app_name" ]]; then
# Define the output file name in the headers directory
output_file="${headers_dir}/$(basename "${script%.*}")"
# Generate figlet output
figlet_output=$(figlet -w 500 -f slant "$app_name")
# Check if figlet output is not empty
if [[ -n "$figlet_output" ]]; then
echo "$figlet_output" > "$output_file"
echo "Generated: $output_file"
else
echo "Figlet failed for $app_name in $script"
fi
figlet_output=$(figlet -f slant "$app_name")
{
echo "### $(basename "$script")"
echo "APP=$app_name"
echo "$figlet_output"
echo
} >> "$output_file"
else
echo "No APP name found in $script, skipping."
fi
done
echo "Completed processing .sh files."
echo "Generated combined file at $output_file"

View File

@ -1,20 +0,0 @@
#!/bin/bash
FILE=$1
TODAY=$(date -u +"%Y-%m-%d")
if [[ -z "$FILE" ]]; then
echo "No file specified. Exiting."
exit 1
fi
if [[ ! -f "$FILE" ]]; then
echo "File $FILE not found. Exiting."
exit 1
fi
DATE_IN_JSON=$(jq -r '.date_created' "$FILE" 2>/dev/null || echo "")
if [[ "$DATE_IN_JSON" != "$TODAY" ]]; then
jq --arg date "$TODAY" '.date_created = $date' "$FILE" >tmp.json && mv tmp.json "$FILE"
fi

View File

@ -11,8 +11,8 @@ for json_file in $json_dir; do
if [[ "$current_json_date" != "$current_date" ]]; then
echo "Updating $json_file with date $current_date"
jq --arg date "$current_date" '.date_created = $date' "$json_file" >temp.json && mv temp.json "$json_file"
jq --arg date "$current_date" '.date_created = $date' "$json_file" > temp.json && mv temp.json "$json_file"
git add "$json_file"
git commit -m "Update date_created to $current_date in $json_file"
else

View File

@ -1,152 +0,0 @@
name: Update JSON Date
on:
push:
branches:
- main
paths:
- "frontend/public/json/**.json"
workflow_dispatch:
jobs:
update-app-files:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: runner-cluster-htl-set
permissions:
contents: write
pull-requests: write
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Generate a token for PR approval and merge
id: generate-token-merge
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.APP_ID_APPROVE_AND_MERGE }}
private-key: ${{ secrets.APP_KEY_APPROVE_AND_MERGE }}
- name: Generate dynamic branch name
id: timestamp
run: echo "BRANCH_NAME=pr-update-json-$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV
- name: Set up GH_TOKEN
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "GH_TOKEN=${GH_TOKEN}" >> $GITHUB_ENV
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 2 # Ensure we have the last two commits
- name: Get Previous Commit
id: prev_commit
run: |
PREV_COMMIT=$(git rev-parse HEAD^)
echo "Previous commit: $PREV_COMMIT"
echo "prev_commit=$PREV_COMMIT" >> $GITHUB_ENV
- name: Get Newly Added JSON Files
id: new_json_files
run: |
git diff --name-only --diff-filter=A ${{ env.prev_commit }} HEAD | grep '^frontend/public/json/.*\.json$' > new_files.txt || true
echo "New files detected:"
cat new_files.txt || echo "No new files."
- name: Disable file mode changes
run: git config core.fileMode false
- name: Set up Git
run: |
git config --global user.name "GitHub Actions"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: Change JSON Date
id: change-json-date
run: |
current_date=$(date +"%Y-%m-%d")
while IFS= read -r file; do
# Skip empty lines
[[ -z "$file" ]] && continue
if [[ -f "$file" ]]; then
echo "Processing $file..."
current_json_date=$(jq -r '.date_created // empty' "$file")
if [[ -z "$current_json_date" || "$current_json_date" != "$current_date" ]]; then
echo "Updating $file with date $current_date"
jq --arg date "$current_date" '.date_created = $date' "$file" > temp.json && mv temp.json "$file"
else
echo "Date in $file is already up to date."
fi
else
echo "Warning: File $file not found!"
fi
done < new_files.txt
rm new_files.txt
- name: Check if there are any changes
run: |
echo "Checking for changes..."
git add -A
git status
if git diff --cached --quiet; then
echo "No changes detected."
echo "changed=false" >> "$GITHUB_ENV"
else
echo "Changes detected:"
git diff --stat --cached
echo "changed=true" >> "$GITHUB_ENV"
fi
# Step 7: Commit and create PR if changes exist
- name: Commit and create PR if changes exist
if: env.changed == 'true'
run: |
git commit -m "Update date in json"
git checkout -b ${{ env.BRANCH_NAME }}
git push origin ${{ env.BRANCH_NAME }}
gh pr create --title "[core] update date in json" \
--body "This PR is auto-generated by a GitHub Action to update the date in json." \
--head ${{ env.BRANCH_NAME }} \
--base main \
--label "automated pr"
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
- name: Approve pull request
if: env.changed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER=$(gh pr list --head "${{ env.BRANCH_NAME }}" --json number --jq '.[].number')
if [ -n "$PR_NUMBER" ]; then
gh pr review $PR_NUMBER --approve
fi
- name: Approve pull request and merge
if: env.changed == 'true'
env:
GH_TOKEN: ${{ steps.generate-token-merge.outputs.token }}
run: |
git config --global user.name "github-actions-automege[bot]"
git config --global user.email "github-actions-automege[bot]@users.noreply.github.com"
PR_NUMBER=$(gh pr list --head "${BRANCH_NAME}" --json number --jq '.[].number')
if [ -n "$PR_NUMBER" ]; then
gh pr review $PR_NUMBER --approve
gh pr merge $PR_NUMBER --squash --admin
fi
- name: No changes detected
if: env.changed == 'false'
run: echo "No changes to commit. Workflow completed successfully."

48
.github/workflows/update_json_date.yml vendored Normal file
View File

@ -0,0 +1,48 @@
name: Update JSON Date
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
list-files:
runs-on: ubuntu-latest
steps:
- name: Checkout PR Branch
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Fetch PR changes
run: |
git remote add fork https://github.com/${{ github.event.pull_request.head.repo.full_name }}.git
git fetch fork ${{ github.event.pull_request.head.ref }}:pullreq
git checkout pullreq
- name: Update JSON
id: changed-files
run: |
FILES=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files --jq '.[].filename' | tr '\n' ' ')
echo "changed_files=${FILES}"
for FILE in $FILES; do
if [[ "$FILE" =~ /(.*)\.json ]]; then
NAME="${BASH_REMATCH[1]}"
else
echo "no new JSON in ${FILES}"
continue
fi
JSON_FILE="json/${NAME}.json"
if [[ -f "$JSON_FILE" ]]; then
echo "Updating date_created in $JSON_FILE"
jq --arg date "$(date +%Y-%m-%d)" '.date_created = $date' "$JSON_FILE" > tmp.json && mv tmp.json "$JSON_FILE"
else
echo "JSON file $FILES not found"
fi
done
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git diff --exit-code || git commit -am "Updating Dates in affected JSON files."
git push
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -5,13 +5,12 @@ on:
paths:
- "ct/*.sh"
- "install/*.sh"
- "frontend/public/json/*.json"
- "json/*.json"
jobs:
check-files:
if: github.repository == 'community-scripts/ProxmoxVE'
name: Check changed files
runs-on: runner-cluster-htl-set
runs-on: ubuntu-latest
permissions:
pull-requests: write
@ -51,13 +50,9 @@ jobs:
NON_COMPLIANT_FILES=""
for FILE in $CHANGED_FILES; do
# Datei "ct/create_lxc.sh" explizit überspringen
if [[ "$FILE" == "ct/create_lxc.sh" ]]; then
continue
fi
BASENAME=$(echo "$(basename "${FILE%.*}")")
if [[ ! "$BASENAME" =~ ^[a-z0-9-]+$ ]]; then
NON_COMPLIANT_FILES="$NON_COMPLIANT_FILES $FILE"
NON_COMPLIANT_FILES="$NON_COMPLIANT_FILES $FILE"
fi
done

77
.gitignore vendored
View File

@ -1,77 +0,0 @@
# General OS files
.DS_Store
Thumbs.db
# Editor & IDE files (keeping .vscode settings but ignoring unnecessary metadata)
!.vscode/
.vscode/*.workspace
.vscode/*.tmp
# Log and Cache files
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Python-specific exclusions
__pycache__/
*.pyc
*.pyo
*.pyd
*.venv/
venv/
env/
*.env
# Node.js dependencies (frontend folder was excluded, but keeping this rule for reference)
frontend/node_modules/
frontend/.svelte-kit/
frontend/.turbo/
frontend/.vite/
frontend/build/
# API and Backend specific exclusions
api/.env
api/__pycache__/
api/*.sqlite3
# Install scripts and temporary files
install/tmp/
install/*.bak
# VM and Container-specific exclusions
vm/tmp/
vm/*.qcow2
vm/*.img
vm/*.vmdk
vm/*.iso
vm/*.bak
# Miscellaneous temporary or unnecessary files
*.bak
*.swp
*.swo
*.swn
*.tmp
*.backup
# JSON configuration backups
json/*.bak
json/*.tmp
json/.vscode/
# Ignore compiled binaries or packaged artifacts
*.exe
*.dll
*.bin
*.deb
*.rpm
*.tar.gz
*.zip
*.tgz
# Ignore repository metadata or Git itself
.git/
.gitignore
.vscode/settings.json

16
.vscode/.editorconfig vendored
View File

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

View File

@ -2,8 +2,7 @@
"recommendations": [
"bmalehorn.shell-syntax",
"timonwong.shellcheck",
"foxundermoon.shell-format",
"editorconfig.editorconfig"
"foxundermoon.shell-format"
],
"unwantedRecommendations": []
}

11
.vscode/settings.json vendored
View File

@ -1,11 +0,0 @@
{
"files.associations": {
"*.func": "shellscript"
},
"files.eol": "\n",
"files.insertFinalNewline": true,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
<div align="center">
<img src="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo.png" height="100px" />
<img src="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/images/logo.png" height="100px" />
</div>
<h2><div align="center">Exploring the Scripts and Steps Involved in an Application LXC Installation</div></h2>

View File

@ -1,7 +1,7 @@
<div align="center">
<p align="center">
<a href="#">
<img src="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo.png" height="100px" />
<img src="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/images/logo.png" height="100px" />
</a>
</p>
</div>
@ -13,16 +13,16 @@
<a href="https://helper-scripts.com">
<img src="https://img.shields.io/badge/Website-4c9b3f?style=for-the-badge&logo=github&logoColor=white" alt="Website" />
</a>
<a href="https://discord.gg/jsYVk5JBxq">
<a href="https://discord.gg/UHrpNWGwkH">
<img src="https://img.shields.io/badge/Discord-7289da?style=for-the-badge&logo=discord&logoColor=white" alt="Discord" />
</a>
<a href="https://ko-fi.com/community_scripts">
<img src="https://img.shields.io/badge/Support-FF5F5F?style=for-the-badge&logo=ko-fi&logoColor=white" alt="Donate" />
<img src="https://img.shields.io/badge/Donate-FF5F5F?style=for-the-badge&logo=ko-fi&logoColor=white" alt="Donate" />
</a>
<a href="https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/CONTRIBUTING.md">
<a href="https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTING.md">
<img src="https://img.shields.io/badge/Contribute-ff4785?style=for-the-badge&logo=git&logoColor=white" alt="Contribute" />
</a>
<a href="https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/USER_SUBMITTED_GUIDES.md">
<a href="https://github.com/community-scripts/ProxmoxVE/blob/main/USER_SUBMITTED_GUIDES.md">
<img src="https://img.shields.io/badge/Guides-0077b5?style=for-the-badge&logo=read-the-docs&logoColor=white" alt="Guides" />
</a>
<a href="https://github.com/community-scripts/ProxmoxVE/blob/main/CHANGELOG.md">
@ -82,7 +82,7 @@ We appreciate any contributions to the project—whether it's bug reports, featu
Join our community for support:
- **Discord**: Join our [Proxmox Helper Scripts Discord server](https://discord.gg/jsYVk5JBxq) for real-time support.
- **Discord**: Join our [Proxmox Helper Scripts Discord server](https://discord.gg/UHrpNWGwkH) for real-time support.
- **GitHub Discussions**: [Ask questions or report issues](https://github.com/community-scripts/ProxmoxVE/discussions).
## 🤝 Report a Bug or Feature Request
@ -91,16 +91,6 @@ If you encounter any issues or have suggestions for improvement, file a new issu
---
## ⭐ Star History
<a href="https://star-history.com/#community-scripts/ProxmoxVE&Date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date" />
</picture>
</a>
## 📜 License
This project is licensed under the [MIT License](LICENSE).

View File

@ -3,7 +3,6 @@ This project currently supports the following versions of Proxmox VE:
| Version | Supported |
| ------- | ------------------ |
| 8.4.x | :white_check_mark: |
| 8.3.x | :white_check_mark: |
| 8.2.x | :white_check_mark: |
| 8.1.x | :white_check_mark: |
@ -14,7 +13,7 @@ This project currently supports the following versions of Proxmox VE:
## Reporting a Vulnerability
Security vulnerabilities shouldnt be reported publicly to prevent potential exploitation. Instead, please report any vulnerabilities privately by reaching out directly to us. You can either join our [Discord server](https://discord.gg/jsYVk5JBxq) and send a direct message to a maintainer or contact us via email at contact@community-scripts.org. Be sure to include a detailed description of the vulnerability and the steps to reproduce it. Thank you for helping us keep our project secure!
Security vulnerabilities shouldnt be reported publicly to prevent potential exploitation. Instead, please report any vulnerabilities privately by reaching out directly to us. You can either join our [Discord server](https://discord.gg/UHrpNWGwkH) and send a direct message to a maintainer or contact us via email at contact@community-scripts.org. Be sure to include a detailed description of the vulnerability and the steps to reproduce it. Thank you for helping us keep our project secure!
Once a vulnerability has been reported, the project maintainers will review it and acknowledge the report within 7 business days. We will then work to address the vulnerability and provide a fix as soon as possible. Depending on the severity of the issue, a patch may be released immediately or included in the next scheduled update.

View File

@ -1,6 +1,6 @@
<div align="center">
<a href="#">
<img src="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo.png" height="100px" />
<img src="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/images/logo.png" height="100px" />
</a>
</div>
<h2 align="center">User Submitted Guides </h2>

View File

@ -1,5 +0,0 @@
MONGO_USER=
MONGO_PASSWORD=
MONGO_IP=
MONGO_PORT=
MONGO_DATABASE=

View File

@ -1,23 +0,0 @@
module proxmox-api
go 1.23.2
require (
github.com/gorilla/mux v1.8.1
github.com/joho/godotenv v1.5.1
github.com/rs/cors v1.11.1
go.mongodb.org/mongo-driver v1.17.2
)
require (
github.com/golang/snappy v0.0.4 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/montanaflynn/stats v0.7.1 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
golang.org/x/crypto v0.35.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/text v0.22.0 // indirect
)

View File

@ -1,56 +0,0 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver v1.17.2 h1:gvZyk8352qSfzyZ2UMWcpDpMSGEr1eqE4T793SqyhzM=
go.mongodb.org/mongo-driver v1.17.2/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -1,450 +0,0 @@
// Copyright (c) 2021-2025 community-scripts ORG
// Author: Michel Roegl-Brunner (michelroegl-brunner)
// License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"strconv"
"time"
"github.com/gorilla/mux"
"github.com/joho/godotenv"
"github.com/rs/cors"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var client *mongo.Client
var collection *mongo.Collection
func loadEnv() {
if err := godotenv.Load(); err != nil {
log.Fatal("Error loading .env file")
}
}
// DataModel represents a single document in MongoDB
type DataModel struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
CT_TYPE uint `json:"ct_type" bson:"ct_type"`
DISK_SIZE float32 `json:"disk_size" bson:"disk_size"`
CORE_COUNT uint `json:"core_count" bson:"core_count"`
RAM_SIZE uint `json:"ram_size" bson:"ram_size"`
OS_TYPE string `json:"os_type" bson:"os_type"`
OS_VERSION string `json:"os_version" bson:"os_version"`
DISABLEIP6 string `json:"disableip6" bson:"disableip6"`
NSAPP string `json:"nsapp" bson:"nsapp"`
METHOD string `json:"method" bson:"method"`
CreatedAt time.Time `json:"created_at" bson:"created_at"`
PVEVERSION string `json:"pve_version" bson:"pve_version"`
STATUS string `json:"status" bson:"status"`
RANDOM_ID string `json:"random_id" bson:"random_id"`
TYPE string `json:"type" bson:"type"`
ERROR string `json:"error" bson:"error"`
}
type StatusModel struct {
RANDOM_ID string `json:"random_id" bson:"random_id"`
ERROR string `json:"error" bson:"error"`
STATUS string `json:"status" bson:"status"`
}
type CountResponse struct {
TotalEntries int64 `json:"total_entries"`
StatusCount map[string]int64 `json:"status_count"`
NSAPPCount map[string]int64 `json:"nsapp_count"`
}
// ConnectDatabase initializes the MongoDB connection
func ConnectDatabase() {
loadEnv()
mongoURI := fmt.Sprintf("mongodb://%s:%s@%s:%s",
os.Getenv("MONGO_USER"),
os.Getenv("MONGO_PASSWORD"),
os.Getenv("MONGO_IP"),
os.Getenv("MONGO_PORT"))
database := os.Getenv("MONGO_DATABASE")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
var err error
client, err = mongo.Connect(ctx, options.Client().ApplyURI(mongoURI))
if err != nil {
log.Fatal("Failed to connect to MongoDB!", err)
}
collection = client.Database(database).Collection("data_models")
fmt.Println("Connected to MongoDB on 10.10.10.18")
}
// UploadJSON handles API requests and stores data as a document in MongoDB
func UploadJSON(w http.ResponseWriter, r *http.Request) {
var input DataModel
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
input.CreatedAt = time.Now()
_, err := collection.InsertOne(context.Background(), input)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
log.Println("Received data:", input)
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(map[string]string{"message": "Data saved successfully"})
}
// UpdateStatus updates the status of a record based on RANDOM_ID
func UpdateStatus(w http.ResponseWriter, r *http.Request) {
var input StatusModel
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
filter := bson.M{"random_id": input.RANDOM_ID}
update := bson.M{"$set": bson.M{"status": input.STATUS, "error": input.ERROR}}
_, err := collection.UpdateOne(context.Background(), filter, update)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
log.Println("Updated data:", input)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"message": "Record updated successfully"})
}
// GetDataJSON fetches all data from MongoDB
func GetDataJSON(w http.ResponseWriter, r *http.Request) {
var records []DataModel
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
cursor, err := collection.Find(ctx, bson.M{})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer cursor.Close(ctx)
for cursor.Next(ctx) {
var record DataModel
if err := cursor.Decode(&record); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
records = append(records, record)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(records)
}
func GetPaginatedData(w http.ResponseWriter, r *http.Request) {
page, _ := strconv.Atoi(r.URL.Query().Get("page"))
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
if page < 1 {
page = 1
}
if limit < 1 {
limit = 10
}
skip := (page - 1) * limit
var records []DataModel
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
options := options.Find().SetSkip(int64(skip)).SetLimit(int64(limit))
cursor, err := collection.Find(ctx, bson.M{}, options)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer cursor.Close(ctx)
for cursor.Next(ctx) {
var record DataModel
if err := cursor.Decode(&record); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
records = append(records, record)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(records)
}
func GetSummary(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
totalCount, err := collection.CountDocuments(ctx, bson.M{})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
statusCount := make(map[string]int64)
nsappCount := make(map[string]int64)
pipeline := []bson.M{
{"$group": bson.M{"_id": "$status", "count": bson.M{"$sum": 1}}},
}
cursor, err := collection.Aggregate(ctx, pipeline)
if err == nil {
for cursor.Next(ctx) {
var result struct {
ID string `bson:"_id"`
Count int64 `bson:"count"`
}
if err := cursor.Decode(&result); err == nil {
statusCount[result.ID] = result.Count
}
}
}
pipeline = []bson.M{
{"$group": bson.M{"_id": "$nsapp", "count": bson.M{"$sum": 1}}},
}
cursor, err = collection.Aggregate(ctx, pipeline)
if err == nil {
for cursor.Next(ctx) {
var result struct {
ID string `bson:"_id"`
Count int64 `bson:"count"`
}
if err := cursor.Decode(&result); err == nil {
nsappCount[result.ID] = result.Count
}
}
}
response := CountResponse{
TotalEntries: totalCount,
StatusCount: statusCount,
NSAPPCount: nsappCount,
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}
func GetByNsapp(w http.ResponseWriter, r *http.Request) {
nsapp := r.URL.Query().Get("nsapp")
var records []DataModel
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
cursor, err := collection.Find(ctx, bson.M{"nsapp": nsapp})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer cursor.Close(ctx)
for cursor.Next(ctx) {
var record DataModel
if err := cursor.Decode(&record); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
records = append(records, record)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(records)
}
func GetByDateRange(w http.ResponseWriter, r *http.Request) {
startDate := r.URL.Query().Get("start_date")
endDate := r.URL.Query().Get("end_date")
if startDate == "" || endDate == "" {
http.Error(w, "Both start_date and end_date are required", http.StatusBadRequest)
return
}
start, err := time.Parse("2006-01-02T15:04:05.999999+00:00", startDate+"T00:00:00+00:00")
if err != nil {
http.Error(w, "Invalid start_date format", http.StatusBadRequest)
return
}
end, err := time.Parse("2006-01-02T15:04:05.999999+00:00", endDate+"T23:59:59+00:00")
if err != nil {
http.Error(w, "Invalid end_date format", http.StatusBadRequest)
return
}
var records []DataModel
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
cursor, err := collection.Find(ctx, bson.M{
"created_at": bson.M{
"$gte": start,
"$lte": end,
},
})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer cursor.Close(ctx)
for cursor.Next(ctx) {
var record DataModel
if err := cursor.Decode(&record); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
records = append(records, record)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(records)
}
func GetByStatus(w http.ResponseWriter, r *http.Request) {
status := r.URL.Query().Get("status")
var records []DataModel
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
cursor, err := collection.Find(ctx, bson.M{"status": status})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer cursor.Close(ctx)
for cursor.Next(ctx) {
var record DataModel
if err := cursor.Decode(&record); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
records = append(records, record)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(records)
}
func GetByOS(w http.ResponseWriter, r *http.Request) {
osType := r.URL.Query().Get("os_type")
osVersion := r.URL.Query().Get("os_version")
var records []DataModel
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
cursor, err := collection.Find(ctx, bson.M{"os_type": osType, "os_version": osVersion})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer cursor.Close(ctx)
for cursor.Next(ctx) {
var record DataModel
if err := cursor.Decode(&record); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
records = append(records, record)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(records)
}
func GetErrors(w http.ResponseWriter, r *http.Request) {
errorCount := make(map[string]int)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
cursor, err := collection.Find(ctx, bson.M{"error": bson.M{"$ne": ""}})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer cursor.Close(ctx)
for cursor.Next(ctx) {
var record DataModel
if err := cursor.Decode(&record); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if record.ERROR != "" {
errorCount[record.ERROR]++
}
}
type ErrorCountResponse struct {
Error string `json:"error"`
Count int `json:"count"`
}
var errorCounts []ErrorCountResponse
for err, count := range errorCount {
errorCounts = append(errorCounts, ErrorCountResponse{
Error: err,
Count: count,
})
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(struct {
ErrorCounts []ErrorCountResponse `json:"error_counts"`
}{
ErrorCounts: errorCounts,
})
}
func main() {
ConnectDatabase()
router := mux.NewRouter()
router.HandleFunc("/upload", UploadJSON).Methods("POST")
router.HandleFunc("/upload/updatestatus", UpdateStatus).Methods("POST")
router.HandleFunc("/data/json", GetDataJSON).Methods("GET")
router.HandleFunc("/data/paginated", GetPaginatedData).Methods("GET")
router.HandleFunc("/data/summary", GetSummary).Methods("GET")
router.HandleFunc("/data/nsapp", GetByNsapp).Methods("GET")
router.HandleFunc("/data/date", GetByDateRange).Methods("GET")
router.HandleFunc("/data/status", GetByStatus).Methods("GET")
router.HandleFunc("/data/os", GetByOS).Methods("GET")
router.HandleFunc("/data/errors", GetErrors).Methods("GET")
c := cors.New(cors.Options{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST"},
AllowedHeaders: []string{"Content-Type", "Authorization"},
AllowCredentials: true,
})
handler := c.Handler(router)
fmt.Println("Server running on port 8080")
log.Fatal(http.ListenAndServe(":8080", handler))
}

View File

@ -1,20 +1,25 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: jkrgr0
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://docs.2fauth.app/
# App Default Values
APP="2FAuth"
var_tags="${var_tags:-2fa;authenticator}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-2}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
TAGS="2fa;authenticator"
var_cpu="1"
var_ram="512"
var_disk="2"
var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -31,37 +36,22 @@ function update_script() {
fi
# Crawling the new version and checking whether an update is required
RELEASE=$(curl -fsSL https://api.github.com/repos/Bubka/2FAuth/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
RELEASE=$(curl -s https://api.github.com/repos/Bubka/2FAuth/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
if [[ "${RELEASE}" != "$(cat /opt/2fauth_version.txt)" ]] || [[ ! -f /opt/2fauth_version.txt ]]; then
msg_info "Updating $APP to ${RELEASE}"
$STD apt-get update
$STD apt-get -y upgrade
apt-get update &>/dev/null
apt-get -y upgrade &>/dev/null
# Creating Backup
msg_info "Creating Backup"
mv "/opt/2fauth" "/opt/2fauth-backup"
if ! dpkg -l | grep -q 'php8.3'; then
cp /etc/nginx/conf.d/2fauth.conf /etc/nginx/conf.d/2fauth.conf.bak
fi
msg_ok "Backup Created"
# Upgrade PHP
if ! dpkg -l | grep -q 'php8.3'; then
$STD apt-get install -y \
lsb-release \
gpg
curl -fsSL https://packages.sury.org/php/apt.gpg | gpg --dearmor -o /usr/share/keyrings/deb.sury.org-php.gpg
echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list
$STD apt-get update
$STD apt-get install -y php8.3-{bcmath,common,ctype,curl,fileinfo,fpm,gd,mbstring,mysql,xml,cli,intl}
sed -i 's/php8.2/php8.3/g' /etc/nginx/conf.d/2fauth.conf
fi
# Execute Update
curl -fsSL -o "${RELEASE}.zip" "https://github.com/Bubka/2FAuth/archive/refs/tags/${RELEASE}.zip"
wget -q "https://github.com/Bubka/2FAuth/archive/refs/tags/${RELEASE}.zip"
unzip -q "${RELEASE}.zip"
mv "2FAuth-${RELEASE//v/}/" "/opt/2fauth"
mv "2FAuth-${RELEASE//v}/" "/opt/2fauth"
mv "/opt/2fauth-backup/.env" "/opt/2fauth/.env"
mv "/opt/2fauth-backup/storage" "/opt/2fauth/storage"
cd "/opt/2fauth" || return
@ -70,18 +60,13 @@ function update_script() {
chmod -R 755 "/opt/2fauth"
export COMPOSER_ALLOW_SUPERUSER=1
$STD composer install --no-dev --prefer-source
composer install --no-dev --prefer-source &>/dev/null
php artisan 2fauth:install
$STD systemctl restart nginx
# Cleaning up
msg_info "Cleaning Up"
rm -rf "v${RELEASE}.zip"
if dpkg -l | grep -q 'php8.2'; then
$STD apt-get remove --purge -y php8.2*
fi
$STD apt-get -y autoremove
$STD apt-get -y autoclean
msg_ok "Cleanup Completed"

113
ct/5etools.sh Normal file
View File

@ -0,0 +1,113 @@
#!/usr/bin/env bash
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: TheRealVira
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://5e.tools/
# App Default Values
APP="5etools"
var_tags="wiki"
var_cpu="1"
var_ram="512"
var_disk="13"
var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
# Check if installation is present | -f for file, -d for folder
if [[ ! -d "/opt/${APP}" ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
RELEASE=$(curl -s https://api.github.com/repos/5etools-mirror-3/5etools-src/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f "/opt/${APP}_version.txt" ]]; then
# Crawling the new version and checking whether an update is required
msg_info "Updating System"
apt-get update &>/dev/null
apt-get -y upgrade &>/dev/null
msg_ok "Updated System"
# Execute Update
msg_info "Updating base 5etools"
cd /opt
wget -q "https://github.com/5etools-mirror-3/5etools-src/archive/refs/tags/${RELEASE}.zip"
unzip -q "${RELEASE}.zip"
mv "/opt/${APP}/img" "/opt/img-backup"
rm -rf "/opt/${APP}"
mv "${APP}-src-${RELEASE:1}" "/opt/${APP}"
mv "/opt/img-backup" "/opt/${APP}/img"
cd /opt/5etools
$STD npm install
$STD npm run build
cd ~
echo "${RELEASE}" >"/opt/${APP}_version.txt"
chown -R www-data: "/opt/${APP}"
chmod -R 755 "/opt/${APP}"
msg_ok "Updated base 5etools"
# Cleaning up
msg_info "Cleaning Up"
rm -rf /opt/${RELEASE}.zip
$STD apt-get -y autoremove
$STD apt-get -y autoclean
msg_ok "Cleanup Completed"
else
msg_ok "No update required. Base ${APP} is already at ${RELEASE}"
fi
IMG_RELEASE=$(curl -s https://api.github.com/repos/5etools-mirror-2/5etools-img/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
if [[ "${IMG_RELEASE}" != "$(cat /opt/${APP}_IMG_version.txt)" ]] || [[ ! -f "/opt/${APP}_IMG_version.txt" ]]; then
# Crawling the new version and checking whether an update is required
msg_info "Updating System"
apt-get update &>/dev/null
apt-get -y upgrade &>/dev/null
msg_ok "Updated System"
# Execute Update
msg_info "Updating 5etools images"
curl -sSL "https://github.com/5etools-mirror-2/5etools-img/archive/refs/tags/${IMG_RELEASE}.zip" > "${IMG_RELEASE}.zip"
unzip -q "${IMG_RELEASE}.zip"
rm -rf "/opt/${APP}/img"
mv "${APP}-img-${IMG_RELEASE:1}" "/opt/${APP}/img"
echo "${IMG_RELEASE}" >"/opt/${APP}_IMG_version.txt"
chown -R www-data: "/opt/${APP}"
chmod -R 755 "/opt/${APP}"
msg_ok "Updating 5etools images"
# Cleaning up
msg_info "Cleaning Up"
rm -rf /opt/${RELEASE}.zip
rm -rf ${IMG_RELEASE}.zip
$STD apt-get -y autoremove
$STD apt-get -y autoclean
msg_ok "Cleanup Completed"
else
msg_ok "No update required. ${APP} images are already at ${IMG_RELEASE}"
fi
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"

View File

@ -1,10 +1,11 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://actualbudget.org/
# App Default Values
APP="Actual Budget"
var_tags="finance"
var_cpu="2"
@ -14,47 +15,47 @@ var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/actualbudget ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
NODE_VERSION="22"
install_node_and_modules
RELEASE=$(curl -fsSL https://api.github.com/repos/actualbudget/actual/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
if [[ -f /opt/actualbudget-data/config.json ]]; then
if [[ ! -f /opt/actualbudget_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/actualbudget_version.txt)" ]]; then
msg_info "Stopping ${APP}"
systemctl stop actualbudget
msg_ok "${APP} Stopped"
msg_info "Updating ${APP} to ${RELEASE}"
$STD npm update -g @actual-app/sync-server
echo "${RELEASE}" >/opt/actualbudget_version.txt
msg_ok "Updated ${APP} to ${RELEASE}"
msg_info "Starting ${APP}"
systemctl start actualbudget
msg_ok "Restarted ${APP}"
else
msg_info "${APP} is already up to date"
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/actualbudget ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
else
msg_info "Old Installation Found, you need to migrate your data and recreate to a new container"
msg_info "Please follow the instructions on the ${APP} website to migrate your data"
msg_info "https://actualbudget.org/docs/backup-restore/backup"
exit 1
fi
exit
if ! command -v jq >/dev/null 2>&1; then
echo "Installing jq..."
apt-get install -y jq >/dev/null 2>&1
echo "Installed jq..."
fi
msg_info "Updating ${APP}"
systemctl stop actualbudget
RELEASE=$(curl -s https://api.github.com/repos/actualbudget/actual-server/tags | jq --raw-output '.[0].name')
TEMPD="$(mktemp -d)"
cd "${TEMPD}"
wget -q https://codeload.github.com/actualbudget/actual-server/legacy.tar.gz/refs/tags/${RELEASE} -O - | tar -xz
mv /opt/actualbudget /opt/actualbudget_bak
mkdir -p /opt/actualbudget/
mv actualbudget-actual-server-*/* /opt/actualbudget/
mv /opt/actualbudget_bak/.env /opt/actualbudget
mv /opt/actualbudget_bak/server-files /opt/actualbudget/server-files
cd /opt/actualbudget
yarn install &>/dev/null
systemctl start actualbudget
msg_ok "Successfully Updated ${APP} to ${RELEASE}"
rm -rf "${TEMPD}"
rm -rf /opt/actualbudget_bak
exit
}
start
@ -64,4 +65,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}https://${IP}:5006${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5006${CL}"

View File

@ -1,20 +1,25 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://adguard.com/
# App Default Values
APP="Adguard"
var_tags="${var_tags:-adblock}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-2}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="adblock"
var_cpu="1"
var_ram="512"
var_disk="2"
var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -38,4 +43,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}:3000${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"

View File

@ -1,20 +1,25 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: MickLesk (Canbiz)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://adventurelog.app/
# App Default Values
APP="AdventureLog"
var_tags="${var_tags:-traveling}"
var_disk="${var_disk:-7}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="traveling"
var_disk="7"
var_cpu="2"
var_ram="2048"
var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -27,7 +32,7 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
RELEASE=$(curl -fsSL https://api.github.com/repos/seanmorley15/AdventureLog/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
RELEASE=$(curl -s https://api.github.com/repos/seanmorley15/AdventureLog/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
msg_info "Stopping Services"
systemctl stop adventurelog-backend
@ -36,22 +41,22 @@ function update_script() {
msg_info "Updating ${APP} to ${RELEASE}"
mv /opt/adventurelog/ /opt/adventurelog-backup/
curl -fsSL -o /opt/v${RELEASE}.zip "https://github.com/seanmorley15/AdventureLog/archive/refs/tags/v${RELEASE}.zip"
wget -qO /opt/v${RELEASE}.zip "https://github.com/seanmorley15/AdventureLog/archive/refs/tags/v${RELEASE}.zip"
unzip -q /opt/v${RELEASE}.zip -d /opt/
mv /opt/AdventureLog-${RELEASE} /opt/adventurelog
mv /opt/adventurelog-backup/backend/server/.env /opt/adventurelog/backend/server/.env
mv /opt/adventurelog-backup/backend/server/media /opt/adventurelog/backend/server/media
cd /opt/adventurelog/backend/server
$STD pip install --upgrade pip
$STD pip install -r requirements.txt
$STD python3 manage.py collectstatic --noinput
$STD python3 manage.py migrate
pip install --upgrade pip &>/dev/null
pip install -r requirements.txt &>/dev/null
python3 manage.py collectstatic --noinput &>/dev/null
python3 manage.py migrate &>/dev/null
mv /opt/adventurelog-backup/frontend/.env /opt/adventurelog/frontend/.env
cd /opt/adventurelog/frontend
$STD pnpm install
$STD pnpm run build
pnpm install &>/dev/null
pnpm run build &>/dev/null
echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated ${APP}"
@ -78,4 +83,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}:3000${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"

View File

@ -1,20 +1,25 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.ispyconnect.com/
# App Default Values
APP="AgentDVR"
var_tags="${var_tags:-dvr}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}"
var_os="${var_os:-ubuntu}"
var_version="${var_version:-22.04}"
var_unprivileged="${var_unprivileged:-0}"
var_tags="dvr"
var_cpu="2"
var_ram="2048"
var_disk="8"
var_os="ubuntu"
var_version="22.04"
var_unprivileged="0"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -27,7 +32,7 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "Currently we don't provide an update function for this ${APP}."
msg_error "There is currently no update path available."
exit
}

View File

@ -1,46 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://adguardhome.com/
APP="Alpine-AdGuard"
var_tags="${var_tags:-alpine;adblock}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-1}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
msg_info "Updating Alpine Packages"
$STD apk -U upgrade
msg_ok "Updated Alpine Packages"
msg_info "Updating AdGuard Home"
$STD /opt/AdGuardHome/AdGuardHome --update
msg_ok "Updated AdGuard Home"
msg_info "Restarting AdGuard Home"
$STD rc-service adguardhome restart
msg_ok "Restarted AdGuard Home"
exit 0
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"

View File

@ -1,89 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Slaviša Arežina (tremor021)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/bitmagnet-io/bitmagnet
APP="Alpine-bitmagnet"
var_tags="${var_tags:-alpine;torrent}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-3}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
if [[ ! -d /opt/bitmagnet ]]; then
msg_error "No ${APP} Installation Found!"
exit 1
fi
RELEASE=$(curl -fsSL https://api.github.com/repos/bitmagnet-io/bitmagnet/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
if [ "${RELEASE}" != "$(cat /opt/bitmagnet_version.txt)" ] || [ ! -f /opt/bitmagnet_version.txt ]; then
msg_info "Backing up database"
rm -f /tmp/backup.sql
$STD sudo -u postgres pg_dump \
--column-inserts \
--data-only \
--on-conflict-do-nothing \
--rows-per-insert=1000 \
--table=metadata_sources \
--table=content \
--table=content_attributes \
--table=content_collections \
--table=content_collections_content \
--table=torrent_sources \
--table=torrents \
--table=torrent_files \
--table=torrent_hints \
--table=torrent_contents \
--table=torrent_tags \
--table=torrents_torrent_sources \
--table=key_values \
bitmagnet \
>/tmp/backup.sql
mv /tmp/backup.sql /opt/
msg_ok "Database backed up"
msg_info "Updating ${APP} from $(cat /opt/bitmagnet_version.txt) to ${RELEASE}"
$STD apk -U upgrade
$STD service bitmagnet stop
[ -f /opt/bitmagnet/.env ] && cp /opt/bitmagnet/.env /opt/
[ -f /opt/bitmagnet/config.yml ] && cp /opt/bitmagnet/config.yml /opt/
rm -rf /opt/bitmagnet/*
temp_file=$(mktemp)
curl -fsSL "https://github.com/bitmagnet-io/bitmagnet/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file"
tar zxf "$temp_file" --strip-components=1 -C /opt/bitmagnet
cd /opt/bitmagnet
VREL=v$RELEASE
$STD go build -ldflags "-s -w -X github.com/bitmagnet-io/bitmagnet/internal/version.GitTag=$VREL"
chmod +x bitmagnet
[ -f "/opt/.env" ] && cp "/opt/.env" /opt/bitmagnet/
[ -f "/opt/config.yml" ] && cp "/opt/config.yml" /opt/bitmagnet/
rm -f "$temp_file"
echo "${RELEASE}" >/opt/bitmagnet_version.txt
$STD service bitmagnet start
msg_ok "Updated Successfully"
else
msg_ok "No update required. ${APP} is already at ${RELEASE}"
fi
exit 0
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following IP:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3333${CL}"

View File

@ -1,20 +1,24 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.docker.com/
# App Default Values
APP="Alpine-Docker"
var_tags="${var_tags:-docker;alpine}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-2}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="docker;alpine"
var_cpu="1"
var_ram="1024"
var_disk="2"
var_os="alpine"
var_version="3.20"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -36,7 +40,7 @@ function update_script() {
header_info
case $CHOICE in
1)
$STD apk -U upgrade
apk update && apk upgrade
exit
;;
esac

View File

@ -1,62 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Slaviša Arežina (tremor021)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/TwiN/gatus
APP="Alpine-gatus"
var_tags="${var_tags:-alpine;monitoring}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-3}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
if [[ ! -d /opt/gatus ]]; then
msg_error "No ${APP} Installation Found!"
exit 1
fi
RELEASE=$(curl -s https://api.github.com/repos/TwiN/gatus/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
if [ "${RELEASE}" != "$(cat /opt/gatus_version.txt)" ] || [ ! -f /opt/gatus_version.txt ]; then
msg_info "Updating ${APP} LXC"
$STD apk -U upgrade
$STD service gatus stop
mv /opt/gatus/config/config.yaml /opt
rm -rf /opt/gatus/*
temp_file=$(mktemp)
curl -fsSL "https://github.com/TwiN/gatus/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file"
tar zxf "$temp_file" --strip-components=1 -C /opt/gatus
cd /opt/gatus
$STD go mod tidy
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o gatus .
setcap CAP_NET_RAW+ep gatus
mv /opt/config.yaml config
rm -f "$temp_file"
echo "${RELEASE}" >/opt/gatus_version.txt
$STD service gatus start
msg_ok "Updated Successfully"
else
msg_ok "No update required. ${APP} is already at ${RELEASE}"
fi
exit 0
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following IP:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"

View File

@ -1,44 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://gitea.io
APP="Alpine-Gitea"
var_tags="${var_tags:-alpine;git}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-1}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
msg_info "Updating Alpine Packages"
$STD apk -U upgrade
msg_ok "Updated Alpine Packages"
msg_info "Updating Gitea"
apk upgrade gitea
msg_ok "Updated Gitea"
msg_info "Restarting Gitea"
rc-service gitea restart
msg_ok "Restarted Gitea"
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"

View File

@ -1,20 +1,24 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://grafana.com/
# App Default Values
APP="Alpine-Grafana"
var_tags="${var_tags:-alpine;monitoring}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-1}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="alpine;monitoring"
var_cpu="1"
var_ram="256"
var_disk="1"
var_os="alpine"
var_version="3.20"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -39,7 +43,7 @@ function update_script() {
header_info
case $CHOICE in
1)
$STD apk -U upgrade
apk update && apk upgrade
exit
;;
2)

View File

@ -1,58 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: nicedevil007 (NiceDevil)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://it-tools.tech/
APP="Alpine-IT-Tools"
var_tags="${var_tags:-alpine;development}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-0.5}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [ ! -d /usr/share/nginx/html ]; then
msg_error "No ${APP} Installation Found!"
exit 1
fi
RELEASE=$(curl -fsSL https://api.github.com/repos/CorentinTh/it-tools/releases/latest | grep '"tag_name":' | cut -d '"' -f4)
if [ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ] || [ ! -f /opt/${APP}_version.txt ]; then
DOWNLOAD_URL="https://github.com/CorentinTh/it-tools/releases/download/${RELEASE}/it-tools-${RELEASE#v}.zip"
msg_info "Updating ${APP} LXC"
curl -fsSL -o it-tools.zip "$DOWNLOAD_URL"
mkdir -p /usr/share/nginx/html
rm -rf /usr/share/nginx/html/*
unzip -q it-tools.zip -d /tmp/it-tools
cp -r /tmp/it-tools/dist/* /usr/share/nginx/html
rm -rf /tmp/it-tools
rm -f it-tools.zip
msg_ok "Updated Successfully"
else
msg_ok "No update required. ${APP} is already at ${RELEASE}"
fi
exit 0
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following IP:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"

View File

@ -1,58 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://komo.do
APP="Alpine-Komodo"
var_tags="${var_tags:-docker,alpine}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-10}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
[[ -d /opt/komodo ]] || {
msg_error "No ${APP} Installation Found!"
exit 1
}
msg_info "Updating ${APP}"
COMPOSE_FILE=$(find /opt/komodo -maxdepth 1 -type f -name '*.compose.yaml' ! -name 'compose.env' | head -n1)
if [[ -z "$COMPOSE_FILE" ]]; then
msg_error "No valid compose file found in /opt/komodo!"
exit 1
fi
COMPOSE_BASENAME=$(basename "$COMPOSE_FILE")
BACKUP_FILE="/opt/komodo/${COMPOSE_BASENAME}.bak_$(date +%Y%m%d_%H%M%S)"
cp "$COMPOSE_FILE" "$BACKUP_FILE" || {
msg_error "Failed to create backup of ${COMPOSE_BASENAME}!"
exit 1
}
GITHUB_URL="https://raw.githubusercontent.com/moghtech/komodo/main/compose/${COMPOSE_BASENAME}"
if ! curl -fsSL "$GITHUB_URL" -o "$COMPOSE_FILE"; then
msg_error "Failed to download ${COMPOSE_BASENAME} from GitHub!"
mv "$BACKUP_FILE" "$COMPOSE_FILE"
exit 1
fi
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env up -d
msg_ok "Updated ${APP}"
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9120${CL}"

View File

@ -1,45 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://mariadb.org
APP="Alpine-MariaDB"
var_tags="${var_tags:-alpine;database}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-1}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
msg_info "Updating Alpine Packages"
$STD apk -U upgrade
msg_ok "Updated Alpine Packages"
msg_info "Updating MariaDB"
$STD apk upgrade mariadb mariadb-client
msg_ok "Updated MariaDB"
msg_info "Restarting MariaDB"
$STD rc-service mariadb restart
msg_ok "Restarted MariaDB"
exit 0
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following IP:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}${IP}:3306${CL}"

View File

@ -1,20 +1,24 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://nextcloud.com/
# App Default Values
APP="Alpine-Nextcloud"
var_tags="${var_tags:-alpine;cloud}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-2}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="alpine;cloud"
var_cpu="2"
var_ram="1024"
var_disk="2"
var_os="alpine"
var_version="3.20"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -28,10 +32,10 @@ function update_script() {
apk add -q newt
fi
while true; do
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SUPPORT" --radiolist --cancel-button Exit-Script "Spacebar = Select" 11 58 3 \
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SUPPORT" --radiolist --cancel-button Exit-Script "Spacebar = Select" 11 58 3 \
"1" "Nextcloud Login Credentials" ON \
"2" "Renew Self-signed Certificate" OFF \
3>&1 1>&2 2>&3)
3>&1 1>&2 2>&3)
exit_status=$?
if [ $exit_status == 1 ]; then
clear
@ -44,7 +48,7 @@ function update_script() {
exit
;;
2)
openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout /etc/ssl/private/nextcloud-selfsigned.key -out /etc/ssl/certs/nextcloud-selfsigned.crt -subj "/C=US/O=Nextcloud/OU=Domain Control Validated/CN=nextcloud.local" >/dev/null 2>&1
openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout /etc/ssl/private/nextcloud-selfsigned.key -out /etc/ssl/certs/nextcloud-selfsigned.crt -subj "/C=US/O=Nextcloud/OU=Domain Control Validated/CN=nextcloud.local" > /dev/null 2>&1
rc-service nginx restart
exit
;;
@ -58,4 +62,4 @@ description
msg_ok "Completed Successfully!\n"
echo -e "${APP} should be reachable by going to the following URL.
${BL}https://${IP}${CL} \n"
${BL}https://${IP}${CL} \n"

View File

@ -1,49 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://nodered.org
APP="Alpine-Node-RED"
var_tags="${var_tags:-alpine;automation}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-1}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
msg_info "Updating Alpine Packages"
$STD apk -U upgrade
msg_ok "Updated Alpine Packages"
msg_info "Updating Node.js and npm"
$STD apk upgrade nodejs npm
msg_ok "Updated Node.js and npm"
msg_info "Updating Node-RED"
$STD npm install -g --unsafe-perm node-red
msg_ok "Updated Node-RED"
msg_info "Restarting Node-RED"
$STD rc-service nodered restart
msg_ok "Restarted Node-RED"
exit 0
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:1880${CL}"

View File

@ -1,45 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://postgresql.org/
APP="Alpine-PostgreSQL"
var_tags="${var_tags:-alpine;database}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-1}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
msg_info "Updating Alpine Packages"
$STD apk -U upgrade
msg_ok "Updated Alpine Packages"
msg_info "Updating PostgreSQL"
$STD apk upgrade postgresql postgresql-contrib
msg_ok "Updated PostgreSQL"
msg_info "Restarting PostgreSQL"
$STD rc-service postgresql restart
msg_ok "Restarted PostgreSQL"
exit 0
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following IP:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}${IP}:5432${CL}"

View File

@ -1,45 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://prometheus.io/
APP="Alpine-Prometheus"
var_tags="${var_tags:-alpine;monitoring}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-1}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
msg_info "Updating Alpine Packages"
$STD apk -U upgrade
msg_ok "Updated Alpine Packages"
msg_info "Updating Prometheus"
$STD apk upgrade prometheus
msg_ok "Updated Prometheus"
msg_info "Restarting Prometheus"
$STD rc-service prometheus restart
msg_ok "Restarted Prometheus"
exit 0
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9090${CL}"

View File

@ -1,54 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Slaviša Arežina (tremor021)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/rclone/rclone
APP="Alpine-rclone"
var_tags="${var_tags:-alpine;backup}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-1}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [ ! -d /opt/rclone ]; then
msg_error "No ${APP} Installation Found!"
exit 1
fi
RELEASE=$(curl -s https://api.github.com/repos/rclone/rclone/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
if [ "${RELEASE}" != "$(cat /opt/rclone_version.txt)" ] || [ ! -f /opt/rclone_version.txt ]; then
msg_info "Updating ${APP} LXC"
temp_file=$(mktemp)
curl -fsSL "https://github.com/rclone/rclone/releases/download/v${RELEASE}/rclone-v${RELEASE}-linux-amd64.zip" -o "$temp_file"
$STD unzip -o "$temp_file" '*/**' -d /opt/rclone
rm -f "$temp_file"
echo "${RELEASE}" >/opt/rclone_version.txt
msg_ok "Updated Successfully"
else
msg_ok "No update required. ${APP} is already at ${RELEASE}"
fi
exit 0
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following IP:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"

View File

@ -1,72 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://redis.io/
APP="Alpine-Redis"
var_tags="${var_tags:-alpine;database}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-1}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
if ! apk -e info newt >/dev/null 2>&1; then
apk add -q newt
fi
LXCIP=$(ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1)
while true; do
CHOICE=$(
whiptail --backtitle "Proxmox VE Helper Scripts" --title "Redis Management" --menu "Select option" 11 58 3 \
"1" "Update Redis" \
"2" "Allow 0.0.0.0 for listening" \
"3" "Allow only ${LXCIP} for listening" 3>&2 2>&1 1>&3
)
exit_status=$?
if [ $exit_status == 1 ]; then
clear
exit-script
fi
header_info
case $CHOICE in
1)
msg_info "Updating Redis"
apk update && apk upgrade redis
rc-service redis restart
msg_ok "Redis updated successfully!"
exit
;;
2)
msg_info "Setting Redis to listen on all interfaces"
sed -i 's/^bind .*/bind 0.0.0.0/' /etc/redis.conf
rc-service redis restart
msg_ok "Redis now listens on all interfaces!"
exit
;;
3)
msg_info "Setting Redis to listen only on ${LXCIP}"
sed -i "s/^bind .*/bind ${LXCIP}/" /etc/redis.conf
rc-service redis restart
msg_ok "Redis now listens only on ${LXCIP}!"
exit
;;
esac
done
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${APP} should be reachable on port 6379.
${BL}redis-cli -h ${IP} -p 6379${CL} \n"

View File

@ -1,69 +0,0 @@
#!/usr/bin/env bash
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Slaviša Arežina (tremor021)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/steveiliop56/tinyauth
APP="Alpine-tinyauth"
var_tags="${var_tags:-alpine;auth}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-3}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
if [[ ! -d /opt/tinyauth ]]; then
msg_error "No ${APP} Installation Found!"
exit 1
fi
msg_info "Updating Alpine Packages"
$STD apk -U upgrade
msg_ok "Updated Alpine Packages"
msg_info "Updating tinyauth"
RELEASE=$(curl -s https://api.github.com/repos/steveiliop56/tinyauth/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
if [ "${RELEASE}" != "$(cat /opt/tinyauth_version.txt)" ] || [ ! -f /opt/tinyauth_version.txt ]; then
$STD service tinyauth stop
temp_file=$(mktemp)
cp /opt/tinyauth/.env /opt
rm -rf /opt/tinyauth
mkdir -p /opt/tinyauth
curl -fsSL "https://github.com/steveiliop56/tinyauth/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file"
tar -xzf "$temp_file" -C /opt/tinyauth --strip-components=1
cd /opt/tinyauth/frontend
$STD bun install
$STD bun run build
mv dist /opt/tinyauth/internal/assets/
cd /opt/tinyauth
$STD go mod download
CGO_ENABLED=0 go build -ldflags "-s -w"
cp /opt/.env /opt/tinyauth
echo "${RELEASE}" >/opt/tinyauth_version.txt
rm -f "$temp_file"
msg_info "Restarting tinyauth"
$STD service tinyauth start
msg_ok "Restarted tinyauth"
msg_ok "Updated tinyauth"
else
msg_ok "No update required. ${APP} is already at ${RELEASE}"
fi
exit 0
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"

View File

@ -1,41 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://alpinelinux.org/
APP="Alpine-Traefik"
var_tags="${var_tags:-os;alpine}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-1}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
msg_info "Updating Alpine Packages"
$STD apk -U upgrade
msg_ok "Updated Alpine Packages"
msg_info "Upgrading traefik from edge"
$STD apk add traefik --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community
msg_ok "Upgraded traefik"
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} WebUI Access (if configured) - using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080/dashboard${CL}"

View File

@ -1,45 +0,0 @@
#!/usr/bin/env bash
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Slaviša Arežina (tremor021)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://transmissionbt.com/
APP="Alpine-Transmission"
var_tags="${var_tags:-alpine;torrent}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-1}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
msg_info "Updating Alpine Packages"
$STD apk -U upgrade
msg_ok "Updated Alpine Packages"
msg_info "Updating Transmission"
$STD apk upgrade transmission-daemon
msg_ok "Updated Transmission"
msg_info "Restarting Transmission"
$STD rc-service transmission-daemon restart
msg_ok "Restarted Transmission"
exit 1
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9091${CL}"

View File

@ -1,20 +1,24 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/dani-garcia/vaultwarden
# App Default Values
APP="Alpine-Vaultwarden"
var_tags="${var_tags:-alpine;vault}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-0.5}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="alpine;vault"
var_cpu="1"
var_ram="256"
var_disk="0.3"
var_os="alpine"
var_version="3.20"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -37,15 +41,14 @@ function update_script() {
header_info
case $CHOICE in
1)
$STD apk -U upgrade
rc-service vaultwarden restart -q
apk update && apk upgrade && rc-service vaultwarden restart -q
exit
;;
2)
if NEWTOKEN=$(whiptail --backtitle "Proxmox VE Helper Scripts" --passwordbox "Setup your ADMIN_TOKEN (make it strong)" 10 58 3>&1 1>&2 2>&3); then
if [[ -z "$NEWTOKEN" ]]; then exit-script; fi
if ! command -v argon2 >/dev/null 2>&1; then apk add argon2 &>/dev/null; fi
TOKEN=$(echo -n "${NEWTOKEN}" | argon2 "$(openssl rand -base64 32)" -e -id -k 19456 -t 2 -p 1)
TOKEN=$(echo -n ${NEWTOKEN} | argon2 "$(openssl rand -base64 32)" -e -id -k 19456 -t 2 -p 1)
if [[ ! -f /var/lib/vaultwarden/config.json ]]; then
sed -i "s|export ADMIN_TOKEN=.*|export ADMIN_TOKEN='${TOKEN}'|" /etc/conf.d/vaultwarden
else

View File

@ -1,49 +0,0 @@
#!/usr/bin/env bash
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.wireguard.com/
APP="Alpine-Wireguard"
var_tags="${var_tags:-alpine;vpn}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-1}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
msg_info "Updating Alpine Packages"
$STD apk -U upgrade
msg_ok "Updated Alpine Packages"
msg_info "update wireguard-tools"
$STD apk add --no-cache --upgrade wireguard-tools
msg_ok "wireguard-tools updated"
if [[ -d /etc/wgdashboard/src ]]; then
msg_info "update WGDashboard"
cd /etc/wgdashboard/src
$STD echo "y" | ./wgd.sh update
$STD ./wgd.sh start
msg_ok "WGDashboard updated"
fi
exit 0
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} WGDashboard Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:10086${CL}"

View File

@ -1,20 +1,24 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.zigbee2mqtt.io/
# App Default Values
APP="Alpine-Zigbee2MQTT"
var_tags="${var_tags:-alpine;zigbee;mqtt;smarthome}"
var_disk="${var_disk:-0.3}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-0}"
var_tags="alpine;zigbee;mqtt;smarthome"
var_disk="0.3"
var_cpu="1"
var_ram="256"
var_os="alpine"
var_version="3.20"
var_unprivileged="0"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -36,7 +40,7 @@ function update_script() {
header_info
case $CHOICE in
1)
$STD apk -U upgrade
apk update && apk upgrade
exit
;;
esac

View File

@ -1,34 +1,36 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://alpinelinux.org/
# App Default Values
APP="Alpine"
var_tags="${var_tags:-os;alpine}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-0.5}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="os;alpine"
var_cpu="1"
var_ram="512"
var_disk="0.1"
var_os="alpine"
var_version="3.20"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
function update_script() {
UPD=$(
whiptail --backtitle "Proxmox VE Helper Scripts" --title "SUPPORT" --radiolist --cancel-button Exit-Script "Spacebar = Select" 11 58 1 \
"1" "Check for Alpine Updates" ON \
3>&1 1>&2 2>&3
)
UPD=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SUPPORT" --radiolist --cancel-button Exit-Script "Spacebar = Select" 11 58 1 \
"1" "Check for Alpine Updates" ON \
3>&1 1>&2 2>&3)
header_info
if [ "$UPD" == "1" ]; then
$STD apk -U upgrade
apk update && apk upgrade
exit
fi
}

View File

@ -1,20 +1,26 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://cassandra.apache.org/_/index.html
# App Default Values
APP="Apache-Cassandra"
var_tags="${var_tags:-database;NoSQL}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="database;NoSQL"
var_cpu="1"
var_ram="2048"
var_disk="4"
var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -27,7 +33,7 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "Currently we don't provide an update function for this ${APP}."
msg_error "There is currently no update path available."
exit
}

View File

@ -1,20 +1,25 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://couchdb.apache.org/
# App Default Values
APP="Apache-CouchDB"
var_tags="${var_tags:-database}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-10}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="database"
var_cpu="2"
var_ram="4096"
var_disk="10"
var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -27,7 +32,7 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "Currently we don't provide an update function for this ${APP}."
msg_error "There is currently no update path available."
exit
}
@ -38,4 +43,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}:5984/_utils/${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5984/_utils/${CL}"

View File

@ -1,20 +1,25 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/refs/heads/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Michel Roegl-Brunner (michelroegl-brunner)
# License: | MIT https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://guacamole.apache.org/
#App Default Values
APP="Apache-Guacamole"
var_tags="${var_tags:-webserver;remote}"
var_disk="${var_disk:-4}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-2048}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
TAGS="webserver;remote"
var_disk="4"
var_cpu="1"
var_ram="2048"
var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -27,7 +32,7 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "Currently we don't provide an update function for this ${APP}."
msg_error "Ther is currently no automatic update function for ${APP}."
exit
}
@ -38,4 +43,5 @@ description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080/guacamole${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080/guacamole${CL}"

View File

@ -1,64 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Andy Grunwald (andygrunwald)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/apache/tika/
APP="Apache-Tika"
var_tags="${var_tags:-document}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-10}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/systemd/system/apache-tika.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
RELEASE="$(curl -fsSL https://dlcdn.apache.org/tika/ | grep -oP '(?<=href=")[0-9]+\.[0-9]+\.[0-9]+(?=/")' | sort -V | tail -n1)"
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
msg_info "Stopping ${APP}"
systemctl stop apache-tika
msg_ok "Stopped ${APP}"
msg_info "Updating ${APP} to v${RELEASE}"
cd /opt/apache-tika
curl -fsSL -o tika-server-standard-${RELEASE}.jar "https://dlcdn.apache.org/tika/${RELEASE}/tika-server-standard-${RELEASE}.jar"
mv --force tika-server-standard.jar tika-server-standard-prev-version.jar
mv tika-server-standard-${RELEASE}.jar tika-server-standard.jar
echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated ${APP} to v${RELEASE}"
msg_info "Starting ${APP}"
systemctl start apache-tika
msg_ok "Started ${APP}"
msg_info "Cleaning Up"
rm -rf /opt/apache-tika/tika-server-standard-prev-version.jar
msg_ok "Cleanup Completed"
msg_ok "Updated Successfully"
else
msg_ok "No update required. ${APP} is already at v${RELEASE}"
fi
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9998${CL}"

View File

@ -1,41 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (Canbiz)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://tomcat.apache.org/
APP="Apache-Tomcat"
var_tags="${var_tags:-webserver}"
var_disk="${var_disk:-5}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if ! ls -d /opt/tomcat-* >/dev/null 2>&1; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "Currently we don't provide an update function for this ${APP}."
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"

View File

@ -1,20 +1,25 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://wiki.debian.org/AptCacherNg
# App Default Values
APP="Apt-Cacher-NG"
var_tags="${var_tags:-caching}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-2}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="caching"
var_cpu="1"
var_ram="512"
var_disk="2"
var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -28,8 +33,8 @@ function update_script() {
exit
fi
msg_info "Updating $APP LXC"
$STD apt-get update
$STD apt-get -y upgrade
apt-get update &>/dev/null
apt-get -y upgrade &>/dev/null
msg_ok "Updated $APP LXC"
exit
}
@ -41,4 +46,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}:3142/acng-report.html${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3142/acng-report.html{CL}"

View File

@ -1,20 +1,25 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://archivebox.io/
# App Default Values
APP="ArchiveBox"
var_tags="${var_tags:-archive;bookmark}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="archive;bookmark"
var_cpu="2"
var_ram="1024"
var_disk="8"
var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -52,4 +57,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}:8000/admin/login${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8000/admin/login${CL}"

View File

@ -1,20 +1,25 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://aria2.github.io/
# App Default Values
APP="Aria2"
var_tags="${var_tags:-download-utility}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="download-utility"
var_cpu="2"
var_ram="1024"
var_disk="8"
var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -28,8 +33,8 @@ function update_script() {
exit
fi
msg_info "Updating $APP LXC"
$STD apt-get update
$STD apt-get -y upgrade
apt-get update &>/dev/null
apt-get -y upgrade &>/dev/null
msg_ok "Updated $APP LXC"
exit
}
@ -41,4 +46,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}:6880${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:6880${CL}"

View File

@ -1,35 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://asterisk.org/
APP="Asterisk"
var_tags="${var_tags:-telephone;pbx}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
msg_error "No Update function provided for ${APP} LXC"
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"

View File

@ -1,20 +1,25 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.audiobookshelf.org/
# App Default Values
APP="audiobookshelf"
var_tags="${var_tags:-podcast;audiobook}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="podcast;audiobook"
var_cpu="2"
var_ram="2048"
var_disk="4"
var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -38,4 +43,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}:13378${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:13378${CL}"

View File

@ -1,58 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: thost96 (thost96)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.authelia.com/
APP="Authelia"
TAGS=""
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-2}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
base_settings
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d "/etc/authelia/" ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
RELEASE=$(curl -fsSL https://api.github.com/repos/authelia/authelia/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
if [[ "${RELEASE}" != "$(/usr/bin/authelia -v | awk '{print substr($3, 2, length($2)) }')" ]]; then
msg_info "Updating $APP to ${RELEASE}"
$STD apt-get update
$STD apt-get -y upgrade
curl -fsSL "https://github.com/authelia/authelia/releases/download/${RELEASE}/authelia_${RELEASE}_amd64.deb" -o $(basename "https://github.com/authelia/authelia/releases/download/${RELEASE}/authelia_${RELEASE}_amd64.deb")
$STD dpkg -i "authelia_${RELEASE}_amd64.deb"
msg_info "Cleaning Up"
rm -f "authelia_${RELEASE}_amd64.deb"
$STD apt-get -y autoremove
$STD apt-get -y autoclean
msg_ok "Cleanup Completed"
msg_ok "Updated $APP to ${RELEASE}"
else
msg_ok "No update required. ${APP} is already at ${RELEASE}"
fi
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9091${CL}"

View File

@ -1,20 +1,25 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: remz1337
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://goauthentik.io/
# License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# App Default Values
APP="Authentik"
var_tags="${var_tags:-identity-provider}"
var_disk="${var_disk:-12}"
var_cpu="${var_cpu:-6}"
var_ram="${var_ram:-10240}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="identity-provider"
var_disk="15"
var_cpu="6"
var_ram="8192"
var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -27,15 +32,8 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
RELEASE=$(curl -fsSL https://api.github.com/repos/goauthentik/authentik/releases/latest | grep "tarball_url" | awk '{print substr($2, 2, length($2)-3)}')
RELEASE=$(curl -s https://api.github.com/repos/goauthentik/authentik/releases/latest | grep "tarball_url" | awk '{print substr($2, 2, length($2)-3)}')
if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
NODE_VERSION="22"
PG_VERSION="16"
setup_uv
install_postgresql
install_node_and_modules
install_go
msg_info "Stopping ${APP}"
systemctl stop authentik-server
systemctl stop authentik-worker
@ -43,32 +41,28 @@ function update_script() {
msg_info "Building ${APP} website"
mkdir -p /opt/authentik
curl -fsSL "${RELEASE}" -o "authentik.tar.gz"
wget -qO authentik.tar.gz "${RELEASE}"
tar -xzf authentik.tar.gz -C /opt/authentik --strip-components 1 --overwrite
rm -rf authentik.tar.gz
cd /opt/authentik/website
$STD npm install
$STD npm run build-bundled
npm install &>/dev/null
npm run build-bundled &>/dev/null
cd /opt/authentik/web
$STD npm install
$STD npm run build
npm install &>/dev/null
npm run build &>/dev/null
msg_ok "Built ${APP} website"
msg_info "Building ${APP} server"
msg_info "Installing Python Dependencies"
cd /opt/authentik
go mod download
go build -o /go/authentik ./cmd/server
go build -o /opt/authentik/authentik-server /opt/authentik/cmd/server/
msg_ok "Built ${APP} server"
msg_info "Building Authentik"
cd /opt/authentik
$STD uv sync --frozen --no-install-project --no-dev
uv run python -m lifecycle.migrate
ln -s /opt/authentik/.venv/bin/gunicorn /usr/local/bin/gunicorn
ln -s /opt/authentik/.venv/bin/celery /usr/local/bin/celery
msg_ok "Authentik built"
poetry install --only=main --no-ansi --no-interaction --no-root &>/dev/null
poetry export --without-hashes --without-urls -f requirements.txt --output requirements.txt &>/dev/null
pip install --no-cache-dir -r requirements.txt &>/dev/null
pip install . &>/dev/null
msg_ok "Installed Python Dependencies"
msg_info "Updating ${APP} to v${RELEASE} (Patience)"
cp -r /opt/authentik/authentik/blueprints /opt/authentik/blueprints
bash /opt/authentik/lifecycle/ak migrate &>/dev/null
echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated ${APP} to v${RELEASE}"

View File

@ -1,20 +1,25 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/config_file/misc/build.func)
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://autobrr.com/
# App Default Values
APP="Autobrr"
var_tags="${var_tags:-arr;}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
var_tags="arr;"
var_cpu="2"
var_ram="2048"
var_disk="8"
var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
@ -33,7 +38,7 @@ function update_script() {
msg_info "Updating ${APP} LXC"
rm -rf /usr/local/bin/*
curl -fsSL "$(curl -fsSL https://api.github.com/repos/autobrr/autobrr/releases/latest | grep download | grep linux_x86_64 | cut -d\" -f4)" -o $(basename "$(curl -fsSL https://api.github.com/repos/autobrr/autobrr/releases/latest | grep download | grep linux_x86_64 | cut -d\" -f4)")
wget -q $(curl -s https://api.github.com/repos/autobrr/autobrr/releases/latest | grep download | grep linux_x86_64 | cut -d\" -f4)
tar -C /usr/local/bin -xzf autobrr*.tar.gz
rm -rf autobrr*.tar.gz
msg_ok "Updated ${APP} LXC"
@ -52,4 +57,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}:7474${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:7474${CL}"

View File

@ -1,70 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: bvdberg01
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://sabre.io/baikal/
APP="Baikal"
var_tags="${var_tags:-Dav}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/baikal ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
RELEASE=$(curl -fsSL https://api.github.com/repos/sabre-io/Baikal/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
msg_info "Stopping Service"
systemctl stop apache2
msg_ok "Stopped Service"
msg_info "Updating ${APP} to v${RELEASE}"
cd /opt
curl -fsSL "https://github.com/sabre-io/baikal/releases/download/${RELEASE}/baikal-${RELEASE}.zip" -o $(basename "https://github.com/sabre-io/baikal/releases/download/${RELEASE}/baikal-${RELEASE}.zip")
mv /opt/baikal /opt/baikal-backup
unzip -o -q "baikal-${RELEASE}.zip"
cp -r /opt/baikal-backup/config/baikal.yaml /opt/baikal/config/
cp -r /opt/baikal-backup/Specific/ /opt/baikal/
chown -R www-data:www-data /opt/baikal/
chmod -R 755 /opt/baikal/
echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated $APP to v${RELEASE}"
msg_info "Starting Service"
systemctl start apache2
msg_ok "Started Service"
msg_info "Cleaning up"
rm -rf "/opt/baikal-${RELEASE}.zip"
rm -rf /opt/baikal-backup
msg_ok "Cleaned"
msg_ok "Updated Successfully"
else
msg_ok "No update required. ${APP} is already at v${RELEASE}"
fi
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"

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